Skip to content

Commit

Permalink
Add ranging methods to RichHandlerSet.
Browse files Browse the repository at this point in the history
  • Loading branch information
jmalloc committed Jan 29, 2020
1 parent cf05c84 commit f05d88b
Show file tree
Hide file tree
Showing 3 changed files with 262 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ The format is based on [Keep a Changelog], and this project adheres to
### Added

- Add `HandlerSet.Range[Aggregates|Processes|Integrations|Projections]()`
- Add `RichHandlerSet.Range[Aggregates|Processes|Integrations|Projections]()`

## [0.2.2] - 2020-01-29

Expand Down
74 changes: 74 additions & 0 deletions handlerset.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,3 +387,77 @@ func (s RichHandlerSet) AcceptRichVisitor(ctx context.Context, v RichVisitor) er

return nil
}

// RangeAggregates invokes fn once for each aggregate handler in the container.
//
// Iteration stops when fn returns false or once fn has been invoked for all
// aggregate handlers in the container.
//
// It returns true if fn returned true for all aggregate handlers.
func (s RichHandlerSet) RangeAggregates(fn func(RichAggregate) bool) bool {
for _, h := range s {
if x, ok := h.(RichAggregate); ok {
if !fn(x) {
return false
}
}
}

return true
}

// RangeProcesses invokes fn once for each process handler in the container.
//
// Iteration stops when fn returns false or once fn has been invoked for all
// process handlers in the container.
//
// It returns true if fn returned true for all process handlers.
func (s RichHandlerSet) RangeProcesses(fn func(RichProcess) bool) bool {
for _, h := range s {
if x, ok := h.(RichProcess); ok {
if !fn(x) {
return false
}
}
}

return true
}

// RangeIntegrations invokes fn once for each integration handler in the
// container.
//
// Iteration stops when fn returns false or once fn has been invoked for all
// integration handlers in the container.
//
// It returns true if fn returned true for all integration handlers.
func (s RichHandlerSet) RangeIntegrations(fn func(RichIntegration) bool) bool {
for _, h := range s {
if x, ok := h.(RichIntegration); ok {
if !fn(x) {
return false
}
}
}

return true
}

// RangeProjections invokes fn once for each projection handler in the
// container.
//
// Iteration stops when fn returns false or once fn has been invoked for all
// projection handlers in the container.
//
// It returns true if fn returned true for all projection handlers.
func (s RichHandlerSet) RangeProjections(fn func(RichProjection) bool) bool {
for _, h := range s {
if x, ok := h.(RichProjection); ok {
if !fn(x) {
return false
}
}
}

return true
}
188 changes: 187 additions & 1 deletion handlerset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ var _ = Describe("type HandlerSet", func() {
})
})

