Docket (docket v0.1.1)

Copy Markdown View Source

Public entry point for durable graph operations.

A runtime instance is one Docket.Runtime.Supervisor tree, identified by the name it was started under. Hosts usually define one with use Docket:

defmodule MyApp.Docket do
  use Docket,
    backend: {MyApp.DocketBackend, backend_option: :value}
end

# in the application supervision tree
children = [MyApp.Docket]

Hosts save graph versions explicitly and use start_run, storage-backed reads, named signals, and await_run. Options given to the instance at startup own backend and execution policy. Per-call options carry only operation data and cannot replace instance configuration. Public durable calls resolve only :tenantless or an explicit {:tenant, id}; :system is reserved for internal dispatch/recovery.

For processless in-test execution of the same loop, use Docket.Test.

Delivery boundary

A durable backend commits each accepted run transition and its retained events atomically under the current claim and checkpoint fences. Node attempts are replayable and may execute more than once even though only one transition can commit. External effects require a cooperating idempotency scheme when duplicates are unacceptable. Checkpoint observers, notifications, and telemetry are best effort rather than durable delivery mechanisms.

Summary

Functions

Defines a host runtime module wrapping a named runtime instance

Polls durable operational state until waiting, terminal, poisoned, or timeout.

Cancels a durable active run and confirms the committed terminal state.

Child spec integration point: {Docket, name: MyRuntime, backend: ...} starts a Docket.Runtime.Supervisor tree.

Synchronously claims and drains due durable runs in a backend testing mode.

Reads one retained durable event by its positive sequence number.

Reads the exact effective graph selected by a Docket.GraphRef.

Reads the latest retained durable event for a run.

Reads the reference for the newest distinct version of a graph ID.

Fetches the newest run summary matching the supplied tenant scope and optional graph/status filters.

Reads the last committed durable Docket.Run.

Reads a durable run plus token-free operational state.

Reads a page of retained durable events for a run.

Lists one graph ID's saved versions newest first under the resolved tenant.

Lists durable runs visible to the resolved tenant scope.

Resolves an open interrupt and schedules the next tick or durable wake.

Clears a non-terminal run's poison state and schedules it immediately.

Saves one effective, content-addressed graph version.

Starts a run from a previously saved graph reference.

Functions

__using__(default_opts)

(macro)

Defines a host runtime module wrapping a named runtime instance:

defmodule MyApp.Docket do
  use Docket, backend: {MyApp.DocketBackend, backend_option: :value}
end

Docket runtime policy remains at the top level. Backend-specific configuration belongs in {BackendModule, backend_options} and is immutable for the runtime instance. The host module gets supervision and operational wrappers that call Docket with the module as the runtime instance.

await_run(runtime, run_id, opts \\ [])

Polls durable operational state until waiting, terminal, poisoned, or timeout.

:timeout is required and expressed in milliseconds. :poll_interval defaults to 50 milliseconds.

cancel_run(runtime, run_id, opts \\ [])

Cancels a durable active run and confirms the committed terminal state.

child_spec(opts)

Child spec integration point: {Docket, name: MyRuntime, backend: ...} starts a Docket.Runtime.Supervisor tree.

drain_runs(runtime, opts \\ [])

Synchronously claims and drains due durable runs in a backend testing mode.

fetch_event(runtime, run_id, seq, opts \\ [])

@spec fetch_event(term(), String.t(), pos_integer(), keyword()) ::
  {:ok, Docket.Event.t()} | {:error, term()}

Reads one retained durable event by its positive sequence number.

A missing or pruned sequence, an unknown run, and a wrong tenant all return {:error, :not_found}.

fetch_graph(runtime, graph_ref, opts \\ [])

@spec fetch_graph(term(), Docket.GraphRef.t(), keyword()) ::
  {:ok, Docket.Graph.t()} | {:error, term()}

Reads the exact effective graph selected by a Docket.GraphRef.

A reference is relative to the resolved tenant owner scope. Equal references may be saved independently by different tenants; possession of a reference never bypasses tenant isolation. An unknown or differently-owned reference returns {:error, :not_found}.

fetch_latest_event(runtime, run_id, opts \\ [])

