Skip to content

Commit

Permalink
Merge pull request #133 from dogmatiq/allow-record-after-destroy
Browse files Browse the repository at this point in the history
Allow AggregateCommandScope.Destroy() and RecordEvent() to be called in any order.
  • Loading branch information
jmalloc authored Nov 5, 2020
2 parents 9b07d4c + 7847444 commit fecbfdd
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 30 deletions.
9 changes: 0 additions & 9 deletions engine/controller/aggregate/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,6 @@ func (c *Controller) Handle(
},
)

if len(s.events) == 0 && s.destroyed {
panic(fmt.Sprintf(
"the '%s' aggregate message handler destroyed the '%s' instance without recording an event while handling a %s command",
ident.Name,
id,
message.TypeOf(env.Message),
))
}

if s.exists {
if c.history == nil {
c.history = map[string][]*envelope.Envelope{}
Expand Down
18 changes: 0 additions & 18 deletions engine/controller/aggregate/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,24 +263,6 @@ var _ = Describe("type Controller", func() {
},
))
})

It("panics if the instance is destroyed without recording an event", func() {
handler.HandleCommandFunc = func(
s dogma.AggregateCommandScope,
_ dogma.Message,
) {
s.Destroy()
}

Expect(func() {
ctrl.Handle(
context.Background(),
fact.Ignore,
time.Now(),
command,
)
}).To(Panic())
})
})

It("provides more context to UnexpectedMessage panics from RouteCommandToInstance()", func() {
Expand Down
2 changes: 0 additions & 2 deletions engine/controller/aggregate/scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ type scope struct {
root dogma.AggregateRoot
now time.Time
exists bool
destroyed bool // true if Destroy() returned true at least once
produced message.TypeCollection
command *envelope.Envelope
events []*envelope.Envelope
Expand All @@ -38,7 +37,6 @@ func (s *scope) Destroy() {

s.root = s.config.Handler().New()
s.exists = false
s.destroyed = true

s.observer.Notify(fact.AggregateInstanceDestroyed{
HandlerName: s.config.Identity().Name,
Expand Down
50 changes: 49 additions & 1 deletion engine/controller/aggregate/scope_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,6 @@ var _ = Describe("type scope", func() {
s dogma.AggregateCommandScope,
_ dogma.Message,
) {
s.RecordEvent(MessageE1) // event must be recorded when destroying
s.Destroy()
}

Expand Down Expand Up @@ -291,6 +290,55 @@ var _ = Describe("type scope", func() {
))
})

It("records facts about instance creation and the event if called after Destroy()", func() {
handler.HandleCommandFunc = func(
s dogma.AggregateCommandScope,
_ dogma.Message,
) {
s.Destroy()
s.RecordEvent(MessageE1)
}

now := time.Now()
buf := &fact.Buffer{}
_, err := ctrl.Handle(
context.Background(),
buf,
now,
command,
)

Expect(err).ShouldNot(HaveOccurred())
Expect(buf.Facts()).To(ContainElement(
fact.AggregateInstanceCreated{
HandlerName: "<name>",
Handler: handler,
InstanceID: "<instance>",
Root: &AggregateRoot{},
Envelope: command,
},
))
Expect(buf.Facts()).To(ContainElement(
fact.EventRecordedByAggregate{
HandlerName: "<name>",
Handler: handler,
InstanceID: "<instance>",
Root: &AggregateRoot{},
Envelope: command,
EventEnvelope: command.NewEvent(
"1",
MessageE1,
now,
envelope.Origin{
HandlerName: "<name>",
HandlerType: configkit.AggregateHandlerType,
InstanceID: "<instance>",
},
),
},
))
})

It("panics if the event type is not configured to be produced", func() {
handler.HandleCommandFunc = func(
s dogma.AggregateCommandScope,
Expand Down

0 comments on commit fecbfdd

Please sign in to comment.