Skip to content
This repository was archived by the owner on Mar 14, 2024. It is now read-only.

Commit 207465f

Browse files
committed
Refactor 'evented data' so that it is the saga that is evented, rather than the data.
This is in preparation for #10, which requires separation of the event handling and the data instance.
1 parent 8bd1fca commit 207465f

File tree

7 files changed

+44
-36
lines changed

7 files changed

+44
-36
lines changed

examples/banking/account/account.go

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,6 @@ func (a *Account) InstanceDescription() string {
2020
)
2121
}
2222

23-
// ApplyEvent updates the data to reflect the fact that ev has occurred.
24-
func (a *Account) ApplyEvent(env ax.Envelope) {
25-
switch ev := env.Message.(type) {
26-
case *messages.AccountOpened:
27-
a.AccountId = ev.AccountId
28-
a.Name = ev.Name
29-
a.IsOpen = true
30-
case *messages.AccountCredited:
31-
a.Balance += ev.Cents
32-
case *messages.AccountDebited:
33-
a.Balance -= ev.Cents
34-
}
35-
}
36-
3723
// AggregateRoot is a saga that implements the Account aggregate.
3824
var AggregateRoot saga.Saga = &aggregateRoot{}
3925

@@ -114,3 +100,19 @@ func (aggregateRoot) HandleMessage(
114100

115101
return
116102
}
103+
104+
// ApplyEvent updates the data to reflect the fact that ev has occurred.
105+
func (aggregateRoot) ApplyEvent(d saga.Data, env ax.Envelope) {
106+
acct := d.(*Account)
107+
108+
switch ev := env.Message.(type) {
109+
case *messages.AccountOpened:
110+
acct.AccountId = ev.AccountId
111+
acct.Name = ev.Name
112+
acct.IsOpen = true
113+
case *messages.AccountCredited:
114+
acct.Balance += ev.Cents
115+
case *messages.AccountDebited:
116+
acct.Balance -= ev.Cents
117+
}
118+
}

src/ax/saga/applier.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ import (
77
)
88

99
// Applier is an implementation of ax.Sender that applies published
10-
// events to an EventedData instance.
10+
// events to saga data for evented sagas.
1111
type Applier struct {
12-
Data EventedData
12+
Saga EventedSaga
13+
Data Data
14+
1315
Next ax.Sender
1416
}
1517

@@ -31,7 +33,7 @@ func (s *Applier) PublishEvent(ctx context.Context, m ax.Event) (ax.Envelope, er
3133
return ax.Envelope{}, err
3234
}
3335

34-
s.Data.ApplyEvent(env)
36+
s.Saga.ApplyEvent(s.Data, env)
3537

3638
return env, nil
3739
}

src/ax/saga/data.go

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package saga
22

33
import (
44
"github.com/golang/protobuf/proto"
5-
"github.com/jmalloc/ax/src/ax"
65
)
76

87
// Data is an interface for application-defined data associated with a saga
@@ -20,15 +19,3 @@ type Data interface {
2019
// https://github.com/golang/go/wiki/CodeReviewComments#error-strings
2120
InstanceDescription() string
2221
}
23-
24-
// EventedData is a specialization of Data for sagas that use events to update
25-
// their state. Event-sourced sagas always use EventedData.
26-
type EventedData interface {
27-
Data
28-
29-
// ApplyEvent updates the data to reflect the fact that an event has
30-
// occurred.
31-
//
32-
// It may panic if env.Message does not implement ax.Event.
33-
ApplyEvent(env ax.Envelope)
34-
}

src/ax/saga/eventsourcing/messagestore.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ func applyEvents(
4545
ctx context.Context,
4646
tx persistence.Tx,
4747
ms persistence.MessageStore,
48+
sg saga.EventedSaga,
4849
i *saga.Instance,
4950
) error {
5051
s, err := ms.OpenStream(
@@ -57,8 +58,6 @@ func applyEvents(
5758
return err
5859
}
5960

60-
data := i.Data.(saga.EventedData)
61-
6261
for {
6362
ok, err := s.Next(ctx)
6463
if !ok || err != nil {
@@ -78,7 +77,7 @@ func applyEvents(
7877
)
7978
}
8079

81-
data.ApplyEvent(env)
80+
sg.ApplyEvent(i.Data, env)
8281
i.Revision++
8382
}
8483
}

src/ax/saga/eventsourcing/persister.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,13 @@ func (p *Persister) BeginUpdate(
6262
}
6363
}
6464

65-
if err := applyEvents(ctx, tx, p.MessageStore, &i); err != nil {
65+
if err := applyEvents(
66+
ctx,
67+
tx,
68+
p.MessageStore,
69+
sg.(saga.EventedSaga),
70+
&i,
71+
); err != nil {
6672
return nil, err
6773
}
6874

src/ax/saga/handler.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ func (h *MessageHandler) handleMessage(
155155
panic("unit-of-work contains saga instance with nil data")
156156
}
157157

158-
if d, ok := i.Data.(EventedData); ok {
159-
s = &Applier{d, s}
158+
if es, ok := h.Saga.(EventedSaga); ok {
159+
s = &Applier{es, i.Data, s}
160160
}
161161

162162
if err := h.Saga.HandleMessage(ctx, s, env, i); err != nil {

src/ax/saga/saga.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,15 @@ type Saga interface {
8585
// that could not be found.
8686
HandleNotFound(context.Context, ax.Sender, ax.Envelope) error
8787
}
88+
89+
// EventedSaga is a saga that only mutates its data when an event occurs.
90+
// CRUD sagas may be evented or non-evented, but eventsourced sagas are always
91+
// evented.
92+
type EventedSaga interface {
93+
Saga
94+
95+
// ApplyEvent updates d to reflect the fact that an event has occurred.
96+
//
97+
// It may panic if env.Message does not implement ax.Event.
98+
ApplyEvent(d Data, env ax.Envelope)
99+
}

0 commit comments

Comments
 (0)