feat: added convenient state groups api

This commit is contained in:
abelith committed 2026-10-09 11:06:30 +03:00
1 parent 7bb08f60f3
commit 7a4e34528f
5 files changed
+63 -11

No files matched your search

+1 -1
View File
@@ -2,7 +2,7 @@ package context
import ( import (
"context" "context"
"github.com/abelith/gomax/v1/state" "github.com/abelith/gomax/v1/fsm/state"
maxbot "github.com/max-messenger/max-bot-api-client-go/v2" maxbot "github.com/max-messenger/max-bot-api-client-go/v2"
"github.com/max-messenger/max-bot-api-client-go/v2/model" "github.com/max-messenger/max-bot-api-client-go/v2/model"
"time" "time"
+2 -2
View File
@@ -4,9 +4,9 @@ import (
"context" "context"
"errors" "errors"
mcontext "github.com/abelith/gomax/v1/context" mcontext "github.com/abelith/gomax/v1/context"
"github.com/abelith/gomax/v1/fsm/memory"
"github.com/abelith/gomax/v1/fsm/state"
"github.com/abelith/gomax/v1/isolation" "github.com/abelith/gomax/v1/isolation"
"github.com/abelith/gomax/v1/state"
"github.com/abelith/gomax/v1/state/memory"
"github.com/google/uuid" "github.com/google/uuid"
maxbot "github.com/max-messenger/max-bot-api-client-go/v2" maxbot "github.com/max-messenger/max-bot-api-client-go/v2"
"github.com/max-messenger/max-bot-api-client-go/v2/model" "github.com/max-messenger/max-bot-api-client-go/v2/model"
+1 -1
View File
@@ -2,7 +2,7 @@ package filters
import ( import (
mcontext "github.com/abelith/gomax/v1/context" mcontext "github.com/abelith/gomax/v1/context"
"github.com/abelith/gomax/v1/state" "github.com/abelith/gomax/v1/fsm/state"
"github.com/max-messenger/max-bot-api-client-go/v2/model" "github.com/max-messenger/max-bot-api-client-go/v2/model"
"regexp" "regexp"
"strings" "strings"
@@ -2,8 +2,8 @@ package memory
import ( import (
"context" "context"
"github.com/abelith/gomax/v1/fsm/state"
"github.com/abelith/gomax/v1/isolation" "github.com/abelith/gomax/v1/isolation"
"github.com/abelith/gomax/v1/state"
"github.com/google/uuid" "github.com/google/uuid"
"sync" "sync"
"time" "time"
+58 -6
View File
@@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/abelith/gomax/v1/isolation" "github.com/abelith/gomax/v1/isolation"
"strings"
) )
var ( var (
@@ -11,7 +12,15 @@ var (
ErrKeyNotFound = fmt.Errorf("state: key not found") ErrKeyNotFound = fmt.Errorf("state: key not found")
) )
type State string type State struct {
group string
name string
}
type Group struct {
name string
states map[string]*State
}
type Codec interface { type Codec interface {
Marshal(v any) ([]byte, error) Marshal(v any) ([]byte, error)
@@ -30,7 +39,7 @@ func (JSONCodec) Unmarshal(d []byte, v any) error {
type Snapshot struct { type Snapshot struct {
Scope isolation.Scope `json:"id"` Scope isolation.Scope `json:"id"`
State State `json:"state"` State string `json:"state"`
Data map[string][]byte `json:"data"` Data map[string][]byte `json:"data"`
} }
@@ -44,6 +53,49 @@ type Context struct {
type Option func(*Context) type Option func(*Context)
func NewStateGroup(name string) *Group {
return &Group{
name: name,
states: make(map[string]*State),
}
}
func (g *Group) State(name string) State {
state := g.states[name]
if state != nil {
return *state
}
if state = g.states[name]; state != nil {
return *state
}
state = &State{
group: g.name,
name: name,
}
g.states[name] = state
return *state
}
func (s *State) String() string {
return fmt.Sprintf("%s:%s", s.group, s.name)
}
func fromString(s string) State {
pieces := strings.Split(s, ":")
if len(pieces) < 2 {
return State{}
}
return State{
group: pieces[0],
name: pieces[1],
}
}
func WithCodec(c Codec) Option { return func(sc *Context) { sc.codec = c } } func WithCodec(c Codec) Option { return func(sc *Context) { sc.codec = c } }
func New(scope isolation.Scope, opts ...Option) *Context { func New(scope isolation.Scope, opts ...Option) *Context {
@@ -60,7 +112,7 @@ func New(scope isolation.Scope, opts ...Option) *Context {
func Restore(s Snapshot, opts ...Option) *Context { func Restore(s Snapshot, opts ...Option) *Context {
sc := New(s.Scope, opts...) sc := New(s.Scope, opts...)
sc.state = s.State sc.state = fromString(s.State)
for k, v := range s.Data { for k, v := range s.Data {
sc.data[k] = v sc.data[k] = v
} }
@@ -72,7 +124,7 @@ func (sc *Context) Snapshot() Snapshot {
for k, v := range sc.data { for k, v := range sc.data {
data[k] = v data[k] = v
} }
return Snapshot{Scope: sc.scope, State: sc.state, Data: data} return Snapshot{Scope: sc.scope, State: sc.state.String(), Data: data}
} }
func (sc *Context) Set(state State) { func (sc *Context) Set(state State) {
@@ -82,13 +134,13 @@ func (sc *Context) Set(state State) {
func (sc *Context) State() State { return sc.state } func (sc *Context) State() State { return sc.state }
func (sc *Context) Clear() { func (sc *Context) Clear() {
sc.state = "" sc.state = State{}
sc.clear = true sc.clear = true
sc.data = make(map[string][]byte) sc.data = make(map[string][]byte)
} }
func (sc *Context) IsEmpty() bool { func (sc *Context) IsEmpty() bool {
return sc.state == "" && sc.clear return sc.state == State{} && sc.clear
} }
func (sc *Context) Store(key string, val any) error { func (sc *Context) Store(key string, val any) error {