Decider
A Decider (aka a command or use-case handler) is a class with a single handle method, that can handle a specific concrete COMMAND and based on its logic it will decide if zero or one EVENT is returned; or in case it's unable to handle the Command (e.g. due to invariant rules) an Exception is thrown.
Command handling SHOULD be idempotent, meaning that if a Command has already been handled then the handle method MUST return zero Events as opposed to throwing an Exception.
Example:
class ShipOrderDecider : Decider<ShipOrder, OrderEvent> {
override fun handle(cmd: ShipOrder, events: List<OrderEvent>): OrderEvent? {
if (events.isEmpty()) {
throw RuntimeException("Cannot accept an order that hasn't been created")
}
if (events.any { it is OrderShipped}) {
// Already shipped - idempotent handling
return null
}
if (!events.any { it is OrderAccepted }) {
throw RuntimeException("Cannot ship an order that hasn't been accepted")
}
return OrderShipped(cmd.id)
}
override fun canHandle(cmd: Any): Boolean {
return cmd is ShipOrder
}
}Content copied to clipboard