@spec fetch_latest_event(term(), String.t(), keyword()) ::
  {:ok, Docket.Event.t() | nil} | {:error, term()}

Reads the latest retained durable event for a run.

A visible run whose complete event history has been pruned returns {:ok, nil}. An unknown run and a wrong tenant return {:error, :not_found}.

fetch_latest_graph_ref(runtime, graph_id, opts \\ [])

@spec fetch_latest_graph_ref(term(), String.t(), keyword()) ::
  {:ok, Docket.GraphRef.t()} | {:error, term()}

Reads the reference for the newest distinct version of a graph ID.

Latest is scoped to the resolved tenant and uses the same durable ordering as list_graph_versions/3. Re-saving an existing version is idempotent and does not move it forward in that order.

fetch_latest_run(runtime, opts \\ [])

@spec fetch_latest_run(
  term(),
  keyword()
) :: {:ok, Docket.RunSummary.t()} | {:error, term()}

Fetches the newest run summary matching the supplied tenant scope and optional graph/status filters.

Returns {:error, :not_found} when the scoped query has no matches.

fetch_run(runtime, run_id, opts \\ [])

Reads the last committed durable Docket.Run.

inspect_run(runtime, run_id, opts \\ [])

Reads a durable run plus token-free operational state.

list_events(runtime, run_id, opts \\ [])

Reads a page of retained durable events for a run.

Events come back in ascending sequence order, restricted to sequences greater than :after_seq (default 0) and limited by :limit (default 250, an integer in 1..1000). Sequence gaps from persistence filtering and retention pruning are normal, so pages are not promised contiguous. The returned Docket.EventPage carries the retention bounds and the run's latest committed event sequence observed from the same snapshot.

Invalid options return {:error, %Docket.Error{type: :invalid_options}} without reaching storage. A wrong tenant and an unknown run both return {:error, :not_found}.

{:ok, page} = MyApp.Docket.list_events("run-123", after_seq: 10, limit: 50)
page.events

list_graph_versions(runtime, graph_id, opts \\ [])

@spec list_graph_versions(term(), String.t(), keyword()) ::
  {:ok, Docket.GraphVersionPage.t()} | {:error, term()}

Lists one graph ID's saved versions newest first under the resolved tenant.

:before is an exclusive cursor returned as next_before by the preceding page. :limit defaults to 100 and must be in 1..1000. An unknown graph ID returns a successful empty Docket.GraphVersionPage.

list_runs(runtime, opts \\ [])

@spec list_runs(
  term(),
  keyword()
) :: {:ok, Docket.RunPage.t()} | {:error, term()}

Lists durable runs visible to the resolved tenant scope.

Runs are returned as lightweight Docket.RunSummary values in newest-first order by the immutable {started_at, run_id} key. :before accepts the previous page's next_before cursor. Optional filters are :status (one durable status or a non-empty list), :graph_id, and :graph_hash. :limit defaults to 100 and must be in 1..1000.

An empty result is a successful empty Docket.RunPage. Under tenant_mode: :required, :tenant_id is mandatory and is always an access scope, never an optional filter.

resolve_interrupt(runtime, run_id, interrupt_id, value, opts \\ [])

Resolves an open interrupt and schedules the next tick or durable wake.

Unknown or already-resolved interrupts return {:error, %Docket.Error{type: :not_found}}. The stored effective graph is loaded and compiled on the executing node without injecting new defaults, the pure mutation and its events commit atomically, and tenant scope is enforced before storage access. Authorization remains host-owned.

retry_poisoned_run(runtime, run_id, opts \\ [])

Clears a non-terminal run's poison state and schedules it immediately.

save_graph(runtime, graph, opts \\ [])

Saves one effective, content-addressed graph version.

Publication snapshots each node implementation's configuration schema once and materializes its defaults into the durable graph before hashing. Storage keeps that effective graph; execution loads and compiles it on the node that performs the work.

start_run(runtime, graph_ref, input, opts \\ [])

Starts a run from a previously saved graph reference.

The effective graph is fetched, validated against local node contracts, and compiled without injecting defaults introduced after publication. The initialized run and assigned events then commit atomically. Durable checkpoint observers run only after that commit; starting a run never publishes or changes a graph document.