feat: added convenient state groups api
This commit is contained in:
1 parent
7bb08f60f3
commit
7a4e34528f
5 files changed
+63
-11
No files matched your search
@@ -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"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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"
|
||||||
@@ -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 {
|
||||||
Reference in new issue
Block a user