Statifier.Effect.CancelInvoke (Statifier v2.5.0)

Copy Markdown View Source

Payload for {:cancel_invoke, %__MODULE__{}} - the cancellation Appendix D's exitStates and exitInterpreter both perform with for inv in s.invoke: cancelInvoke(inv) when a state carrying live invocations exits. invoke_id names the invocation to cancel; state_index is the constraint-3 identity of the state that owned it. macrostep/microstep/ round are the counters as they stood at the moment of the cancel.

Not Statifier.Effect.Cancel

Effect.Cancel is spec 6.3's <cancel sendid> - an authored element that cancels a delayed send, resolved against Statifier.Session.Timers by send_id. This effect has no <cancel> element behind it at all: it is the interpreter's own reaction to a state exiting while one of its <invoke>s is still live, and it has no notion of a delayed send to look up. The two share no session-side machinery, which is why they are two structs rather than one with an optional field.

One effect per invocation, not one per state

Appendix D's loop is for inv in s.invoke: cancelInvoke(inv) - one call per invocation - and every other effect this vocabulary produces is one-per-action (Effect.Invoke is one-per-<invoke>, Effect.Log is one-per-<log>). A state with two live invocations therefore emits two CancelInvoke effects, never one carrying a list.

caller_context

caller_context is the opaque host term the current macrostep's triggering external event carried (ADR-0063, amended 2026-09-01), copied off Statifier.MachineState's transient slot at construction - nil when no context was attached. Both invoke lifecycle effects carry it, not just the start, for the same both-or-neither reason ADR-0063 decision 2 gave %Cancel{} the slot beside %SendDelayed{}: the same handler and the same durable store process both, and the cancellation act wants the same attribution as the start. Statifier.Effect.Autoforward deliberately gains nothing - it carries the triggering %Statifier.Event{} whole, and that event's own slot already travels with it (ADR-0063 decision 3). The library never reads the value.

Summary

Types

t()

@type t() :: %Statifier.Effect.CancelInvoke{
  caller_context: term(),
  invoke_id: String.t(),
  macrostep: non_neg_integer(),
  microstep: non_neg_integer(),
  round: non_neg_integer(),
  state_index: non_neg_integer()
}