Context("each functions", func() {
Context("ranging functions", func() {
var (
aggregate1, aggregate2 Aggregate
process1, process2 Process
Expand Down Expand Up @@ -777,4 +777,190 @@ var _ = Describe("type RichHandlerSet", func() {
Expect(err).To(MatchError("<error>"))
})
})

Context("ranging functions", func() {
var (
aggregate1, aggregate2 RichAggregate
process1, process2 RichProcess
integration1, integration2 RichIntegration
projection1, projection2 RichProjection
)

BeforeEach(func() {
aggregate1 = FromAggregate(&fixtures.AggregateMessageHandler{
ConfigureFunc: func(c dogma.AggregateConfigurer) {
c.Identity("<agg1-name>", "<agg1-key>")
c.ConsumesCommandType(fixtures.MessageC{})
c.ProducesEventType(fixtures.MessageD{})
},
})

aggregate2 = FromAggregate(&fixtures.AggregateMessageHandler{
ConfigureFunc: func(c dogma.AggregateConfigurer) {
c.Identity("<agg2-name>", "<agg2-key>")
c.ConsumesCommandType(fixtures.MessageC{})
c.ProducesEventType(fixtures.MessageD{})
},
})

process1 = FromProcess(&fixtures.ProcessMessageHandler{
ConfigureFunc: func(c dogma.ProcessConfigurer) {
c.Identity("<proc1-name>", "<proc1-key>")
c.ConsumesEventType(fixtures.MessageE{})
c.ProducesCommandType(fixtures.MessageC{})
},
})

process2 = FromProcess(&fixtures.ProcessMessageHandler{
ConfigureFunc: func(c dogma.ProcessConfigurer) {
c.Identity("<proc2-name>", "<proc2-key>")
c.ConsumesEventType(fixtures.MessageE{})
c.ProducesCommandType(fixtures.MessageC{})
},
})

integration1 = FromIntegration(&fixtures.IntegrationMessageHandler{
ConfigureFunc: func(c dogma.IntegrationConfigurer) {
c.Identity("<int1-name>", "<int1-key>")
c.ConsumesCommandType(fixtures.MessageC{})
c.ProducesEventType(fixtures.MessageD{})
},
})

integration2 = FromIntegration(&fixtures.IntegrationMessageHandler{
ConfigureFunc: func(c dogma.IntegrationConfigurer) {
c.Identity("<int2-name>", "<int2-key>")
c.ConsumesCommandType(fixtures.MessageC{})
c.ProducesEventType(fixtures.MessageD{})
},
})

projection1 = FromProjection(&fixtures.ProjectionMessageHandler{
ConfigureFunc: func(c dogma.ProjectionConfigurer) {
c.Identity("<proj1-name>", "<proj1-key>")
c.ConsumesEventType(fixtures.MessageE{})
},
})

projection2 = FromProjection(&fixtures.ProjectionMessageHandler{
ConfigureFunc: func(c dogma.ProjectionConfigurer) {
c.Identity("<proj2-name>", "<proj2-key>")
c.ConsumesEventType(fixtures.MessageE{})
},
})

set.Add(aggregate1)
set.Add(aggregate2)
set.Add(process1)
set.Add(process2)
set.Add(integration1)
set.Add(integration2)
set.Add(projection1)
set.Add(projection2)
})

Describe("func RangeAggregates()", func() {
It("calls fn for each aggregate in the set", func() {
var names []string

all := set.RangeAggregates(func(h RichAggregate) bool {
names = append(names, h.Identity().Name)
return true
})

Expect(names).To(ConsistOf("<agg1-name>", "<agg2-name>"))
Expect(all).To(BeTrue())
})

It("stops iterating if fn returns false", func() {
count := 0

all := set.RangeAggregates(func(h RichAggregate) bool {
count++
return false
})

Expect(count).To(BeNumerically("==", 1))
Expect(all).To(BeFalse())
})
})

Describe("func RangeProcesses()", func() {
It("calls fn for each process in the set", func() {
var names []string

all := set.RangeProcesses(func(h RichProcess) bool {
names = append(names, h.Identity().Name)
return true
})

Expect(names).To(ConsistOf("<proc1-name>", "<proc2-name>"))
Expect(all).To(BeTrue())
})

It("stops iterating if fn returns false", func() {
count := 0

all := set.RangeProcesses(func(h RichProcess) bool {
count++
return false
})

Expect(count).To(BeNumerically("==", 1))
Expect(all).To(BeFalse())
})
})

Describe("func RangeIntegrations()", func() {
It("calls fn for each integration in the set", func() {
var names []string

all := set.RangeIntegrations(func(h RichIntegration) bool {
names = append(names, h.Identity().Name)
return true
})

Expect(names).To(ConsistOf("<int1-name>", "<int2-name>"))
Expect(all).To(BeTrue())
})

It("stops iterating if fn returns false", func() {
count := 0

all := set.RangeIntegrations(func(h RichIntegration) bool {
count++
return false
})

Expect(count).To(BeNumerically("==", 1))
Expect(all).To(BeFalse())
})
})

Describe("func RangeProjections()", func() {
It("calls fn for each projection in the set", func() {
var names []string

all := set.RangeProjections(func(h RichProjection) bool {
names = append(names, h.Identity().Name)
return true
})

Expect(names).To(ConsistOf("<proj1-name>", "<proj2-name>"))
Expect(all).To(BeTrue())
})

It("stops iterating if fn returns false", func() {
count := 0

all := set.RangeProjections(func(h RichProjection) bool {
count++
return false
})

Expect(count).To(BeNumerically("==", 1))
Expect(all).To(BeFalse())
})
})
})
})

0 comments on commit f05d88b

Please sign in to comment.