SagaContext

The context of every handler of a me.ahoo.wow.api.annotation.Saga: its @OnEvent handlers, its @OnRejected and @OnCommitted handlers of the receipts of the commands it derives (CommandReceipt), and its @OnSchedule jobs' handlers. A handler returns the commands it derives as CommandRequests, one, several (an Iterable, a Sequence, a Flow) or none, and the subscription sends each, deterministic, so handling the same commit, receipt or tick again derives the same requests, which their targets decide once:

  • its target is the request's: CommandRequest.type, else the aggregate type the local Manifest and the peer contracts on the class path (each api jar's META-INF/wow/contract.json) assign the command's class; its tenant CommandRequest.targetTenant, else this execution's (the commit's, the receipt's or the job instance's); its id CommandRequest.id, else none: a creation whose id the target's admission gives, the id of the aggregate the request already created when it is handled again, so the target keeps the first one;

  • its id and request id are name-based on executionId (and, for a receipt, the receipt's command), the target, the command's class and, when the request gives a CommandRequest.requestId, that business key, else how many such requests to the same target the execution derived before it; the order the handler builds them in does not matter;

  • its scope is CommandRequest.targetScope, else the commit's (the receipt's command's), so an aggregate it creates belongs to the owner the chain acts for; its operator is the commit's, and its causation links it to the commit (the receipt's command) and to the root of the chain; its CommandRequest.expectedVersion is kept;

  • a request with a CommandRequest.wait or a CommandRequest.timeout fails the handler unrecoverable, so the aggregate parks at once: the subscription sends derived commands and waits for none.

Derived commands are trusted: the target's scope guard does not check one it changes, so a wrong target is not refused; test the targets in a saga spec. A command class no contract assigns, or several aggregates decide, fails the handler with an IllegalArgumentException naming them: give the request its CommandRequest.type.

The handler of a receipt finds the aggregate whose commit derived the command in CommandReceipt.source, and a job's handler its tick in the ScheduleTick it takes.

Properties

Link copied to clipboard
abstract val ids: Ids

The ids this execution takes: the node's generators, each aggregate type's the one the host configures for it (wow.aggregates.<ctx.agg>.id-generator), fixed ids in the test DSL.

Functions

Link copied to clipboard
abstract suspend fun call(request: CommandRequest<*>): CommandResult

Sends request, to an aggregate of another bounded context, through that context's HTTP command gateway and returns its result once it is committed there: the aggregate it acted on (the id the target gave a creation without one), its version, duplicate when the target had already committed the request. It becomes a command as a returned request does: its deterministic request id makes every retry and replay of this execution the same request, which the target decides once and answers with the same aggregate; its operator, scope and causation are the root command's, which the client asserts on the target's internal port, naming its service, a port only the platform's own services reach. A wait that follows the saga goes on with it: the target signals the next hops as for a derived command.

Link copied to clipboard
abstract fun cancel(key: String, target: AggregateRef)

Cancels the schedule key of target: the execution derives the system command wow.schedule.Cancel to it, after the commands the handler returns; see schedule.

Link copied to clipboard
abstract fun schedule(key: String, rule: ScheduleRule, request: CommandRequest<*>)

Schedules request's command on its target under key as rule says: the execution derives the system command wow.schedule.Set to that target with the commands the handler returns, after them, keyed as a returned request is, so handling the commit again derives the same request. The handler declares the class of the command in its @Sends(schedules). The target must exist: otherwise it rejects the command, which the saga's @OnRejected handler for SetSchedule gets. key names the schedule among the target's: setting it again replaces it, and cancel cancels it. An after rule counts from the commit that sets it on the target.