OutlabsTaskq
API

Enqueue

Typed enqueue results and 0.1 uniqueness.

Every enqueue returns a structured EnqueueResult. Never infer success from a missing id.

Statuses (0.1)

StatusMeaning
createdNew row inserted (created=True)
existedActive (queue, idempotency_key) already present (created=False)
result = await tq.enqueue(
    DOUBLE,
    {"value": 3},
    idempotency_key="demo:3",
)
assert result.status in {"created", "existed"}

Uniqueness in 0.1

Reject-only on active (queue, idempotency_key). Duplicate key → existed.

Modes such as replace, preserve_run_at, and statuses like replaced / skipped_locked / conflict are 0.2+ design — not on the current wire surface.

concurrency_key is separate: it caps parallel runners; it is not an enqueue identity key.

Options

TaskQ.enqueue accepts optional scheduled_at, priority, lease_seconds, concurrency_key, affinity_key, retry overrides, headers, and a transactional session or connection.

Also available: enqueue_many (one result per input, in order) and enqueue_raw (requires validate_job_types=False).

Bulk workflow admission

Use enqueue_many when a planner already knows many independent members of one workflow. Contract 0.6.7 introduced the workflow reservation and set-based insert behavior retained in 0.6.12: it reserves the workflow members once, inserts the jobs set-wise, preserves caller order, and sends one wake-up notification. A call is limited to 1,000 items; chunk larger plans while keeping one caller-owned transaction, then seal the workflow after every chunk succeeds.

results = await tq.enqueue_many(
    PROFILE_REFRESH,
    payloads,
    idempotency_keys=idempotency_keys,
    workflow_id=workflow.workflow_id,
    step_keys=step_keys,
    session=session,
)

Each member still becomes its own job. Bulk admission only removes the per-member database round trips; it does not combine execution, retries, settlement, suppression, or observability. Use one job per item when those properties must remain independent.

All items in a workflow bulk call must use distinct step_key and idempotency_key values. The operation is atomic: validation, member-limit, workflow-conflict, or queue-depth failure inserts nothing. Exact idempotent replays return existed, even after the workflow is sealed or the queue reaches its depth cap.

Do not loop over enqueue thousands of times inside one transaction. That holds the transaction open, repeats admission work, and can consume the shared TaskQ database even though each eventual job is tiny. Chunk enqueue_many at 1,000 and set an explicit planning-time budget in the producing application.