Skip to Content

Event Pipelines

An event declaration can carry three pipeline segments — before / after / finally — writing the “around the emit” rules into the channel itself: before can rewrite the payload or cancel the dispatch, after runs after dispatch, and finally runs unconditionally.

The Three Segments

event Order(id: string) { before { if id == "black" { discard; } if id == "swap" { resume "white"; } } after { print("[after] dispatch done"); } finally { print("[finally] always runs"); } }

The execution order on emit is: before → dispatch → after → finally. Each of the three payloads takes a turn:

func OnOrder(id: string) { print("kitchen received", id); } Order ~> OnOrder; emit Order("white ticket"); print("---"); emit Order("black"); print("---"); emit Order("swap");
kitchen received white ticket [after] dispatch done [finally] always runs --- [finally] always runs --- kitchen received white [after] dispatch done [finally] always runs
  • white ticket passes straight through: falling off the end of before means allowed, and subscribers receive the original payload.
  • black is stopped by discard;: dispatch and after are both skipped; only finally always runs.
  • swap is rewritten by resume "white";: subscribers receive the rewritten payload.

Rules for resume and discard

  • resume rewrites the payload; its argument must carry all payload fields.
  • discard; is a soft keyword in statement position, legal only inside event pipelines and handle arms.
  • after / finally are pure execution segments: resume / discard are not allowed inside them.

The Event Prop Write Pipeline

Writes to an event prop go through the same pipeline: before (can rewrite the pending value / cancel the write) → change check → storage → after → automatic emit → finally. Segments can take an explicit parameter list, bound as (old, new):

class Gauge { public event prop Level: int { before(oldV, newV) { if newV < 0 { resume 0; } } } }

resume rewrites only the new-value slot; discard; cancels both the write and the broadcast. In an explicit parameter list the old value is read-only; without a parameter list, use the setter’s value parameter name — the same mechanism as prop.

Notes

  • Declaring pipeline segments alone (without get; / set;) implies automatic get;set; the segments always run.
  • Pipeline bodies can perform (no uses declaration needed; resolved through the handler stack at runtime), and instance pipelines can access self.
  • The error set of a fail inside the pipeline is automatically folded into the emit site’s obligation: on the call side, an emit with a pipeline must consume or declare per the fail contract.
Last updated on October 11, 2026