more
This commit is contained in:
@@ -6,8 +6,13 @@ import (
|
||||
"github.com/gogo/protobuf/proto"
|
||||
)
|
||||
|
||||
type MutationResult[V any] struct {
|
||||
Result V `json:"result"`
|
||||
Mutations []ApplyResult `json:"mutations,omitempty"`
|
||||
}
|
||||
|
||||
type GrainPool[V any] interface {
|
||||
Apply(id uint64, mutation ...proto.Message) (V, error)
|
||||
Apply(id uint64, mutation ...proto.Message) (*MutationResult[V], error)
|
||||
Get(id uint64) (V, error)
|
||||
OwnerHost(id uint64) (Host, bool)
|
||||
Hostname() string
|
||||
|
||||
@@ -9,8 +9,14 @@ import (
|
||||
"github.com/gogo/protobuf/proto"
|
||||
)
|
||||
|
||||
type ApplyResult struct {
|
||||
Type string `json:"type"`
|
||||
Mutation proto.Message `json:"mutation"`
|
||||
Error error `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
type MutationRegistry interface {
|
||||
Apply(grain any, msg ...proto.Message) error
|
||||
Apply(grain any, msg ...proto.Message) ([]ApplyResult, error)
|
||||
RegisterMutations(handlers ...MutationHandler)
|
||||
Create(typeName string) (proto.Message, bool)
|
||||
GetTypeName(msg proto.Message) (string, bool)
|
||||
@@ -145,12 +151,14 @@ func (r *ProtoMutationRegistry) Create(typeName string) (proto.Message, bool) {
|
||||
// Returns updated grain if successful.
|
||||
//
|
||||
// If the mutation is not registered, returns (nil, ErrMutationNotRegistered).
|
||||
func (r *ProtoMutationRegistry) Apply(grain any, msg ...proto.Message) error {
|
||||
func (r *ProtoMutationRegistry) Apply(grain any, msg ...proto.Message) ([]ApplyResult, error) {
|
||||
results := make([]ApplyResult, 0, len(msg))
|
||||
|
||||
if grain == nil {
|
||||
return fmt.Errorf("nil grain")
|
||||
return results, fmt.Errorf("nil grain")
|
||||
}
|
||||
if msg == nil {
|
||||
return fmt.Errorf("nil mutation message")
|
||||
return results, fmt.Errorf("nil mutation message")
|
||||
}
|
||||
|
||||
for _, m := range msg {
|
||||
@@ -159,18 +167,18 @@ func (r *ProtoMutationRegistry) Apply(grain any, msg ...proto.Message) error {
|
||||
entry, ok := r.mutationRegistry[rt]
|
||||
r.mutationRegistryMu.RUnlock()
|
||||
if !ok {
|
||||
return ErrMutationNotRegistered
|
||||
}
|
||||
if err := entry.Handle(grain, m); err != nil {
|
||||
return err
|
||||
results = append(results, ApplyResult{Error: ErrMutationNotRegistered, Type: rt.Name(), Mutation: m})
|
||||
continue
|
||||
}
|
||||
err := entry.Handle(grain, m)
|
||||
results = append(results, ApplyResult{Error: err, Type: rt.Name(), Mutation: m})
|
||||
}
|
||||
|
||||
// if entry.updateTotals {
|
||||
// grain.UpdateTotals()
|
||||
// }
|
||||
|
||||
return nil
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// RegisteredMutations returns metadata for all registered mutations (snapshot).
|
||||
|
||||
@@ -78,7 +78,7 @@ func TestRegisteredMutationBasics(t *testing.T) {
|
||||
// Apply happy path
|
||||
state := &cartState{}
|
||||
add := &messages.AddItem{ItemId: 42, Quantity: 3, Sku: "ABC"}
|
||||
if err := reg.Apply(state, add); err != nil {
|
||||
if _, err := reg.Apply(state, add); err != nil {
|
||||
t.Fatalf("Apply returned error: %v", err)
|
||||
}
|
||||
if state.calls != 1 {
|
||||
@@ -89,17 +89,17 @@ func TestRegisteredMutationBasics(t *testing.T) {
|
||||
}
|
||||
|
||||
// Apply nil grain
|
||||
if err := reg.Apply(nil, add); err == nil {
|
||||
if _, err := reg.Apply(nil, add); err == nil {
|
||||
t.Fatalf("expected error for nil grain")
|
||||
}
|
||||
|
||||
// Apply nil message
|
||||
if err := reg.Apply(state, nil); err == nil {
|
||||
if _, err := reg.Apply(state, nil); err == nil {
|
||||
t.Fatalf("expected error for nil mutation message")
|
||||
}
|
||||
|
||||
// Apply unregistered message
|
||||
if err := reg.Apply(state, &messages.Noop{}); !errors.Is(err, ErrMutationNotRegistered) {
|
||||
if _, err := reg.Apply(state, &messages.Noop{}); !errors.Is(err, ErrMutationNotRegistered) {
|
||||
t.Fatalf("expected ErrMutationNotRegistered, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,13 +371,15 @@ func (p *SimpleGrainPool[V]) getOrClaimGrain(id uint64) (Grain[V], error) {
|
||||
// var ErrNotOwner = fmt.Errorf("not owner")
|
||||
|
||||
// Apply applies a mutation to a grain.
|
||||
func (p *SimpleGrainPool[V]) Apply(id uint64, mutation ...proto.Message) (*V, error) {
|
||||
func (p *SimpleGrainPool[V]) Apply(id uint64, mutation ...proto.Message) (*MutationResult[*V], error) {
|
||||
grain, err := p.getOrClaimGrain(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if applyErr := p.mutationRegistry.Apply(grain, mutation...); applyErr != nil {
|
||||
return nil, applyErr
|
||||
|
||||
mutations, err := p.mutationRegistry.Apply(grain, mutation...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if p.storage != nil {
|
||||
go func() {
|
||||
@@ -386,7 +388,14 @@ func (p *SimpleGrainPool[V]) Apply(id uint64, mutation ...proto.Message) (*V, er
|
||||
}
|
||||
}()
|
||||
}
|
||||
return grain.GetCurrentState()
|
||||
result, err := grain.GetCurrentState()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &MutationResult[*V]{
|
||||
Result: result,
|
||||
Mutations: mutations,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Get returns the current state of a grain.
|
||||
|
||||
Reference in New Issue
Block a user