Skip to content

Commit

Permalink
Merge pull request #24 from dogmatiq/visit-handlers
Browse files Browse the repository at this point in the history
Add accept methods to handler sets.
  • Loading branch information
jmalloc authored Dec 6, 2019
2 parents 3448e61 + 10fbdf1 commit 48959e9
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 15 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ The format is based on [Keep a Changelog], and this project adheres to
[Keep a Changelog]: https://keepachangelog.com/en/1.0.0/
[Semantic Versioning]: https://semver.org/spec/v2.0.0.html

## [Unreleased]

### Added

- Add `HandlerSet.AcceptVisitor()` and `RichHandlerSet.AcceptRichVisitor()`

## [0.1.0] - 2019-12-02

- Initial release
Expand Down
16 changes: 2 additions & 14 deletions fixtures/visitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,7 @@ func (v *Visitor) VisitApplication(ctx context.Context, cfg configkit.Applicatio
return v.VisitApplicationFunc(ctx, cfg)
}

for _, h := range cfg.Handlers() {
if err := h.AcceptVisitor(ctx, v); err != nil {
return err
}
}

return nil
return cfg.Handlers().AcceptVisitor(ctx, v)
}

// VisitAggregate calls v.VisitAggregateFunc(ctx, cfg) if it is non-nil.
Expand Down Expand Up @@ -89,13 +83,7 @@ func (v *RichVisitor) VisitRichApplication(ctx context.Context, cfg configkit.Ri
return v.VisitRichApplicationFunc(ctx, cfg)
}

for _, h := range cfg.RichHandlers() {
if err := h.AcceptRichVisitor(ctx, v); err != nil {
return err
}
}

return nil
return cfg.RichHandlers().AcceptRichVisitor(ctx, v)
}

// VisitRichAggregate calls v.VisitAggregateFunc(ctx, cfg) if it is non-nil.
Expand Down
38 changes: 37 additions & 1 deletion handlerset.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package configkit

import "github.com/dogmatiq/configkit/message"
import (
"context"

"github.com/dogmatiq/configkit/message"
)

// HandlerSet is a collection of handlers.
type HandlerSet map[Identity]Handler
Expand Down Expand Up @@ -111,6 +115,22 @@ func (s HandlerSet) Filter(fn func(Handler) bool) HandlerSet {
return subset
}

// AcceptVisitor visits each handler in the set.
//
// It returns the error returned by the first handler to return a non-nil error.
// It returns nil if all handlers accept the visitor without failure.
//
// The order in which handlers are visited is not guaranteed.
func (s HandlerSet) AcceptVisitor(ctx context.Context, v Visitor) error {
for _, h := range s {
if err := h.AcceptVisitor(ctx, v); err != nil {
return err
}
}

return nil
}

// RichHandlerSet is a collection of rich handlers.
type RichHandlerSet map[Identity]RichHandler

Expand Down Expand Up @@ -245,3 +265,19 @@ func (s RichHandlerSet) Filter(fn func(RichHandler) bool) RichHandlerSet {

return subset
}

// AcceptRichVisitor visits each handler in the set.
//
// It returns the error returned by the first handler to return a non-nil error.
// It returns nil if all handlers accept the visitor without failure.
//
// The order in which handlers are visited is not guaranteed.
func (s RichHandlerSet) AcceptRichVisitor(ctx context.Context, v RichVisitor) error {
for _, h := range s {
if err := h.AcceptRichVisitor(ctx, v); err != nil {
return err
}
}

return nil
}
89 changes: 89 additions & 0 deletions handlerset_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package configkit_test

import (
"context"
"errors"

. "github.com/dogmatiq/configkit"
cfixtures "github.com/dogmatiq/configkit/fixtures"
"github.com/dogmatiq/dogma"
Expand Down Expand Up @@ -208,6 +211,49 @@ var _ = Describe("type HandlerSet", func() {
Expect(set.Has(projection)).To(BeTrue())
})
})

Describe("func AcceptVisitor()", func() {
BeforeEach(func() {
set.Add(aggregate)
set.Add(projection)
})

It("visits each handler in the set", func() {
var visited []Handler

err := set.AcceptVisitor(
context.Background(),
&cfixtures.Visitor{
VisitAggregateFunc: func(_ context.Context, cfg Aggregate) error {
Expect(cfg).To(BeIdenticalTo(aggregate))
visited = append(visited, cfg)
return nil
},
VisitProjectionFunc: func(_ context.Context, cfg Projection) error {
Expect(cfg).To(BeIdenticalTo(projection))
visited = append(visited, cfg)
return nil
},
},
)

Expect(err).ShouldNot(HaveOccurred())
Expect(visited).To(ConsistOf(aggregate, projection))
})

It("returns an error if one of the handlers fails", func() {
err := set.AcceptVisitor(
context.Background(),
&cfixtures.Visitor{
VisitProjectionFunc: func(_ context.Context, cfg Projection) error {
return errors.New("<error>")
},
},
)

Expect(err).To(MatchError("<error>"))
})
})
})

var _ = Describe("type RichHandlerSet", func() {
Expand Down Expand Up @@ -409,4 +455,47 @@ var _ = Describe("type RichHandlerSet", func() {
Expect(set.Has(projection)).To(BeTrue())
})
})

Describe("func AcceptRichVisitor()", func() {
BeforeEach(func() {
set.Add(aggregate)
set.Add(projection)
})

It("visits each handler in the set", func() {
var visited []RichHandler

err := set.AcceptRichVisitor(
context.Background(),
&cfixtures.RichVisitor{
VisitRichAggregateFunc: func(_ context.Context, cfg RichAggregate) error {
Expect(cfg).To(BeIdenticalTo(aggregate))
visited = append(visited, cfg)
return nil
},
VisitRichProjectionFunc: func(_ context.Context, cfg RichProjection) error {
Expect(cfg).To(BeIdenticalTo(projection))
visited = append(visited, cfg)
return nil
},
},
)

Expect(err).ShouldNot(HaveOccurred())
Expect(visited).To(ConsistOf(aggregate, projection))
})

It("returns an error if one of the handlers fails", func() {
err := set.AcceptRichVisitor(
context.Background(),
&cfixtures.RichVisitor{
VisitRichProjectionFunc: func(_ context.Context, cfg RichProjection) error {
return errors.New("<error>")
},
},
)

Expect(err).To(MatchError("<error>"))
})
})
})

0 comments on commit 48959e9

Please sign in to comment.