diff --git a/v1/core/dispatcher.go b/v1/core/dispatcher.go index de5833e..0b66f3b 100644 --- a/v1/core/dispatcher.go +++ b/v1/core/dispatcher.go @@ -27,9 +27,9 @@ type EventIsolation interface { } type FSMStorage interface { - Get(ctx context.Context, userID int) (state.Snapshot, error) + Get(ctx context.Context, scope isolation.Scope) (state.Snapshot, error) Put(ctx context.Context, state state.Snapshot) error - Delete(ctx context.Context, userID int) error + Delete(ctx context.Context, scope isolation.Scope) error } type UpdateHandler interface { @@ -157,13 +157,13 @@ func (d *Dispatcher) handleUpdates(ch <-chan model.Update) { func (d *Dispatcher) handleUpdate(ctx context.Context, upd model.Update) { var st *state.Context - snapshot, err := d.fsmStorage.Get(ctx, int(upd.UserID)) + snapshot, err := d.fsmStorage.Get(ctx, isolation.Scope{UserID: upd.UserID, ChatID: upd.ChatID}) if err != nil && !errors.Is(err, state.ErrStateNotFound) { log.Error().Err(err).Send() return } if errors.Is(err, state.ErrStateNotFound) { - st = state.New(int(upd.UserID)) + st = state.New(isolation.Scope{UserID: upd.UserID, ChatID: upd.ChatID}) } else { st = state.Restore(snapshot) } @@ -177,7 +177,7 @@ func (d *Dispatcher) handleUpdate(ctx context.Context, upd model.Update) { st = c.State() if st.State() == state.ClearState { - if err := d.fsmStorage.Delete(ctx, int(upd.UserID)); err != nil { + if err := d.fsmStorage.Delete(ctx, isolation.Scope{UserID: upd.UserID, ChatID: upd.ChatID}); err != nil { log.Error().Err(err).Send() return } diff --git a/v1/state/memory/memory.go b/v1/state/memory/memory.go index 22ab55f..2a27171 100644 --- a/v1/state/memory/memory.go +++ b/v1/state/memory/memory.go @@ -19,6 +19,11 @@ type EventIsolation struct { ttl time.Duration } +type fsmKey struct { + userID int64 + chatID int64 +} + type eventIsolationKey struct { userID int chatID int @@ -34,8 +39,11 @@ func NewFSMStorage() *FSMStorage { return &FSMStorage{} } -func (f *FSMStorage) Get(_ context.Context, userID int) (state.Snapshot, error) { - st, ok := f.m.Load(userID) +func (f *FSMStorage) Get(_ context.Context, scope isolation.Scope) (state.Snapshot, error) { + st, ok := f.m.Load(fsmKey{ + userID: scope.UserID, + chatID: scope.ChatID, + }) if !ok { return state.Snapshot{}, state.ErrStateNotFound } @@ -44,12 +52,18 @@ func (f *FSMStorage) Get(_ context.Context, userID int) (state.Snapshot, error) } func (f *FSMStorage) Put(_ context.Context, snapshot state.Snapshot) error { - f.m.Store(snapshot.ID, snapshot) + f.m.Store(fsmKey{ + userID: snapshot.Scope.UserID, + chatID: snapshot.Scope.ChatID, + }, snapshot) return nil } -func (f *FSMStorage) Delete(_ context.Context, userID int) error { - f.m.Delete(userID) +func (f *FSMStorage) Delete(_ context.Context, scope isolation.Scope) error { + f.m.Delete(fsmKey{ + userID: scope.UserID, + chatID: scope.ChatID, + }) return nil } diff --git a/v1/state/state.go b/v1/state/state.go index 5d14af2..a71bff8 100644 --- a/v1/state/state.go +++ b/v1/state/state.go @@ -3,8 +3,7 @@ package state import ( "encoding/json" "fmt" - - "github.com/rs/zerolog/log" + "github.com/abelith/gomax/v1/isolation" ) var ( @@ -32,13 +31,13 @@ func (JSONCodec) Unmarshal(d []byte, v any) error { } type Snapshot struct { - ID int `json:"id"` + Scope isolation.Scope `json:"id"` State State `json:"state"` Data map[string][]byte `json:"data"` } type Context struct { - id int + scope isolation.Scope state State data map[string][]byte codec Codec @@ -48,9 +47,9 @@ type Option func(*Context) func WithCodec(c Codec) Option { return func(sc *Context) { sc.codec = c } } -func New(id int, opts ...Option) *Context { +func New(scope isolation.Scope, opts ...Option) *Context { sc := &Context{ - id: id, + scope: scope, data: make(map[string][]byte), codec: JSONCodec{}, } @@ -61,7 +60,7 @@ func New(id int, opts ...Option) *Context { } func Restore(s Snapshot, opts ...Option) *Context { - sc := New(s.ID, opts...) + sc := New(s.Scope, opts...) sc.state = s.State for k, v := range s.Data { sc.data[k] = v @@ -74,15 +73,10 @@ func (sc *Context) Snapshot() Snapshot { for k, v := range sc.data { data[k] = v } - return Snapshot{ID: sc.id, State: sc.state, Data: data} + return Snapshot{Scope: sc.scope, State: sc.state, Data: data} } func (sc *Context) Set(state State) { - log.Debug(). - Int("user_id", sc.id). - Str("from", string(sc.state)). - Str("to", string(state)). - Msg("fsm state transition") sc.state = state }