Skip to content

Commit

Permalink
check if target account id is same as the actor account id
Browse files Browse the repository at this point in the history
  • Loading branch information
sdil committed Dec 17, 2024
1 parent 51fe420 commit 83cc317
Showing 1 changed file with 121 additions and 118 deletions.
239 changes: 121 additions & 118 deletions example/statestore/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,121 +22,124 @@
* SOFTWARE.
*/

package main

import (
"context"
"errors"
"log"
"os"
"os/signal"
"syscall"
"time"

"github.com/google/uuid"
"google.golang.org/protobuf/proto"

"github.com/tochemey/ego/v3"
samplepb "github.com/tochemey/ego/v3/example/pbs/sample/pb/v1"
"github.com/tochemey/ego/v3/plugins/statestore/memory"
)

func main() {
// create the go context
ctx := context.Background()
// create the event store
durableStore := memory.NewStateStore()
// connect the event store
_ = durableStore.Connect(ctx)
// create the ego engine
engine := ego.NewEngine("Sample", nil, ego.WithStateStore(durableStore))
// start ego engine
_ = engine.Start(ctx)
// create a persistence id
entityID := uuid.NewString()
// create an entity behavior with a given id
behavior := NewAccountBehavior(entityID)
// create an entity
_ = engine.DurableStateEntity(ctx, behavior)

// send some commands to the pid
var command proto.Message
// create an account
command = &samplepb.CreateAccount{
AccountId: entityID,
AccountBalance: 500.00,
}
// send the command to the actor. Please don't ignore the error in production grid code
reply, _, _ := engine.SendCommand(ctx, entityID, command, time.Minute)
account := reply.(*samplepb.Account)
log.Printf("current balance on opening: %v", account.GetAccountBalance())

// send another command to credit the balance
command = &samplepb.CreditAccount{
AccountId: entityID,
Balance: 250,
}

reply, _, _ = engine.SendCommand(ctx, entityID, command, time.Minute)
account = reply.(*samplepb.Account)
log.Printf("current balance after a credit of 250: %v", account.GetAccountBalance())

// capture ctrl+c
interruptSignal := make(chan os.Signal, 1)
signal.Notify(interruptSignal, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
<-interruptSignal

// disconnect the event store
_ = durableStore.Disconnect(ctx)
// stop the actor system
_ = engine.Stop(ctx)
os.Exit(0)
}

// AccountBehavior implements EventSourcedBehavior
type AccountBehavior struct {
id string
}

// make sure that AccountBehavior is a true persistence behavior
var _ ego.DurableStateBehavior = &AccountBehavior{}

// NewAccountBehavior creates an instance of AccountBehavior
func NewAccountBehavior(id string) *AccountBehavior {
return &AccountBehavior{id: id}
}

// ID returns the id
func (a *AccountBehavior) ID() string {
return a.id
}

// InitialState returns the initial state
func (a *AccountBehavior) InitialState() ego.State {
return ego.State(new(samplepb.Account))
}

// HandleCommand handles every command that is sent to the persistent behavior
func (a *AccountBehavior) HandleCommand(_ context.Context, command ego.Command, priorVersion uint64, priorState ego.State) (event ego.State, newVersion uint64, err error) {
switch cmd := command.(type) {
case *samplepb.CreateAccount:
// TODO in production grid app validate the command using the prior state
return &samplepb.Account{
AccountId: a.id,
AccountBalance: cmd.GetAccountBalance(),
}, priorVersion + 1, nil

case *samplepb.CreditAccount:
// TODO in production grid app validate the command using the prior state
account := priorState.(*samplepb.Account)
bal := account.GetAccountBalance() + cmd.GetBalance()

return &samplepb.Account{
AccountId: a.id,
AccountBalance: bal,
}, priorVersion + 1, nil

default:
return nil, 1, errors.New("unhandled command")
}
}
package main

import (
"context"
"errors"
"log"
"os"
"os/signal"
"syscall"
"time"

"github.com/google/uuid"
"google.golang.org/protobuf/proto"

"github.com/tochemey/ego/v3"
samplepb "github.com/tochemey/ego/v3/example/pbs/sample/pb/v1"
"github.com/tochemey/ego/v3/plugins/statestore/memory"
)

func main() {
// create the go context
ctx := context.Background()
// create the event store
durableStore := memory.NewStateStore()
// connect the event store
_ = durableStore.Connect(ctx)
// create the ego engine
engine := ego.NewEngine("Sample", nil, ego.WithStateStore(durableStore))
// start ego engine
_ = engine.Start(ctx)
// create a persistence id
entityID := uuid.NewString()
// create an entity behavior with a given id
behavior := NewAccountBehavior(entityID)
// create an entity
_ = engine.DurableStateEntity(ctx, behavior)

// send some commands to the pid
var command proto.Message
// create an account
command = &samplepb.CreateAccount{
AccountId: entityID,
AccountBalance: 500.00,
}
// send the command to the actor. Please don't ignore the error in production grid code
reply, _, _ := engine.SendCommand(ctx, entityID, command, time.Minute)
account := reply.(*samplepb.Account)
log.Printf("current balance on opening: %v", account.GetAccountBalance())

// send another command to credit the balance
command = &samplepb.CreditAccount{
AccountId: entityID,
Balance: 250,
}

reply, _, _ = engine.SendCommand(ctx, entityID, command, time.Minute)
account = reply.(*samplepb.Account)
log.Printf("current balance after a credit of 250: %v", account.GetAccountBalance())

// capture ctrl+c
interruptSignal := make(chan os.Signal, 1)
signal.Notify(interruptSignal, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
<-interruptSignal

// disconnect the event store
_ = durableStore.Disconnect(ctx)
// stop the actor system
_ = engine.Stop(ctx)
os.Exit(0)
}

// AccountBehavior implements EventSourcedBehavior
type AccountBehavior struct {
id string
}

// make sure that AccountBehavior is a true persistence behavior
var _ ego.DurableStateBehavior = &AccountBehavior{}

// NewAccountBehavior creates an instance of AccountBehavior
func NewAccountBehavior(id string) *AccountBehavior {
return &AccountBehavior{id: id}
}

// ID returns the id
func (a *AccountBehavior) ID() string {
return a.id
}

// InitialState returns the initial state
func (a *AccountBehavior) InitialState() ego.State {
return ego.State(new(samplepb.Account))
}

// HandleCommand handles every command that is sent to the persistent behavior
func (a *AccountBehavior) HandleCommand(_ context.Context, command ego.Command, priorVersion uint64, priorState ego.State) (event ego.State, newVersion uint64, err error) {
switch cmd := command.(type) {
case *samplepb.CreateAccount:
// TODO in production grid app validate the command using the prior state
return &samplepb.Account{
AccountId: a.id,
AccountBalance: cmd.GetAccountBalance(),
}, priorVersion + 1, nil

case *samplepb.CreditAccount:
if cmd.GetAccountId() == a.id {
// TODO in production grid app validate the command using the prior state
account := priorState.(*samplepb.Account)
bal := account.GetAccountBalance() + cmd.GetBalance()

return &samplepb.Account{
AccountId: a.id,
AccountBalance: bal,
}, priorVersion + 1, nil
}
return nil, 0, errors.New("command sent to the wrong entity")

default:
return nil, 0, errors.New("unhandled command")
}
}

0 comments on commit 83cc317

Please sign in to comment.