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 m.shards[ix]
|
||||
return m.shards[ix].Shard
|
||||
}
|
||||
|
||||
// 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()
|
||||
|
||||
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
|
||||
|
|
|
@ -38,7 +38,7 @@ func NewGatewayShard(m *Manager, id *gateway.Identifier) *gateway.Gateway {
|
|||
|
||||
// ShardState wraps around the Gateway interface to provide additional state.
|
||||
type ShardState struct {
|
||||
Shard
|
||||
Shard Shard
|
||||
// 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
|
||||
// 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.
|
||||
func OpenShards(ctx context.Context, shards []ShardState) error {
|
||||
for i, shard := range shards {
|
||||
if err := shard.Open(ctx); err != nil {
|
||||
if err := shard.Shard.Open(ctx); err != nil {
|
||||
CloseShards(shards)
|
||||
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 {
|
||||
if gw.Opened {
|
||||
if err := gw.Close(); err != nil {
|
||||
if err := gw.Shard.Close(); err != nil {
|
||||
lastError = err
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@ type Closed struct {
|
|||
}
|
||||
|
||||
// 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 {
|
||||
return func(m *shard.Manager, id *gateway.Identifier) (shard.Shard, error) {
|
||||
s := NewCustomShard(m, id)
|
||||
|
|
|
@ -22,29 +22,12 @@ var (
|
|||
MaxFetchGuilds uint = 100
|
||||
)
|
||||
|
||||
// NewShardFunc creates a shard constructor that shares the same handler. The
|
||||
// given opts function is called everytime the State is created. If it doesn't
|
||||
// set a cabinet into the state, then a shared default cabinet is set instead.
|
||||
// NewShardFunc creates a shard constructor with its own state registry and
|
||||
// handlers. The given opts function is called everytime the State is created.
|
||||
// The user should initialize handlers and intents in the opts function.
|
||||
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) {
|
||||
state := NewFromSession(session.NewCustomShard(m, id), 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
|
||||
return NewFromSession(session.NewCustomShard(m, id), defaultstore.New()), nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue