Skip to content

Commit

Permalink
Merge pull request #339 from dogmatiq/handler-disable
Browse files Browse the repository at this point in the history
Support handlers that are disabled by their configuration.
  • Loading branch information
jmalloc authored Jul 16, 2024
2 parents 8bd8f15 + de1278e commit 09bf56b
Show file tree
Hide file tree
Showing 10 changed files with 224 additions and 34 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,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

- Added support for `Disable()` method in `dogmatiq/dogma` v0.13.1.

## [0.15.0] - 2024-03-26

### Added
Expand Down
4 changes: 4 additions & 0 deletions engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,10 @@ func (e *Engine) skipHandler(
return !en, fact.IndividualHandlerDisabled
}

if h.IsDisabled() {
return true, fact.IndividualHandlerDisabledByConfiguration
}

en := oo.enabledHandlerTypes[h.HandlerType()]
return !en, fact.HandlerTypeDisabled
}
77 changes: 70 additions & 7 deletions engine/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ import (

var _ = g.Describe("type Engine", func() {
var (
aggregate *AggregateMessageHandler
process *ProcessMessageHandler
integration *IntegrationMessageHandler
projection *ProjectionMessageHandler
app *Application
config configkit.RichApplication
engine *Engine
aggregate *AggregateMessageHandler
process *ProcessMessageHandler
integration *IntegrationMessageHandler
projection, disabled *ProjectionMessageHandler
app *Application
config configkit.RichApplication
engine *Engine
)

g.BeforeEach(func() {
Expand Down Expand Up @@ -76,13 +76,24 @@ var _ = g.Describe("type Engine", func() {
},
}

disabled = &ProjectionMessageHandler{
ConfigureFunc: func(c dogma.ProjectionConfigurer) {
c.Identity("<disabled-projection>", "06426c1f-788d-4852-9a3f-c77580dafaed")
c.Routes(
dogma.HandlesEvent[MessageG](),
)
c.Disable()
},
}

app = &Application{
ConfigureFunc: func(c dogma.ApplicationConfigurer) {
c.Identity("<app>", "9bc07eeb-5821-4649-941a-d931c8c88cb9")
c.RegisterAggregate(aggregate)
c.RegisterProcess(process)
c.RegisterIntegration(integration)
c.RegisterProjection(projection)
c.RegisterProjection(disabled)
},
}

Expand Down Expand Up @@ -289,6 +300,58 @@ var _ = g.Describe("type Engine", func() {
))
})

g.It("skips handlers that are disabled by their configuration", func() {
buf := &fact.Buffer{}
err := engine.Tick(
context.Background(),
WithObserver(buf),
)
Expect(err).ShouldNot(HaveOccurred())

h, _ := config.RichHandlers().ByName("<disabled-projection>")
Expect(buf.Facts()).To(ContainElement(
fact.TickSkipped{
Handler: h,
Reason: fact.IndividualHandlerDisabledByConfiguration,
},
))
})

g.It("skips handlers that are disabled by their configuration, even if they are explicitly enabled by type", func() {
buf := &fact.Buffer{}
err := engine.Tick(
context.Background(),
WithObserver(buf),
EnableProjections(true),
)
Expect(err).ShouldNot(HaveOccurred())

h, _ := config.RichHandlers().ByName("<disabled-projection>")
Expect(buf.Facts()).To(ContainElement(
fact.TickSkipped{
Handler: h,
Reason: fact.IndividualHandlerDisabledByConfiguration,
},
))
})

g.It("does not skip handlers that are enabled by name, even if they are disabled by their configuration", func() {
buf := &fact.Buffer{}
err := engine.Tick(
context.Background(),
WithObserver(buf),
EnableHandler("<disabled-projection>", true),
)
Expect(err).ShouldNot(HaveOccurred())

h, _ := config.RichHandlers().ByName("<disabled-projection>")
Expect(buf.Facts()).To(ContainElement(
fact.TickBegun{
Handler: h,
},
))
})

g.It("always returns context errors even if other errors occur", func() {
ctx, cancel := context.WithCancel(context.Background())

Expand Down
3 changes: 3 additions & 0 deletions engine/operationoption.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ func enableHandlerType(t configkit.HandlerType, enabled bool) OperationOption {
//
// This option takes precedence over any EnableAggregates(), EnableProcesses(),
// EnableIntegrations() or EnableProjections() options.
//
// It also takes precedence over the handler's own configuration, which may lead
// to unexpected behavior.
func EnableHandler(name string, enabled bool) OperationOption {
if err := configkit.ValidateIdentityName(name); err != nil {
panic(err)
Expand Down
9 changes: 7 additions & 2 deletions fact/skip.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@ type HandlerSkipReason byte

const (
// HandlerTypeDisabled indicates that a handler was skipped because all
// handlers of that type have been disabled.
// handlers of that type have been disabled using an engine option.
HandlerTypeDisabled HandlerSkipReason = 'T'

// IndividualHandlerDisabled indicates that a handler was skipped because
// that specific handler was disabled.
// that specific handler was disabled using an engine option.
IndividualHandlerDisabled HandlerSkipReason = 'I'

// IndividualHandlerDisabledByConfiguration indicates that a handler was
// skipped because it was disabled by a call to Disable() in its Configure()
// method.
IndividualHandlerDisabledByConfiguration HandlerSkipReason = 'C'
)
4 changes: 1 addition & 3 deletions fact/tick.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ type TickCompleted struct {
Error error
}

// TickSkipped indicates that a call to Controller.Tick() has been skipped,
// either because all handlers of that type are or the handler itself is
// disabled.
// TickSkipped indicates that a call to Controller.Tick() has been skipped.
type TickSkipped struct {
Handler configkit.RichHandler
Reason HandlerSkipReason
Expand Down
12 changes: 6 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ module github.com/dogmatiq/testkit
go 1.21

require (
github.com/dogmatiq/configkit v0.13.0
github.com/dogmatiq/configkit v0.13.1
github.com/dogmatiq/cosyne v0.2.0
github.com/dogmatiq/dapper v0.5.3
github.com/dogmatiq/dogma v0.13.0
github.com/dogmatiq/dogma v0.13.1
github.com/dogmatiq/iago v0.4.0
github.com/dogmatiq/linger v1.1.0
github.com/onsi/ginkgo/v2 v2.19.0
github.com/onsi/gomega v1.33.1
github.com/sergi/go-diff v1.3.1
go.uber.org/multierr v1.11.0
golang.org/x/text v0.16.0
google.golang.org/protobuf v1.34.2
)

Expand All @@ -23,9 +24,8 @@ require (
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect
github.com/google/uuid v1.6.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
golang.org/x/tools v0.21.0 // indirect
golang.org/x/net v0.27.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/tools v0.23.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
24 changes: 12 additions & 12 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dogmatiq/configkit v0.13.0 h1:pV2Pz0iBUBnRfOm6tbWVRXvuh2bWHBScOh8KfVp/N68=
github.com/dogmatiq/configkit v0.13.0/go.mod h1:9Sx3e0G9o/wPvRfhpKcS7+3bhYHmOyRBqKdXRZdDx7M=
github.com/dogmatiq/configkit v0.13.1 h1:iwddmpFabu2nwfElCcQ0NF3CWGJafKGkag+k6bW+09M=
github.com/dogmatiq/configkit v0.13.1/go.mod h1:Ou5kBaudSkl/3qIEVQJWedmbakf/tWCtROL49AcxqT0=
github.com/dogmatiq/cosyne v0.2.0 h1:tO957BpS4I9kqSw31ds6Ef4CXvV8zPAqWzbXKElsGWg=
github.com/dogmatiq/cosyne v0.2.0/go.mod h1:dD8EZjbRX7FFw9t6P7l1nwoZbA7YxtOCfl9ZZAHPucU=
github.com/dogmatiq/dapper v0.5.3 h1:DZkitO0TiokaiZt+9J7UNnagW2ezSYmJUlDTXLWGf8g=
github.com/dogmatiq/dapper v0.5.3/go.mod h1:lrBXvNri2wXkk1T0muaTUqd5lVDwIBRKeOzVRU46XI0=
github.com/dogmatiq/dogma v0.13.0 h1:MKk9MHErGKD53Y+43I4fcoPZMQjX0N2DUZEc4rLp+Hk=
github.com/dogmatiq/dogma v0.13.0/go.mod h1:9lyVA+6V2+E/exV0IrBOrkUiyFwIATEhv+b0vnB2umQ=
github.com/dogmatiq/dogma v0.13.1 h1:b1nsqYNmICEG2egvZ43K8w04Jma+MWYL6yF5Ad12y9o=
github.com/dogmatiq/dogma v0.13.1/go.mod h1:9lyVA+6V2+E/exV0IrBOrkUiyFwIATEhv+b0vnB2umQ=
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/jumble v0.1.0 h1:Cb3ExfxY+AoUP4G9/sOwoOdYX8o+kOLK8+dhXAry+QA=
Expand Down Expand Up @@ -78,8 +78,8 @@ golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand All @@ -90,16 +90,16 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=
golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
Expand Down
23 changes: 19 additions & 4 deletions test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"github.com/dogmatiq/iago/must"
"github.com/dogmatiq/testkit/engine"
"github.com/dogmatiq/testkit/fact"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)

// Test contains the state of a single test.
Expand Down Expand Up @@ -189,14 +191,27 @@ func (t *Test) DisableHandlersLike(patterns ...string) *Test {

func (t *Test) enableHandlers(names []string, enable bool) *Test {
for _, n := range names {
if _, ok := t.app.Handlers().ByName(n); !ok {
h, ok := t.app.Handlers().ByName(n)
if !ok {
panic(fmt.Sprintf(
"the %q application does not have a handler named %q",
t.app.Identity().Name,
n,
))
}

if enable && h.IsDisabled() {
panic(fmt.Sprintf(
"cannot enable the %q handler, it has been disabled by a call to %sConfigurer.Disable()",
n,
cases.
Title(language.English).
String(
h.HandlerType().String(),
),
))
}

t.operationOptions = append(
t.operationOptions,
engine.EnableHandler(n, enable),
Expand All @@ -213,16 +228,16 @@ func (t *Test) enableHandlersLike(patterns []string, enable bool) *Test {
re := regexp.MustCompile(p)
matched := false

for ident := range t.app.Handlers() {
if re.MatchString(ident.Name) {
for ident, h := range t.app.Handlers() {
if !h.IsDisabled() && re.MatchString(ident.Name) {
names[ident.Name] = struct{}{}
matched = true
}
}

if !matched {
panic(fmt.Sprintf(
"the %q application does not have any handlers with names that match the regular expression: %s",
"the %q application does not have any handlers with names that match the regular expression (%s), or all such handlers have been disabled by a call to ProjectionConfigurer.Disable()",
t.app.Identity().Name,
p,
))
Expand Down
Loading

0 comments on commit 09bf56b

Please sign in to comment.