DecideScope

interface DecideScope

What a decide function (or an after hook) can ask of the kernel besides returning its decision.

A decide function may act on other systems, such as reserving a unique key. onAppendFailure undoes such an act when the command's events are surely not appended: the decision rejects, the version conflicts and the command is decided again, or deciding fails. It does not run when whether the append committed is unknown, and it cannot run if the process dies; an act that must not leak then needs its own expiry. Reserved keys (reserve, release) are unique within the aggregate's type and tenant unless reserved with ReservationTenancy.SYSTEM.

A decide function may also schedule a command for later: schedule and cancelSchedule add the system events wow.ScheduleSet and wow.ScheduleCancelled to the events the command commits, atomically with them, and the runtime sends the command each time it is due. A decision that only schedules commits those events.

Properties

Link copied to clipboard
abstract val command: Command<*>

The command being decided, with what admission learned about its request.

Link copied to clipboard
abstract val ids: Ids

The ids this decision takes: the node's global and aggregate id generators, fixed ids in the test DSL. A decision decided again, after a version conflict, takes new ones.

Link copied to clipboard
abstract val now: Long

The time of this decision, epoch milliseconds, from the node's clock: the commit time its events are recorded at, which a sourcing function reads back as EventStream.commitTime. A decision computes a deadline or an expiry from it, not from the system clock, so a test sets it: the test DSL's time starts at its start and moves with advanceTime. A decision decided again, after a version conflict, reads the clock anew.

Functions

Link copied to clipboard
abstract fun afterAppend(action: suspend () -> Unit)

Registers action to run once this attempt's events are appended. A failure of it is logged, not raised.

Link copied to clipboard
abstract fun cancelSchedule(key: String)

Cancels the schedule this aggregate keeps under key, scheduled by an earlier command or this one (the system event wow.ScheduleCancelled); nothing when there is none. A command already sent is not recalled: its target's state guards it.

Link copied to clipboard
abstract fun onAppendFailure(compensation: suspend () -> Unit)

Registers compensation to run when this attempt's events are surely not appended.

Link copied to clipboard
abstract fun putResult(key: String, value: Any)

Adds value under key to what the caller is answered once the events are appended.

Link copied to clipboard
open fun reject(code: String, message: String): Nothing

Refuses the command with the rejection code and message, as returning Decision.reject(code, message) does: it throws a RejectedException, which the kernel answers as that rejection. message is shown to the caller. The same as the top-level reject(code, message), which a decide function without a scope calls.

open fun reject(code: String, message: String, events: List<Any> = emptyList(), extensions: Map<String, Any?> = emptyMap()): Nothing

Refuses the command with the rejection code, message and structured extensions, appending events with it; see the top-level reject.

Link copied to clipboard
abstract fun release(namespace: String, key: String)

Releases key in namespace, which this command's aggregate holds, once the events are appended: another aggregate may then reserve it. The release commits with the events: it is recorded with them and applied again after a crash, as a confirmation is; nothing is released when they are not appended, or by a decision that appends no event. A key the aggregate does not hold stays as it is.

abstract fun release(namespace: String, key: String, tenancy: ReservationTenancy)

Releases key in namespace as release does, the key reserved with tenancy.

Link copied to clipboard
abstract suspend fun reserve(namespace: String, key: String): Boolean

Reserves key in namespace for this command's aggregate, such as a unique user name; false when another aggregate holds it. The key is unique among the aggregates of this aggregate's type, within its tenant (ReservationTenancy.TENANT): another tenant, or an aggregate of another type, may hold the same key (a type's reservations live with its log). A key unique across types, such as an e-mail address that users and organizations share, is modelled as an aggregate of its own that holds the keys, which the other aggregates claim through it.

abstract suspend fun reserve(namespace: String, key: String, tenancy: ReservationTenancy): Boolean

Reserves key in namespace for this command's aggregate as reserve does, unique among the aggregates tenancy says: ReservationTenancy.SYSTEM makes it unique across the type's tenants.

Link copied to clipboard
open fun schedule(key: String, rule: ScheduleRule, command: Any)

Schedules command for this aggregate under key as rule says; see schedule of a target.

abstract fun schedule(key: String, rule: ScheduleRule, command: Any, target: AggregateRef)

Schedules command to be sent to target, this aggregate by default, as rule says: at an instant, after a delay counted from this commit, or by a cron expression. key names the schedule within this aggregate: scheduling a key again replaces it (a reschedule, or a new rule), and cancelSchedule cancels it. Within one decision the last call for a key wins.