mirror of
https://github.com/diamondburned/arikawa.git
synced 2025-12-02 09:47:52 +00:00
shard: Separate state's cabinet, fix return bugs
This commit makes it so that all sharded state.State instances will have its own cabinet store on construction. This ensures that when a State is reconnected, a Ready event won't wipe the cabinet for all other states. This commit also fixes a bug with the Shard() and FromGuildID() getters.
This commit is contained in:
parent
e8131db8df
commit
7f4daccd2d
|
|
@ -155,7 +155,7 @@ func (m *Manager) Shard(ix int) Shard {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.shards[ix]
|
return m.shards[ix].Shard
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromGuildID returns the Shard and the shard ID for the guild with the given
|
// FromGuildID returns the Shard and the shard ID for the guild with the given
|
||||||
|
|
@ -165,7 +165,7 @@ func (m *Manager) FromGuildID(guildID discord.GuildID) (shard Shard, ix int) {
|
||||||
defer m.mutex.RUnlock()
|
defer m.mutex.RUnlock()
|
||||||
|
|
||||||
ix = int(uint64(guildID>>22) % uint64(len(m.shards)))
|
ix = int(uint64(guildID>>22) % uint64(len(m.shards)))
|
||||||
return m.shards[ix], ix
|
return m.shards[ix].Shard, ix
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForEach calls the given function on each shard from first to last. The caller
|
// ForEach calls the given function on each shard from first to last. The caller
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ func NewGatewayShard(m *Manager, id *gateway.Identifier) *gateway.Gateway {
|
||||||
|
|
||||||
// ShardState wraps around the Gateway interface to provide additional state.
|
// ShardState wraps around the Gateway interface to provide additional state.
|
||||||
type ShardState struct {
|
type ShardState struct {
|
||||||
Shard
|
Shard Shard
|
||||||
// This is a bit wasteful: 2 constant pointers are stored here, and they
|
// This is a bit wasteful: 2 constant pointers are stored here, and they
|
||||||
// waste GC cycles. This is unavoidable, however, since the API has to take
|
// waste GC cycles. This is unavoidable, however, since the API has to take
|
||||||
// in a pointer to Identifier, not IdentifyData. This is to ensure rescales
|
// in a pointer to Identifier, not IdentifyData. This is to ensure rescales
|
||||||
|
|
@ -55,7 +55,7 @@ func (state ShardState) ShardID() int {
|
||||||
// OpenShards opens the gateways of the given list of shard states.
|
// OpenShards opens the gateways of the given list of shard states.
|
||||||
func OpenShards(ctx context.Context, shards []ShardState) error {
|
func OpenShards(ctx context.Context, shards []ShardState) error {
|
||||||
for i, shard := range shards {
|
for i, shard := range shards {
|
||||||
if err := shard.Open(ctx); err != nil {
|
if err := shard.Shard.Open(ctx); err != nil {
|
||||||
CloseShards(shards)
|
CloseShards(shards)
|
||||||
return errors.Wrapf(err, "failed to open shard %d/%d", i, len(shards)-1)
|
return errors.Wrapf(err, "failed to open shard %d/%d", i, len(shards)-1)
|
||||||
}
|
}
|
||||||
|
|
@ -73,7 +73,7 @@ func CloseShards(shards []ShardState) error {
|
||||||
|
|
||||||
for i, gw := range shards {
|
for i, gw := range shards {
|
||||||
if gw.Opened {
|
if gw.Opened {
|
||||||
if err := gw.Close(); err != nil {
|
if err := gw.Shard.Close(); err != nil {
|
||||||
lastError = err
|
lastError = err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ type Closed struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewShardFunc creates a shard constructor for a session.
|
// NewShardFunc creates a shard constructor for a session.
|
||||||
// Accessing any shard and adding a handler will add a handler for all shards.
|
|
||||||
func NewShardFunc(f func(m *shard.Manager, s *Session)) shard.NewShardFunc {
|
func NewShardFunc(f func(m *shard.Manager, s *Session)) shard.NewShardFunc {
|
||||||
return func(m *shard.Manager, id *gateway.Identifier) (shard.Shard, error) {
|
return func(m *shard.Manager, id *gateway.Identifier) (shard.Shard, error) {
|
||||||
s := NewCustomShard(m, id)
|
s := NewCustomShard(m, id)
|
||||||
|
|
|
||||||
|
|
@ -22,29 +22,12 @@ var (
|
||||||
MaxFetchGuilds uint = 100
|
MaxFetchGuilds uint = 100
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewShardFunc creates a shard constructor that shares the same handler. The
|
// NewShardFunc creates a shard constructor with its own state registry and
|
||||||
// given opts function is called everytime the State is created. If it doesn't
|
// handlers. The given opts function is called everytime the State is created.
|
||||||
// set a cabinet into the state, then a shared default cabinet is set instead.
|
// The user should initialize handlers and intents in the opts function.
|
||||||
func NewShardFunc(opts func(*shard.Manager, *State)) shard.NewShardFunc {
|
func NewShardFunc(opts func(*shard.Manager, *State)) shard.NewShardFunc {
|
||||||
var once sync.Once
|
|
||||||
var cab *store.Cabinet
|
|
||||||
|
|
||||||
return func(m *shard.Manager, id *gateway.Identifier) (shard.Shard, error) {
|
return func(m *shard.Manager, id *gateway.Identifier) (shard.Shard, error) {
|
||||||
state := NewFromSession(session.NewCustomShard(m, id), nil)
|
return NewFromSession(session.NewCustomShard(m, id), defaultstore.New()), nil
|
||||||
|
|
||||||
if opts != nil {
|
|
||||||
opts(m, state)
|
|
||||||
}
|
|
||||||
|
|
||||||
if state.Cabinet == nil {
|
|
||||||
// Create the cabinet once; use sync.Once so the constructor can be
|
|
||||||
// concurrently safe.
|
|
||||||
once.Do(func() { cab = defaultstore.New() })
|
|
||||||
|
|
||||||
state.Cabinet = cab
|
|
||||||
}
|
|
||||||
|
|
||||||
return state, nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue