Skip to content

Commit

Permalink
Ignore disabled handlers that are unconfigured.
Browse files Browse the repository at this point in the history
  • Loading branch information
jmalloc committed Jul 16, 2024
1 parent 9a41753 commit 9678519
Show file tree
Hide file tree
Showing 13 changed files with 125 additions and 52 deletions.
15 changes: 9 additions & 6 deletions aggregate.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"reflect"

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

Expand All @@ -28,6 +27,14 @@ type RichAggregate interface {
// It panics if the handler is configured incorrectly. Use Recover() to convert
// configuration related panic values to errors.
func FromAggregate(h dogma.AggregateMessageHandler) RichAggregate {
cfg, c := fromAggregate(h)
c.mustValidate()
return cfg
}

func fromAggregate(
h dogma.AggregateMessageHandler,
) (*aggregate, *aggregateConfigurer) {
cfg := &aggregate{
handler: handler{
entity: entity{
Expand All @@ -48,11 +55,7 @@ func FromAggregate(h dogma.AggregateMessageHandler) RichAggregate {

h.Configure(c)

c.validate()
c.mustConsume(message.CommandRole)
c.mustProduce(message.EventRole)

return cfg
return cfg, c
}

// aggregate is an implementation of RichAggregate.
Expand Down
11 changes: 10 additions & 1 deletion aggregateconfigurer.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package configkit

import "github.com/dogmatiq/dogma"
import (
"github.com/dogmatiq/configkit/message"
"github.com/dogmatiq/dogma"
)

type aggregateConfigurer struct {
handlerConfigurer
Expand All @@ -11,3 +14,9 @@ func (c *aggregateConfigurer) Routes(routes ...dogma.AggregateRoute) {
c.route(r)
}
}

func (c *aggregateConfigurer) mustValidate() {
c.handlerConfigurer.mustValidate()
c.mustConsume(message.CommandRole)
c.mustProduce(message.EventRole)
}
10 changes: 7 additions & 3 deletions application.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ type RichApplication interface {
// It panics if the application is configured incorrectly. Use Recover() to
// convert configuration related panic values to errors.
func FromApplication(a dogma.Application) RichApplication {
cfg, c := fromApplication(a)
c.mustValidate()
return cfg
}

func fromApplication(a dogma.Application) (*application, *applicationConfigurer) {
cfg := &application{
entity: entity{
rt: reflect.TypeOf(a),
Expand All @@ -52,9 +58,7 @@ func FromApplication(a dogma.Application) RichApplication {

a.Configure(c)

c.validate()

return cfg
return cfg, c
}

// IsApplicationEqual compares two applications for equality.
Expand Down
10 changes: 10 additions & 0 deletions application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,23 @@ var _ = Describe("func FromApplication()", func() {
},
}

disabled := &fixtures.ProjectionMessageHandler{
ConfigureFunc: func(c dogma.ProjectionConfigurer) {
// Verify that disabled handlers with no identity / route
// configuration are excluded from the application
// configuration.
c.Disable()
},
}

app = &fixtures.Application{
ConfigureFunc: func(c dogma.ApplicationConfigurer) {
c.Identity("<app>", appKey)
c.RegisterAggregate(aggregate)
c.RegisterProcess(process)
c.RegisterIntegration(integration)
c.RegisterProjection(projection)
c.RegisterProjection(disabled)
},
}
})
Expand Down
26 changes: 17 additions & 9 deletions applicationconfigurer.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,35 @@ func (c *applicationConfigurer) Identity(name, key string) {
}

func (c *applicationConfigurer) RegisterAggregate(h dogma.AggregateMessageHandler, _ ...dogma.RegisterAggregateOption) {
cfg := FromAggregate(h)
c.register(cfg)
c.registerIfConfigured(fromAggregate(h))
}

func (c *applicationConfigurer) RegisterProcess(h dogma.ProcessMessageHandler, _ ...dogma.RegisterProcessOption) {
cfg := FromProcess(h)
c.register(cfg)
c.registerIfConfigured(fromProcess(h))
}

func (c *applicationConfigurer) RegisterIntegration(h dogma.IntegrationMessageHandler, _ ...dogma.RegisterIntegrationOption) {
cfg := FromIntegration(h)
c.register(cfg)
c.registerIfConfigured(fromIntegration(h))
}

func (c *applicationConfigurer) RegisterProjection(h dogma.ProjectionMessageHandler, _ ...dogma.RegisterProjectionOption) {
cfg := FromProjection(h)
c.register(cfg)
c.registerIfConfigured(fromProjection(h))
}

// register adds a handler configuration to the application.
func (c *applicationConfigurer) register(h RichHandler) {
func (c *applicationConfigurer) registerIfConfigured(
h RichHandler,
hc interface {
isConfigured() bool
mustValidate()
},
) {
if h.IsDisabled() && !hc.isConfigured() {
return
}

hc.mustValidate()

c.guardAgainstConflictingIdentities(h)
c.guardAgainstConflictingRoles(h)
c.guardAgainstConflictingRoutes(h)
Expand Down
13 changes: 10 additions & 3 deletions entityconfigurer.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ import "github.com/dogmatiq/configkit/internal/validation"
// - [dogma.ProjectionConfigurer]
type entityConfigurer struct {
// entity is the target entity to populate with the configuration values.
entity *entity
entity *entity
configured bool
}

// Identity sets the entity's identity.
func (c *entityConfigurer) Identity(n string, k string) {
c.configured = true

if !c.entity.ident.IsZero() {
validation.Panicf(
"%s is configured with multiple identities (%s and %s/%s), Identity() must be called exactly once within Configure()",
Expand All @@ -39,8 +42,12 @@ func (c *entityConfigurer) Identity(n string, k string) {
}
}

// validate panics if the configuration is invalid.
func (c *entityConfigurer) validate() {
func (c *entityConfigurer) isConfigured() bool {
return c.configured
}

// mustValidate panics if the configuration is invalid.
func (c *entityConfigurer) mustValidate() {
if c.entity.ident.IsZero() {
validation.Panicf(
"%s is configured without an identity, Identity() must be called exactly once within Configure()",
Expand Down
10 changes: 6 additions & 4 deletions handlerconfigurer.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@ type handlerConfigurer struct {
handler *handler
}

func (c *handlerConfigurer) Disable(...dogma.DisableOption) {
c.handler.isDisabled = true
}

func (c *handlerConfigurer) route(r dogma.Route) {
c.configured = true

switch r := r.(type) {
case dogma.HandlesCommandRoute:
c.consumes(r.Type, message.CommandRole, "HandlesCommand")
Expand Down Expand Up @@ -156,7 +162,3 @@ func (c *handlerConfigurer) mustProduce(r message.Role) {
route,
)
}

func (c *handlerConfigurer) Disable(...dogma.DisableOption) {
c.handler.isDisabled = true
}
12 changes: 7 additions & 5 deletions integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"reflect"

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

Expand All @@ -28,6 +27,12 @@ type RichIntegration interface {
// It panics if the handler is configured incorrectly. Use Recover() to convert
// configuration related panic values to errors.
func FromIntegration(h dogma.IntegrationMessageHandler) RichIntegration {
cfg, c := fromIntegration(h)
c.mustValidate()
return cfg
}

func fromIntegration(h dogma.IntegrationMessageHandler) (*integration, *integrationConfigurer) {
cfg := &integration{
handler: handler{
entity: entity{
Expand All @@ -48,10 +53,7 @@ func FromIntegration(h dogma.IntegrationMessageHandler) RichIntegration {

h.Configure(c)

c.validate()
c.mustConsume(message.CommandRole)

return cfg
return cfg, c
}

// integration is an implementation of RichIntegration.
Expand Down
10 changes: 9 additions & 1 deletion integrationconfigurer.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package configkit

import "github.com/dogmatiq/dogma"
import (
"github.com/dogmatiq/configkit/message"
"github.com/dogmatiq/dogma"
)

type integrationConfigurer struct {
handlerConfigurer
Expand All @@ -11,3 +14,8 @@ func (c *integrationConfigurer) Routes(routes ...dogma.IntegrationRoute) {
c.route(r)
}
}

func (c *integrationConfigurer) mustValidate() {
c.handlerConfigurer.mustValidate()
c.mustConsume(message.CommandRole)
}
13 changes: 7 additions & 6 deletions process.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"reflect"

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

Expand All @@ -28,6 +27,12 @@ type RichProcess interface {
// It panics if the handler is configured incorrectly. Use Recover() to convert
// configuration related panic values to errors.
func FromProcess(h dogma.ProcessMessageHandler) RichProcess {
cfg, c := fromProcess(h)
c.mustValidate()
return cfg
}

func fromProcess(h dogma.ProcessMessageHandler) (*process, *processConfigurer) {
cfg := &process{
handler: handler{
entity: entity{
Expand All @@ -48,11 +53,7 @@ func FromProcess(h dogma.ProcessMessageHandler) RichProcess {

h.Configure(c)

c.validate()
c.mustConsume(message.EventRole)
c.mustProduce(message.CommandRole)

return cfg
return cfg, c
}

// process is an implementation of RichProcess.
Expand Down
11 changes: 10 additions & 1 deletion processconfigurer.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package configkit

import "github.com/dogmatiq/dogma"
import (
"github.com/dogmatiq/configkit/message"
"github.com/dogmatiq/dogma"
)

type processConfigurer struct {
handlerConfigurer
Expand All @@ -11,3 +14,9 @@ func (c *processConfigurer) Routes(routes ...dogma.ProcessRoute) {
c.route(r)
}
}

func (c *processConfigurer) mustValidate() {
c.handlerConfigurer.mustValidate()
c.mustConsume(message.EventRole)
c.mustProduce(message.CommandRole)
}
17 changes: 8 additions & 9 deletions projection.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"reflect"

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

Expand All @@ -31,6 +30,12 @@ type RichProjection interface {
// It panics if the handler is configured incorrectly. Use Recover() to convert
// configuration related panic values to errors.
func FromProjection(h dogma.ProjectionMessageHandler) RichProjection {
cfg, c := fromProjection(h)
c.mustValidate()
return cfg
}

func fromProjection(h dogma.ProjectionMessageHandler) (*projection, *projectionConfigurer) {
cfg := &projection{
handler: handler{
entity: entity{
Expand All @@ -48,18 +53,12 @@ func FromProjection(h dogma.ProjectionMessageHandler) RichProjection {
},
handler: &cfg.handler,
},
projection: cfg,
}

h.Configure(c)

c.validate()
c.mustConsume(message.EventRole)

if c.deliveryPolicy != nil {
cfg.deliveryPolicy = c.deliveryPolicy
}

return cfg
return cfg, c
}

// projection is an implementation of RichProjection.
Expand Down
19 changes: 15 additions & 4 deletions projectionconfigurer.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package configkit

import "github.com/dogmatiq/dogma"
import (
"github.com/dogmatiq/configkit/internal/validation"
"github.com/dogmatiq/configkit/message"
"github.com/dogmatiq/dogma"
)

type projectionConfigurer struct {
handlerConfigurer
deliveryPolicy dogma.ProjectionDeliveryPolicy
projection *projection
}

func (c *projectionConfigurer) Routes(routes ...dogma.ProjectionRoute) {
Expand All @@ -14,9 +18,16 @@ func (c *projectionConfigurer) Routes(routes ...dogma.ProjectionRoute) {
}

func (c *projectionConfigurer) DeliveryPolicy(p dogma.ProjectionDeliveryPolicy) {
c.configured = true

if p == nil {
panic("delivery policy must not be nil")
validation.Panicf("delivery policy must not be nil")

Check warning on line 24 in projectionconfigurer.go

View check run for this annotation

Codecov / codecov/patch

projectionconfigurer.go#L24

Added line #L24 was not covered by tests
}

c.deliveryPolicy = p
c.projection.deliveryPolicy = p
}

func (c *projectionConfigurer) mustValidate() {
c.handlerConfigurer.mustValidate()
c.mustConsume(message.EventRole)
}

0 comments on commit 9678519

Please sign in to comment.