Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Dependencies and keys

Keys

A key is an optional unique name for a task.

  • Deduplication: submitting a task whose key belongs to a live task, or to a terminal task still in the retention window, does not create a new task. It returns the existing id with duplicate = true. This makes producers safe to retry.
  • References: dependencies, cancellation, status lookups and result waits accept a key wherever they accept an id.

Keys stay reserved while the task is live and for the retention window after it ends (limits.key_retention_s on the server, CoreConfig::retention in the library; 1 hour by default). Separately, the server deletes finished rows from a Postgres or SQLite store after store.keep_finished_s (7 days by default).

Edges

A dependency is a reference to a parent (id or key) plus a condition:

ConditionRustPythonSatisfied when the parent...
on success (default).after(x) / Dep::on_success(x)after=[x] / Dep(x)succeeded
on failureDep::on_failure(x)Dep(x, on="failure")failed or was dead-lettered
on completeDep::on_complete(x)Dep(x, on="complete")reached any terminal status

A task with unmet dependencies is Blocked and does not enter any queue. When a parent ends:

  • every satisfied edge decrements the child's count of unmet dependencies; at zero the child becomes eligible;
  • an edge that can no longer be satisfied makes the child Skipped, and this propagates to its own dependents.

If the parent had already finished when the child was submitted, the edge is resolved immediately from the retained status.

After a restart with a durable store, a parent that finished so long ago that its status is no longer retained counts as satisfied: it was accepted, and only work that has not finished is recovered.

Unknown parents

A dependency on a key that does not exist yet is handled per pool:

SettingEffect
UnknownDependency::Reject (default)Submission fails with UnknownDependency.
UnknownDependency::Await { timeout }The child waits for a task with that key; if none appears within timeout, it is Skipped.

In Python: Pool(unknown_dependency="await", await_timeout=...); on the server: await_unknown_dependencies_s on the pool. Waiting children are tracked per key and cleaned up when they are cancelled, time out or are resolved, so abandoned awaits do not accumulate.

A dependency on an id that does not exist is always rejected.

Cycles

Cycles are rejected with Cycle: a task depending on its own key, cycles within a batch, and cycles closed through a task that is awaiting a key the new submission defines.

Batches

submit_batch admits several tasks atomically. Dependencies may reference keys defined anywhere in the batch, in any order. If any task is invalid, would close a cycle, conflicts with a reservation or exceeds a bound, nothing is admitted and the error names the offending index.

Complexity

Dependencies are tracked with in-degree counters and reverse edges, so a parent finishing costs O(number of its children). Completed parents are never scanned.