Skip to content

Commit

Permalink
Use enum package to implement HandlerType.
Browse files Browse the repository at this point in the history
  • Loading branch information
jmalloc committed Oct 15, 2024
1 parent af4f2bb commit 73788ec
Show file tree
Hide file tree
Showing 4 changed files with 329 additions and 117 deletions.
92 changes: 18 additions & 74 deletions config/handlertype.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package config

import (
"iter"

"github.com/dogmatiq/enginekit/internal/enum"
)

// HandlerType is an enumeration of the types of message handlers.
type HandlerType int

Expand All @@ -21,99 +27,37 @@ const (
ProjectionHandlerType
)

// HandlerTypes returns a list of all [HandlerType] values.
func HandlerTypes() []HandlerType {
return []HandlerType{
AggregateHandlerType,
ProcessHandlerType,
IntegrationHandlerType,
ProjectionHandlerType,
}
// HandlerTypes returns a sequence that yields all valid [HandlerType] values.
func HandlerTypes() iter.Seq[HandlerType] {
return enum.Range(AggregateHandlerType, ProjectionHandlerType)
}

func (t HandlerType) String() string {
switch t {
case AggregateHandlerType:
return "aggregate"
case ProcessHandlerType:
return "process"
case IntegrationHandlerType:
return "integration"
case ProjectionHandlerType:
return "projection"
default:
panic("invalid handler type")
}
}

// SwitchByHandlerTypeOf invokes one of the provided functions based on the
// [HandlerType] of h.
func SwitchByHandlerTypeOf(
h Handler,
aggregate func(*Aggregate),
process func(*Process),
integration func(*Integration),
projection func(*Projection),
) {
switch h := h.(type) {
case *Aggregate:
if aggregate == nil {
panic("no case function was provided for aggregate handlers")
}
aggregate(h)
case *Process:
if process == nil {
panic("no case function was provided for process handlers")
}
process(h)
case *Integration:
if integration == nil {
panic("no case function was provided for integration handlers")
}
integration(h)
case *Projection:
if projection == nil {
panic("no case function was provided for projection handlers")
}
projection(h)
default:
panic("invalid handler type")
}
return enum.String(t, "aggregate", "process", "integration", "projection")
}

// RouteCapabilities returns a value that describes the routing capabilities of
// the handler type.
func (t HandlerType) RouteCapabilities() RouteCapabilities {
switch t {
case AggregateHandlerType:
return RouteCapabilities{
return RouteCapabilities{
MapByHandlerType(
t,
map[RouteType]RouteTypeCapability{
HandlesCommandRouteType: RouteTypeRequired,
RecordsEventRouteType: RouteTypeRequired,
},
}
case IntegrationHandlerType:
return RouteCapabilities{
map[RouteType]RouteTypeCapability{
HandlesCommandRouteType: RouteTypeRequired,
RecordsEventRouteType: RouteTypeAllowed,
},
}
case ProcessHandlerType:
return RouteCapabilities{
map[RouteType]RouteTypeCapability{
HandlesEventRouteType: RouteTypeRequired,
ExecutesCommandRouteType: RouteTypeRequired,
SchedulesTimeoutRouteType: RouteTypeAllowed,
},
}
case ProjectionHandlerType:
return RouteCapabilities{
map[RouteType]RouteTypeCapability{
HandlesCommandRouteType: RouteTypeRequired,
RecordsEventRouteType: RouteTypeAllowed,
},
map[RouteType]RouteTypeCapability{
HandlesEventRouteType: RouteTypeRequired,
},
}
default:
panic("invalid handler type")
),
}
}
43 changes: 0 additions & 43 deletions config/handlertype_test.go

This file was deleted.

122 changes: 122 additions & 0 deletions config/handlertypeswitch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package config

import (
"github.com/dogmatiq/enginekit/internal/enum"
)

// SwitchByHandlerType invokes one of the provided functions based on t.
//
// It provides a compile-time guarantee that all possible values are handled,
// even if new [HandlerType] values are added in the future.
//
// It panics if the function associated with t is nil, or if t is not a valid
// [HandlerType].
func SwitchByHandlerType(
t HandlerType,
aggregate func(),
process func(),
integration func(),
projection func(),
) {
enum.Switch(t, aggregate, process, integration, projection)
}

// MapByHandlerType maps t to a value of type T.
//
// It provides a compile-time guarantee that all possible values are handled,
// even if new [HandlerType] values are added in the future.
//
// It panics if t is not a valid [HandlerType].
func MapByHandlerType[T any](t HandlerType, aggregate, process, integration, projection T) T {
return enum.Map(t, aggregate, process, integration, projection)
}

// SwitchByHandlerTypeOf invokes one of the provided functions based on the
// [HandlerType] of h.
//
// It provides a compile-time guarantee that all types are handled, even if new
// [HandlerType] values are added in the future.
//
// It panics if the function associated with h's type is nil.
func SwitchByHandlerTypeOf(
h Handler,
aggregate func(*Aggregate),
process func(*Process),
integration func(*Integration),
projection func(*Projection),
) {
switch h := h.(type) {
case *Aggregate:
if aggregate == nil {
panic("no case function was provided for *config.Aggregate")
}
aggregate(h)
case *Process:
if process == nil {
panic("no case function was provided for *config.Process")
}
process(h)
case *Integration:
if integration == nil {
panic("no case function was provided for *config.Integration")
}
integration(h)
case *Projection:
if projection == nil {
panic("no case function was provided for *config.Projection")
}
projection(h)
default:
panic("invalid handler type")
}
}

// MapByHandlerTypeOf invokes one of the provided functions based on the
// [HandlerType] of h, and returns the result.
//
// It provides a compile-time guarantee that all types are handled, even if new
// [HandlerType] values are added in the future.
//
// It panics if the function associated with h's type is nil.
func MapByHandlerTypeOf[T any](
h Handler,
aggregate func(*Aggregate) T,
process func(*Process) T,
integration func(*Integration) T,
projection func(*Projection) T,
) (result T) {
SwitchByHandlerTypeOf(
h,
enum.AssignResult(aggregate, &result),
enum.AssignResult(process, &result),
enum.AssignResult(integration, &result),
enum.AssignResult(projection, &result),
)

return result
}

// MapByHandlerTypeOfWithErr invokes one of the provided functions based on the
// [HandlerType] of h, and returns the result and error value.
//
// It provides a compile-time guarantee that all types are handled, even if new
// [HandlerType] values are added in the future.
//
// It panics if the function associated with h's type is nil.
func MapByHandlerTypeOfWithErr[T any](
h Handler,
aggregate func(*Aggregate) (T, error),
process func(*Process) (T, error),
integration func(*Integration) (T, error),
projection func(*Projection) (T, error),
) (result T, err error) {
SwitchByHandlerTypeOf(
h,
enum.AssignResultErr(aggregate, &result, &err),
enum.AssignResultErr(process, &result, &err),
enum.AssignResultErr(integration, &result, &err),
enum.AssignResultErr(projection, &result, &err),
)

return result, err
}
Loading

0 comments on commit 73788ec

Please sign in to comment.