Decider

interface Decider<COMMAND, EVENT>

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
}
}

Functions

Link copied to clipboard
abstract fun canHandle(cmd: Any): Boolean

Guard method that can check if the specific command is supported by this Decider instance

Link copied to clipboard
abstract fun handle(cmd: COMMAND, events: List<EVENT>): EVENT?

Handle the COMMAND and decide if zero or one EVENT is returned as a result of handling the command