From 04461dd2e564ed9019e217bff84f6f2196e5726f Mon Sep 17 00:00:00 2001 From: James Harris Date: Fri, 6 Nov 2020 06:43:58 +1000 Subject: [PATCH] Pass aggregate root directly to `AggregateMessageHandler.HandleCommand()`. --- assert/common_test.go | 1 + compare/comparator_test.go | 35 +++++-- engine/controller/aggregate/controller.go | 2 +- .../controller/aggregate/controller_test.go | 67 ++++++++++++- engine/controller/aggregate/scope.go | 4 - engine/controller/aggregate/scope_test.go | 95 ++++++++----------- engine/executor_test.go | 1 + go.mod | 2 +- go.sum | 2 + render/renderer_test.go | 13 ++- render/string_test.go | 13 ++- 11 files changed, 160 insertions(+), 75 deletions(-) diff --git a/assert/common_test.go b/assert/common_test.go index b60d097b..26e8569a 100644 --- a/assert/common_test.go +++ b/assert/common_test.go @@ -28,6 +28,7 @@ func newTestApp() ( return "" }, HandleCommandFunc: func( + _ dogma.AggregateRoot, s dogma.AggregateCommandScope, m dogma.Message, ) { diff --git a/compare/comparator_test.go b/compare/comparator_test.go index c997e189..db4d70d4 100644 --- a/compare/comparator_test.go +++ b/compare/comparator_test.go @@ -1,6 +1,7 @@ package compare_test import ( + "github.com/dogmatiq/dogma" . "github.com/dogmatiq/dogma/fixtures" . "github.com/dogmatiq/testkit/compare" . "github.com/onsi/ginkgo" @@ -36,30 +37,50 @@ var _ = Describe("type DefaultComparator", func() { }) Describe("func AggregateRootIsEqual()", func() { - It("returns true if tlues have the same type and value", func() { + It("returns true if the values have the same type and value", func() { Expect(comparator.AggregateRootIsEqual( - &AggregateRoot{Value: ""}, - &AggregateRoot{Value: ""}, + &AggregateRoot{ + AppliedEvents: []dogma.Message{ + MessageA1, + }, + }, + &AggregateRoot{ + AppliedEvents: []dogma.Message{ + MessageA1, + }, + }, )).To(BeTrue()) }) It("returns false if the values have the same type with different values", func() { Expect(comparator.AggregateRootIsEqual( - &AggregateRoot{Value: ""}, - &AggregateRoot{Value: ""}, + &AggregateRoot{ + AppliedEvents: []dogma.Message{ + MessageA1, + }, + }, + &AggregateRoot{ + AppliedEvents: []dogma.Message{ + MessageA2, + }, + }, )).To(BeFalse()) }) It("returns false if the values are different types", func() { Expect(comparator.AggregateRootIsEqual( - &AggregateRoot{Value: ""}, + &AggregateRoot{ + AppliedEvents: []dogma.Message{ + "", + }, + }, &struct{ AggregateRoot }{}, )).To(BeFalse()) }) }) Describe("func ProcessRootIsEqual()", func() { - It("returns true if tlues have the same type and value", func() { + It("returns true if the values have the same type and value", func() { Expect(comparator.ProcessRootIsEqual( &ProcessRoot{Value: ""}, &ProcessRoot{Value: ""}, diff --git a/engine/controller/aggregate/controller.go b/engine/controller/aggregate/controller.go index 06e2f496..ad917a48 100644 --- a/engine/controller/aggregate/controller.go +++ b/engine/controller/aggregate/controller.go @@ -144,7 +144,7 @@ func (c *Controller) Handle( "HandleCommand", env.Message, func() { - handler.HandleCommand(s, env.Message) + handler.HandleCommand(r, s, env.Message) }, ) diff --git a/engine/controller/aggregate/controller_test.go b/engine/controller/aggregate/controller_test.go index 3a3934fb..c734dc1d 100644 --- a/engine/controller/aggregate/controller_test.go +++ b/engine/controller/aggregate/controller_test.go @@ -112,6 +112,7 @@ var _ = Describe("type Controller", func() { It("forwards the message to the handler", func() { called := false handler.HandleCommandFunc = func( + _ dogma.AggregateRoot, _ dogma.AggregateCommandScope, m dogma.Message, ) { @@ -132,6 +133,7 @@ var _ = Describe("type Controller", func() { It("returns the recorded events", func() { handler.HandleCommandFunc = func( + _ dogma.AggregateRoot, s dogma.AggregateCommandScope, _ dogma.Message, ) { @@ -208,6 +210,25 @@ var _ = Describe("type Controller", func() { )) }) + It("passes a new aggregate root", func() { + handler.HandleCommandFunc = func( + r dogma.AggregateRoot, + s dogma.AggregateCommandScope, + _ dogma.Message, + ) { + Expect(r).To(Equal(&AggregateRoot{})) + } + + _, err := ctrl.Handle( + context.Background(), + fact.Ignore, + time.Now(), + command, + ) + + Expect(err).ShouldNot(HaveOccurred()) + }) + It("panics if New() returns nil", func() { handler.NewFunc = func() dogma.AggregateRoot { return nil @@ -227,6 +248,7 @@ var _ = Describe("type Controller", func() { When("the instance exists", func() { BeforeEach(func() { handler.HandleCommandFunc = func( + _ dogma.AggregateRoot, s dogma.AggregateCommandScope, _ dogma.Message, ) { @@ -241,6 +263,8 @@ var _ = Describe("type Controller", func() { ) Expect(err).ShouldNot(HaveOccurred()) + + handler.HandleCommandFunc = nil }) It("records a fact", func() { @@ -258,11 +282,40 @@ var _ = Describe("type Controller", func() { HandlerName: "", Handler: handler, InstanceID: "", - Root: &AggregateRoot{}, - Envelope: command, + Root: &AggregateRoot{ + AppliedEvents: []dogma.Message{ + MessageE1, + }, + }, + Envelope: command, }, )) }) + + It("passes an aggregate root with historical events applied", func() { + handler.HandleCommandFunc = func( + r dogma.AggregateRoot, + s dogma.AggregateCommandScope, + _ dogma.Message, + ) { + Expect(r).To(Equal( + &AggregateRoot{ + AppliedEvents: []dogma.Message{ + MessageE1, + }, + }, + )) + } + + _, err := ctrl.Handle( + context.Background(), + fact.Ignore, + time.Now(), + command, + ) + + Expect(err).ShouldNot(HaveOccurred()) + }) }) It("provides more context to UnexpectedMessage panics from RouteCommandToInstance()", func() { @@ -292,6 +345,7 @@ var _ = Describe("type Controller", func() { It("provides more context to UnexpectedMessage panics from HandleCommand()", func() { handler.HandleCommandFunc = func( + dogma.AggregateRoot, dogma.AggregateCommandScope, dogma.Message, ) { @@ -320,6 +374,7 @@ var _ = Describe("type Controller", func() { It("provides more context to UnexpectedMessage panics from ApplyEvent() when called with new events", func() { handler.HandleCommandFunc = func( + _ dogma.AggregateRoot, s dogma.AggregateCommandScope, _ dogma.Message, ) { @@ -328,7 +383,7 @@ var _ = Describe("type Controller", func() { handler.NewFunc = func() dogma.AggregateRoot { return &AggregateRoot{ - ApplyEventFunc: func(dogma.Message, interface{}) { + ApplyEventFunc: func(dogma.Message) { panic(dogma.UnexpectedMessage) }, } @@ -356,6 +411,7 @@ var _ = Describe("type Controller", func() { It("provides more context to UnexpectedMessage panics from ApplyEvent() when called with historical events", func() { handler.HandleCommandFunc = func( + _ dogma.AggregateRoot, s dogma.AggregateCommandScope, _ dogma.Message, ) { @@ -372,7 +428,7 @@ var _ = Describe("type Controller", func() { handler.HandleCommandFunc = nil handler.NewFunc = func() dogma.AggregateRoot { return &AggregateRoot{ - ApplyEventFunc: func(dogma.Message, interface{}) { + ApplyEventFunc: func(dogma.Message) { panic(dogma.UnexpectedMessage) }, } @@ -402,8 +458,9 @@ var _ = Describe("type Controller", func() { Describe("func Reset()", func() { BeforeEach(func() { handler.HandleCommandFunc = func( + _ dogma.AggregateRoot, s dogma.AggregateCommandScope, - m dogma.Message, + _ dogma.Message, ) { s.RecordEvent(MessageE1) // record event to create the instance } diff --git a/engine/controller/aggregate/scope.go b/engine/controller/aggregate/scope.go index 1e789a43..f61d5696 100644 --- a/engine/controller/aggregate/scope.go +++ b/engine/controller/aggregate/scope.go @@ -47,10 +47,6 @@ func (s *scope) Destroy() { }) } -func (s *scope) Root() dogma.AggregateRoot { - return s.root -} - func (s *scope) RecordEvent(m dogma.Message) { if !s.exists { s.observer.Notify(fact.AggregateInstanceCreated{ diff --git a/engine/controller/aggregate/scope_test.go b/engine/controller/aggregate/scope_test.go index 435dfff2..61e4f77f 100644 --- a/engine/controller/aggregate/scope_test.go +++ b/engine/controller/aggregate/scope_test.go @@ -60,30 +60,10 @@ var _ = Describe("type scope", func() { }) When("the instance does not exist", func() { - Describe("func Root()", func() { - It("returns a new root", func() { - handler.HandleCommandFunc = func( - s dogma.AggregateCommandScope, - _ dogma.Message, - ) { - r := s.Root() - Expect(r).To(Equal(&AggregateRoot{})) - } - - _, err := ctrl.Handle( - context.Background(), - fact.Ignore, - time.Now(), - command, - ) - - Expect(err).ShouldNot(HaveOccurred()) - }) - }) - Describe("func Destroy()", func() { It("does not record a fact", func() { handler.HandleCommandFunc = func( + _ dogma.AggregateRoot, s dogma.AggregateCommandScope, _ dogma.Message, ) { @@ -108,6 +88,7 @@ var _ = Describe("type scope", func() { Describe("func RecordEvent()", func() { It("records facts about instance creation and the event", func() { handler.HandleCommandFunc = func( + _ dogma.AggregateRoot, s dogma.AggregateCommandScope, _ dogma.Message, ) { @@ -129,8 +110,12 @@ var _ = Describe("type scope", func() { HandlerName: "", Handler: handler, InstanceID: "", - Root: &AggregateRoot{}, - Envelope: command, + Root: &AggregateRoot{ + AppliedEvents: []dogma.Message{ + MessageE1, + }, + }, + Envelope: command, }, )) Expect(buf.Facts()).To(ContainElement( @@ -138,8 +123,12 @@ var _ = Describe("type scope", func() { HandlerName: "", Handler: handler, InstanceID: "", - Root: &AggregateRoot{}, - Envelope: command, + Root: &AggregateRoot{ + AppliedEvents: []dogma.Message{ + MessageE1, + }, + }, + Envelope: command, EventEnvelope: command.NewEvent( "1", MessageE1, @@ -159,6 +148,7 @@ var _ = Describe("type scope", func() { When("the instance exists", func() { BeforeEach(func() { handler.HandleCommandFunc = func( + _ dogma.AggregateRoot, s dogma.AggregateCommandScope, _ dogma.Message, ) { @@ -181,29 +171,10 @@ var _ = Describe("type scope", func() { messageIDs.Reset() // reset after setup for a predictable ID. }) - Describe("func Root()", func() { - It("returns the root", func() { - handler.HandleCommandFunc = func( - s dogma.AggregateCommandScope, - _ dogma.Message, - ) { - Expect(s.Root()).To(Equal(&AggregateRoot{})) - } - - _, err := ctrl.Handle( - context.Background(), - fact.Ignore, - time.Now(), - command, - ) - - Expect(err).ShouldNot(HaveOccurred()) - }) - }) - Describe("func Destroy()", func() { It("records a fact", func() { handler.HandleCommandFunc = func( + _ dogma.AggregateRoot, s dogma.AggregateCommandScope, _ dogma.Message, ) { @@ -234,8 +205,9 @@ var _ = Describe("type scope", func() { Describe("func RecordEvent()", func() { BeforeEach(func() { handler.HandleCommandFunc = func( + _ dogma.AggregateRoot, s dogma.AggregateCommandScope, - m dogma.Message, + _ dogma.Message, ) { s.RecordEvent(MessageB1) } @@ -259,8 +231,13 @@ var _ = Describe("type scope", func() { HandlerName: "", Handler: handler, InstanceID: "", - Root: &AggregateRoot{}, - Envelope: command, + Root: &AggregateRoot{ + AppliedEvents: []dogma.Message{ + MessageE1, + MessageB1, + }, + }, + Envelope: command, EventEnvelope: command.NewEvent( "1", MessageB1, @@ -292,6 +269,7 @@ var _ = Describe("type scope", func() { It("records facts about instance creation and the event if called after Destroy()", func() { handler.HandleCommandFunc = func( + _ dogma.AggregateRoot, s dogma.AggregateCommandScope, _ dogma.Message, ) { @@ -314,8 +292,12 @@ var _ = Describe("type scope", func() { HandlerName: "", Handler: handler, InstanceID: "", - Root: &AggregateRoot{}, - Envelope: command, + Root: &AggregateRoot{ + AppliedEvents: []dogma.Message{ + MessageE1, + }, + }, + Envelope: command, }, )) Expect(buf.Facts()).To(ContainElement( @@ -323,8 +305,12 @@ var _ = Describe("type scope", func() { HandlerName: "", Handler: handler, InstanceID: "", - Root: &AggregateRoot{}, - Envelope: command, + Root: &AggregateRoot{ + AppliedEvents: []dogma.Message{ + MessageE1, + }, + }, + Envelope: command, EventEnvelope: command.NewEvent( "1", MessageE1, @@ -341,8 +327,9 @@ var _ = Describe("type scope", func() { It("panics if the event type is not configured to be produced", func() { handler.HandleCommandFunc = func( + _ dogma.AggregateRoot, s dogma.AggregateCommandScope, - m dogma.Message, + _ dogma.Message, ) { s.RecordEvent(MessageZ1) } @@ -363,6 +350,7 @@ var _ = Describe("type scope", func() { It("returns the instance ID", func() { called := false handler.HandleCommandFunc = func( + _ dogma.AggregateRoot, s dogma.AggregateCommandScope, _ dogma.Message, ) { @@ -385,6 +373,7 @@ var _ = Describe("type scope", func() { Describe("func Log()", func() { BeforeEach(func() { handler.HandleCommandFunc = func( + _ dogma.AggregateRoot, s dogma.AggregateCommandScope, _ dogma.Message, ) { diff --git a/engine/executor_test.go b/engine/executor_test.go index 4f4cc771..6aaf7632 100644 --- a/engine/executor_test.go +++ b/engine/executor_test.go @@ -50,6 +50,7 @@ var _ = Describe("type CommandExecutor", func() { It("dispatches to the engine", func() { called := false aggregate.HandleCommandFunc = func( + _ dogma.AggregateRoot, _ dogma.AggregateCommandScope, m dogma.Message, ) { diff --git a/go.mod b/go.mod index fedf0724..98a7942a 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/dogmatiq/configkit v0.8.0 github.com/dogmatiq/cosyne v0.1.0 github.com/dogmatiq/dapper v0.4.0 - github.com/dogmatiq/dogma v0.8.0 + github.com/dogmatiq/dogma v0.9.0 github.com/dogmatiq/iago v0.4.0 github.com/dogmatiq/linger v0.2.1 github.com/onsi/ginkgo v1.14.2 diff --git a/go.sum b/go.sum index 07c714c3..14d42ed6 100644 --- a/go.sum +++ b/go.sum @@ -15,6 +15,8 @@ github.com/dogmatiq/dapper v0.4.0 h1:WshL6xcW56jxkh1XE/x7sXyzxOvjBFjMcxz1jdjwn60 github.com/dogmatiq/dapper v0.4.0/go.mod h1:U32cRxzGYI5owhc/hMKjYLgBTVCdW/s3MdFJHwfDrLQ= github.com/dogmatiq/dogma v0.8.0 h1:ijrlmCZGY6GcQ8Atfil6bXGIHEh/hRQoEnUoqfuZzts= github.com/dogmatiq/dogma v0.8.0/go.mod h1:8TdjQ5jjV2DcCPb/jjHPgSrqU66H6092yMEIF5HGx0g= +github.com/dogmatiq/dogma v0.9.0 h1:PGRUqBPVI76HhkxulEEvzxe+693pq9cfQxJWBCpV730= +github.com/dogmatiq/dogma v0.9.0/go.mod h1:8TdjQ5jjV2DcCPb/jjHPgSrqU66H6092yMEIF5HGx0g= github.com/dogmatiq/iago v0.4.0 h1:57nZqVT34IZxtCZEW/RFif7DNUEjMXgevfr/Mmd0N8I= github.com/dogmatiq/iago v0.4.0/go.mod h1:fishMWBtzYcjgis6d873VTv9kFm/wHYLOzOyO9ECBDc= github.com/dogmatiq/linger v0.2.1 h1:ecVwiFlTcQuQ7ygQXH5bUPkWNve8n5BmVnCYMGMQ3zc= diff --git a/render/renderer_test.go b/render/renderer_test.go index b4f86e0c..e73f45d2 100644 --- a/render/renderer_test.go +++ b/render/renderer_test.go @@ -3,6 +3,7 @@ package render import ( "io" + "github.com/dogmatiq/dogma" "github.com/dogmatiq/dogma/fixtures" // can't dot-import due to conflicts "github.com/dogmatiq/iago/iotest" "github.com/dogmatiq/iago/must" @@ -39,12 +40,20 @@ var _ = Describe("type DefaultRenderer", func() { return must.Must( DefaultRenderer{}.WriteAggregateRoot( w, - &fixtures.AggregateRoot{Value: ""}, + &fixtures.AggregateRoot{ + AppliedEvents: []dogma.Message{ + fixtures.MessageA1, + }, + }, ), ) }, "*fixtures.AggregateRoot{", - ` Value: ""`, + ` AppliedEvents: {`, + ` fixtures.MessageA{`, + ` Value: "A1"`, + ` }`, + ` }`, ` ApplyEventFunc: nil`, "}", ) diff --git a/render/string_test.go b/render/string_test.go index a6cfe512..f37b4675 100644 --- a/render/string_test.go +++ b/render/string_test.go @@ -3,6 +3,7 @@ package render_test import ( "strings" + "github.com/dogmatiq/dogma" "github.com/dogmatiq/dogma/fixtures" // can't dot-import due to conflicts . "github.com/dogmatiq/testkit/render" . "github.com/onsi/ginkgo" @@ -29,11 +30,19 @@ var _ = Describe("func AggregateRoot()", func() { Expect( AggregateRoot( DefaultRenderer{}, - &fixtures.AggregateRoot{Value: ""}, + &fixtures.AggregateRoot{ + AppliedEvents: []dogma.Message{ + fixtures.MessageA1, + }, + }, ), ).To(Equal(join( "*fixtures.AggregateRoot{", - ` Value: ""`, + ` AppliedEvents: {`, + ` fixtures.MessageA{`, + ` Value: "A1"`, + ` }`, + ` }`, ` ApplyEventFunc: nil`, "}", )))