GenDurable.Await (gen_durable v0.2.10)

Copy Markdown View Source

Wait for an instance to settle — the sync-over-async bridge (GenDurable.await/3 is the public entry).

The answer is always read from the row (the single source of truth); everything else only shortens the time until that read:

  • the local fast path — the executor, after committing a settled outcome, nudges same-node waiters through an ETS table owned by the watcher (one lookup per outcome; free when nobody waits). Waiters are never Process.linked to anything — an engine shutdown can strand a waiter, not kill it;
  • the watcher — a per-instance batched poller: waiters register their ids, one SELECT … WHERE id = ANY(...) per tick covers all of them (cross-node executions land within a tick); idle means zero queries;
  • with no running instance (bare-repo usage) a plain per-caller poll loop, so await/3 works everywhere insert does.

A nudge is only a hint — the waiter re-checks the row and keeps waiting if it is not settled by its predicate. "Settled" means nothing left to do without external input: done, failed, awaiting_signal, awaiting_children (with until: :terminal, only the first two). Every subscription point is guarded: an engine stopping or a component restarting mid-await degrades the caller to polling (the row outlives the engine), never crashes it — blocked waiters re-check and re-assert their watch on a coarse cadence as the backstop.