StatifierOban.Timer.Delivery.Session (StatifierOban v0.1.0)

Copy Markdown View Source

The default StatifierOban.Timer.Delivery: feeds a fired event back into a live Statifier.Session, behind the two-step liveness check statifier-ex's docs/durable-timers.md spells out.

The two steps run in order because Statifier.Session.status/1 is a GenServer.call that exits the caller against a dead process - it cannot itself answer "terminated?":

  1. Terminated? Registry.lookup/2 against Statifier.Registry under the scope (st-ADR-0027 decision 2: sessions register under their session id). Empty means discard: the session no longer exists, or never registered, and status/1 is not safe to call.
  2. Halted? With a live process confirmed, status/1. Anything but :running discards too - "live" is stricter than "not terminated": a :done session keeps its process but declines to drain, so an event fed to it would sit queued forever, not be processed and not be discarded. The process exiting between the two steps is caught and reported as the same :terminated fact step 1 answers.

Delivery is Statifier.Session.send_event/2 - the same door a fired in-process timer rejoins through - with the event built from the stored effect exactly as the session's own delivery path builds it: origin/origintype stamped as the scxml processor at the sending session's location, sendid only when the author wrote the id (C.1), data and caller_context carried through untouched. send_event/2 is a cast, so :delivered means enqueued onto the session's inbox, not processed.

This module requires Statifier.Supervisor (which owns Statifier.Registry) to be running: Registry.lookup/2 raises when it is not, and the job retries rather than discards - a missing registry is an environment fact about the host, not a liveness fact about the run. The scope must therefore be the session id the session registered under (ctx.session_id); a host using any other scope owes its own StatifierOban.Timer.Delivery implementation.