Skip to content

Commit ffa04da

Browse files
authored
refactor!: complete refactoring of the code to account for cluster (#80)
* refactor!: complete refactoring of the code to account for cluster * refactor!: add more tests
1 parent e7ede34 commit ffa04da

34 files changed

+650
-619
lines changed

Earthfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ protogen:
1515
--path protos/ego
1616

1717
# save artifact to
18-
SAVE ARTIFACT gen/ego/v2 AS LOCAL egopb
18+
SAVE ARTIFACT gen/ego/v3 AS LOCAL egopb
1919

2020
testprotogen:
2121
# copy the proto files to generate

actor.go

+17-17
Original file line numberDiff line numberDiff line change
@@ -39,23 +39,23 @@ import (
3939
"github.com/tochemey/goakt/v2/actors"
4040
"github.com/tochemey/goakt/v2/goaktpb"
4141

42-
"github.com/tochemey/ego/v2/egopb"
43-
"github.com/tochemey/ego/v2/eventstore"
44-
"github.com/tochemey/ego/v2/eventstream"
45-
"github.com/tochemey/ego/v2/internal/telemetry"
42+
"github.com/tochemey/ego/v3/egopb"
43+
"github.com/tochemey/ego/v3/eventstore"
44+
"github.com/tochemey/ego/v3/eventstream"
45+
"github.com/tochemey/ego/v3/internal/telemetry"
4646
)
4747

4848
var (
4949
eventsTopic = "topic.events.%d"
5050
)
5151

5252
// actor is an event sourced based actor
53-
type actor[T State] struct {
54-
EntityBehavior[T]
53+
type actor struct {
54+
EntityBehavior
5555
// specifies the events store
5656
eventsStore eventstore.EventsStore
5757
// specifies the current state
58-
currentState T
58+
currentState State
5959

6060
eventsCounter *atomic.Uint64
6161
lastCommandTime time.Time
@@ -64,12 +64,12 @@ type actor[T State] struct {
6464
}
6565

6666
// enforce compilation error
67-
var _ actors.Actor = &actor[State]{}
67+
var _ actors.Actor = (*actor)(nil)
6868

6969
// newActor creates an instance of actor provided the eventSourcedHandler and the events store
70-
func newActor[T State](behavior EntityBehavior[T], eventsStore eventstore.EventsStore, eventsStream eventstream.Stream) *actor[T] {
70+
func newActor(behavior EntityBehavior, eventsStore eventstore.EventsStore, eventsStream eventstream.Stream) *actor {
7171
// create an instance of entity and return it
72-
return &actor[T]{
72+
return &actor{
7373
eventsStore: eventsStore,
7474
EntityBehavior: behavior,
7575
eventsCounter: atomic.NewUint64(0),
@@ -80,7 +80,7 @@ func newActor[T State](behavior EntityBehavior[T], eventsStore eventstore.Events
8080

8181
// PreStart pre-starts the actor
8282
// At this stage we connect to the various stores
83-
func (entity *actor[T]) PreStart(ctx context.Context) error {
83+
func (entity *actor) PreStart(ctx context.Context) error {
8484
spanCtx, span := telemetry.SpanContext(ctx, "PreStart")
8585
defer span.End()
8686
entity.mu.Lock()
@@ -98,7 +98,7 @@ func (entity *actor[T]) PreStart(ctx context.Context) error {
9898
}
9999

100100
// Receive processes any message dropped into the actor mailbox.
101-
func (entity *actor[T]) Receive(ctx actors.ReceiveContext) {
101+
func (entity *actor) Receive(ctx actors.ReceiveContext) {
102102
_, span := telemetry.SpanContext(ctx.Context(), "Receive")
103103
defer span.End()
104104

@@ -119,7 +119,7 @@ func (entity *actor[T]) Receive(ctx actors.ReceiveContext) {
119119
}
120120

121121
// PostStop prepares the actor to gracefully shutdown
122-
func (entity *actor[T]) PostStop(ctx context.Context) error {
122+
func (entity *actor) PostStop(ctx context.Context) error {
123123
_, span := telemetry.SpanContext(ctx, "PostStop")
124124
defer span.End()
125125

@@ -131,7 +131,7 @@ func (entity *actor[T]) PostStop(ctx context.Context) error {
131131

132132
// recoverFromSnapshot reset the persistent actor to the latest snapshot in case there is one
133133
// this is vital when the entity actor is restarting.
134-
func (entity *actor[T]) recoverFromSnapshot(ctx context.Context) error {
134+
func (entity *actor) recoverFromSnapshot(ctx context.Context) error {
135135
spanCtx, span := telemetry.SpanContext(ctx, "RecoverFromSnapshot")
136136
defer span.End()
137137

@@ -157,7 +157,7 @@ func (entity *actor[T]) recoverFromSnapshot(ctx context.Context) error {
157157
}
158158

159159
// sendErrorReply sends an error as a reply message
160-
func (entity *actor[T]) sendErrorReply(ctx actors.ReceiveContext, err error) {
160+
func (entity *actor) sendErrorReply(ctx actors.ReceiveContext, err error) {
161161
reply := &egopb.CommandReply{
162162
Reply: &egopb.CommandReply_ErrorReply{
163163
ErrorReply: &egopb.ErrorReply{
@@ -170,7 +170,7 @@ func (entity *actor[T]) sendErrorReply(ctx actors.ReceiveContext, err error) {
170170
}
171171

172172
// getStateAndReply returns the current state of the entity
173-
func (entity *actor[T]) getStateAndReply(ctx actors.ReceiveContext) {
173+
func (entity *actor) getStateAndReply(ctx actors.ReceiveContext) {
174174
latestEvent, err := entity.eventsStore.GetLatestEvent(ctx.Context(), entity.ID())
175175
if err != nil {
176176
entity.sendErrorReply(ctx, err)
@@ -193,7 +193,7 @@ func (entity *actor[T]) getStateAndReply(ctx actors.ReceiveContext) {
193193
}
194194

195195
// processCommandAndReply processes the incoming command
196-
func (entity *actor[T]) processCommandAndReply(ctx actors.ReceiveContext, command Command) {
196+
func (entity *actor) processCommandAndReply(ctx actors.ReceiveContext, command Command) {
197197
goCtx := ctx.Context()
198198
events, err := entity.HandleCommand(goCtx, command, entity.currentState)
199199
if err != nil {

actor_test.go

+11-11
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@ import (
3939
"github.com/tochemey/goakt/v2/log"
4040
"github.com/tochemey/gopack/postgres"
4141

42-
"github.com/tochemey/ego/v2/egopb"
43-
"github.com/tochemey/ego/v2/eventstore/memory"
44-
pgeventstore "github.com/tochemey/ego/v2/eventstore/postgres"
45-
"github.com/tochemey/ego/v2/eventstream"
46-
testpb "github.com/tochemey/ego/v2/test/data/pb/v1"
42+
"github.com/tochemey/ego/v3/egopb"
43+
"github.com/tochemey/ego/v3/eventstore/memory"
44+
pgeventstore "github.com/tochemey/ego/v3/eventstore/postgres"
45+
"github.com/tochemey/ego/v3/eventstream"
46+
testpb "github.com/tochemey/ego/v3/test/data/pb/v3"
4747
)
4848

4949
func TestActor(t *testing.T) {
@@ -76,7 +76,7 @@ func TestActor(t *testing.T) {
7676
eventStream := eventstream.New()
7777

7878
// create the persistence actor using the behavior previously created
79-
actor := newActor[*testpb.Account](behavior, eventStore, eventStream)
79+
actor := newActor(behavior, eventStore, eventStream)
8080
// spawn the actor
8181
pid, _ := actorSystem.Spawn(ctx, behavior.ID(), actor)
8282
require.NotNil(t, pid)
@@ -174,7 +174,7 @@ func TestActor(t *testing.T) {
174174
eventStream := eventstream.New()
175175

176176
// create the persistence actor using the behavior previously created
177-
persistentActor := newActor[*testpb.Account](behavior, eventStore, eventStream)
177+
persistentActor := newActor(behavior, eventStore, eventStream)
178178
// spawn the actor
179179
pid, _ := actorSystem.Spawn(ctx, behavior.ID(), persistentActor)
180180
require.NotNil(t, pid)
@@ -259,7 +259,7 @@ func TestActor(t *testing.T) {
259259
eventStream := eventstream.New()
260260

261261
// create the persistence actor using the behavior previously created
262-
persistentActor := newActor[*testpb.Account](behavior, eventStore, eventStream)
262+
persistentActor := newActor(behavior, eventStore, eventStream)
263263
// spawn the actor
264264
pid, _ := actorSystem.Spawn(ctx, behavior.ID(), persistentActor)
265265
require.NotNil(t, pid)
@@ -340,7 +340,7 @@ func TestActor(t *testing.T) {
340340
eventStream := eventstream.New()
341341

342342
// create the persistence actor using the behavior previously created
343-
persistentActor := newActor[*testpb.Account](behavior, eventStore, eventStream)
343+
persistentActor := newActor(behavior, eventStore, eventStream)
344344
// spawn the actor
345345
pid, err := actorSystem.Spawn(ctx, behavior.ID(), persistentActor)
346346
require.NoError(t, err)
@@ -464,7 +464,7 @@ func TestActor(t *testing.T) {
464464
eventStream := eventstream.New()
465465

466466
// create the persistence actor using the behavior previously created
467-
actor := newActor[*testpb.Account](behavior, eventStore, eventStream)
467+
actor := newActor(behavior, eventStore, eventStream)
468468
// spawn the actor
469469
pid, _ := actorSystem.Spawn(ctx, behavior.ID(), actor)
470470
require.NotNil(t, pid)
@@ -582,7 +582,7 @@ func TestActor(t *testing.T) {
582582
eventStream := eventstream.New()
583583

584584
// create the persistence actor using the behavior previously created
585-
actor := newActor[*testpb.Account](behavior, eventStore, eventStream)
585+
actor := newActor(behavior, eventStore, eventStream)
586586
// spawn the actor
587587
pid, _ := actorSystem.Spawn(ctx, behavior.ID(), actor)
588588
require.NotNil(t, pid)

behavior.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ type Event proto.Message
3535
type State proto.Message
3636

3737
// EntityBehavior defines an event sourced behavior when modeling a CQRS EntityBehavior.
38-
type EntityBehavior[T State] interface {
38+
type EntityBehavior interface {
3939
// ID defines the id that will be used in the event journal.
4040
// This helps track the entity in the events store.
4141
ID() string
4242
// InitialState returns the event sourced actor initial state.
4343
// This is set as the initial state when there are no snapshots found the entity
44-
InitialState() T
44+
InitialState() State
4545
// HandleCommand helps handle commands received by the event sourced actor. The command handlers define how to handle each incoming command,
4646
// which validations must be applied, and finally, which events will be persisted if any. When there is no event to be persisted a nil can
4747
// be returned as a no-op. Command handlers are the meat of the event sourced actor.
@@ -53,8 +53,8 @@ type EntityBehavior[T State] interface {
5353
// Every event emitted are processed one after the other in the same order they were emitted to guarantee consistency.
5454
// It is at the discretion of the application developer to know in which order a given command should return the list of events
5555
// This is really powerful when a command needs to return two events. For instance, an OpenAccount command can result in two events: one is AccountOpened and the second is AccountCredited
56-
HandleCommand(ctx context.Context, command Command, priorState T) (events []Event, err error)
56+
HandleCommand(ctx context.Context, command Command, priorState State) (events []Event, err error)
5757
// HandleEvent handle events emitted by the command handlers. The event handlers are used to mutate the state of the event sourced actor by applying the events to it.
5858
// Event handlers must be pure functions as they will be used when instantiating the event sourced actor and replaying the event journal.
59-
HandleEvent(ctx context.Context, event Event, priorState T) (state T, err error)
59+
HandleEvent(ctx context.Context, event Event, priorState State) (state State, err error)
6060
}

0 commit comments

Comments
 (0)