Queue Backends#
Registry#
Queue backends are registered through litestar_queues.backends.
- litestar_queues.backends.get_queue_backend(backend: QueueBackendConfig = 'memory', config: QueueConfig | None = None) BaseQueueBackend[source]#
Get an instantiated queue backend.
- Returns:
A configured queue backend instance.
- Raises:
TypeError – If a typed backend config selects a backend class that does not accept
backend_config.
- litestar_queues.backends.get_queue_backend_class(backend_path: str) type[BaseQueueBackend][source]#
Get a queue backend class by short name or import path.
Optional backends are imported lazily on first lookup so unused adapters do not require their driver extras to be installed.
- Returns:
The resolved queue backend class.
- Raises:
ValueError – If a short backend name is unknown.
- litestar_queues.backends.queue_backend(name: str) Callable[[type[BaseQueueBackend]], type[BaseQueueBackend]][source]#
Decorator to register a queue backend class with a short name.
- Returns:
A decorator that registers the backend class.
Base Backend#
- class litestar_queues.backends.base.BaseQueueBackend(config: QueueConfig | None = None)[source]#
Bases:
objectBase class for queue persistence backends.
- __init__(config: QueueConfig | None = None) None[source]#
Initialize the queue backend.
- config#
- property capabilities: QueueBackendCapabilities#
Backend behavior capabilities.
- get_event_log(config: EventHistoryConfig) QueueEventLog | None[source]#
Return a backend-owned queue event history implementation, if supported.
- async enqueue(task_name: str, *, args: tuple[Any, ...] = (), kwargs: dict[str, Any] | None = None, queue: str = 'default', priority: int = 0, max_retries: int = 0, scheduled_at: datetime | None = None, expires_at: datetime | None = None, key: str | None = None, execution_backend: str = 'local', execution_profile: str | None = None, metadata: dict[str, Any] | None = None, id: UUID | None = None) QueuedTaskRecord[source]#
Persist a queued task.
When
idis provided the persisted record uses it instead of a freshly generated identifier; the service pre-generates it forunique_until="forever"enqueues so the identity reservation and the executable record share one id.
- async enqueue_many(requests: Sequence[TaskRequest]) list[QueuedTaskRecord][source]#
Persist multiple queued tasks, returning records in input order.
The default implementation issues one
enqueue()per request, which preserves per-key deduplication and ordering. Backends with a native bulk path (e.g. SQLSpec COPY/Arrow/execute_many) override this for throughput while keeping the same semantics.- Returns:
Queue task records in the same order as
requests.
- async get_task(task_id: UUID) QueuedTaskRecord | None[source]#
Return a queued task by ID.
- async get_task_by_key(key: str) QueuedTaskRecord | None[source]#
Return a queued task by deduplication key.
- async get_tasks(task_ids: Sequence[UUID]) list[QueuedTaskRecord][source]#
Return existing records for the supplied identifiers.
- async notify_worker_control(worker_id: str | None) None[source]#
Publish a best-effort worker-control hint.
worker_idis the record’s persisted owner, orNonewhen the record was cancelled before any worker claimed it. It travels for observability only: the control channel is shared and every subscribed worker reconciles its own running tasks against durable status on receipt.Worker-control hints are lossy: durable status remains authoritative, and a dropped hint costs cancellation latency, never correctness.
- async wait_for_worker_control(*, worker_id: str, timeout: float | None = None) bool[source]#
Wait for a best-effort worker-control hint.
Mirrors
wait_for_wakeups(): polling-only backends inherit this sleep-and-report-nothing default and stay pure-poll.- Returns:
True when a control hint was observed.
- async assign_worker(task_id: UUID, *, worker_id: str, expected_retry_count: int) QueuedTaskRecord | None[source]#
Persist the owner of a running retry generation.
The write is fenced on
status='running' AND retry_count = expectedso a worker can never claim ownership of a generation it lost.- Parameters:
task_id – Queue record identifier.
worker_id – Identity to persist as the record owner.
expected_retry_count – Retry generation the caller believes it owns.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async list_pending(*, limit: int = 1, queue: str | None = None, execution_backend: str | None = None) list[QueuedTaskRecord][source]#
Return due pending or scheduled tasks ordered for execution.
- async claim_task(task_id: UUID, *, expected_retry_count: int | None = None, expected_execution_ref: str | None = None) QueuedTaskRecord | None[source]#
Atomically claim a pending task.
- async claim_task_with_expired(task_id: UUID, *, expected_retry_count: int | None = None, expected_execution_ref: str | None = None) tuple[QueuedTaskRecord | None, QueuedTaskRecord | None][source]#
Claim one task and report when this call expires that task.
- Returns:
The claimed record and the expired record, at most one of which is set.
- async claim_next(*, queues: tuple[str, ...] = (), execution_backend: str | None = None) QueuedTaskRecord | None[source]#
Claim the next due task across the requested queues.
An empty
queuestuple claims across all queues.- Returns:
The claimed task record, if one was available.
- async claim_many(*, limit: int, queues: tuple[str, ...] = (), execution_backend: str | None = None, queue_limits: Mapping[str, int] | None = None) list[QueuedTaskRecord][source]#
Claim up to
limitdue tasks across the requested queues.An empty
queuestuple claims across all queues. Backends with a native batch-claim primitive override this method; the fallback here preservesclaim_next()semantics for backends with only a single-record primitive.- Returns:
Claimed task records.
- async claim_many_with_expired(*, limit: int, queues: tuple[str, ...] = (), execution_backend: str | None = None, queue_limits: Mapping[str, int] | None = None) tuple[list[QueuedTaskRecord], list[QueuedTaskRecord]][source]#
Claim records and report overdue records transitioned while claiming.
- Returns:
Claimed records and records expired by this call.
- async complete_task(task_id: UUID, *, result: Any = None, expected_retry_count: int | None = None) QueuedTaskRecord | None[source]#
Mark a task as completed.
- Parameters:
task_id – Queue record identifier.
result – Task result payload.
expected_retry_count – When provided, update only if the record is still running with this retry count.
- async fail_task(task_id: UUID, error: str, *, retry: bool = True, expected_retry_count: int | None = None, retry_at: datetime | None = None, queued_at: datetime | None = None) QueuedTaskRecord | None[source]#
Mark a task as failed or retry it.
- Parameters:
task_id – Queue record identifier.
error – Error message to persist.
retry – Whether retry policy may requeue the task.
expected_retry_count – When provided, update only if the record is still running with this retry count.
retry_at – Scheduled eligibility timestamp for a delayed retry.
queued_at – Queue ordering timestamp for the new retry attempt.
- async cancel_task(task_id: UUID, *, include_running: bool = False, expected_retry_count: int | None = None) bool[source]#
Cancel a task.
- Parameters:
task_id – ID of the task to cancel.
include_running – Whether to cancel a task that is currently running.
expected_retry_count – Only cancel if the task is still on this retry generation.
- Returns:
True if the task was successfully cancelled, False otherwise.
- async interrupt_task(task_id: UUID, *, expected_retry_count: int, worker_id: str, queued_at: datetime) QueuedTaskRecord | None[source]#
Return an owned running attempt to pending after interruption.
The write is fenced on
status='running' AND retry_count = expected AND worker_id = worker_id. It resets the record topendingwith a freshqueued_atand clearsscheduled_at,started_at,heartbeat_at,completed_at,execution_ref, andworker_id.- Parameters:
task_id – Queue record identifier.
expected_retry_count – Retry generation the caller owns.
worker_id – Identity that must currently own the record.
queued_at – Requeue timestamp used for fair claim ordering.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async cancel_tasks(*, task_name: str | None = None, queue: str | None = None, kwargs: Mapping[str, Any] | None = None, metadata: Mapping[str, Any] | None = None, include_running: bool = False) int[source]#
Cancel tasks matching a domain predicate.
- Parameters:
task_name – Optional task name exact match.
queue – Optional queue exact match.
kwargs – Optional top-level kwargs exact-match subset.
metadata – Optional top-level metadata exact-match subset.
include_running – When true, running records are included for cooperative cancellation.
- Returns:
Number of records cancelled.
- async touch_heartbeats(touches: Sequence[HeartbeatTouch]) HeartbeatTouchResult[source]#
Update heartbeat timestamps for running tasks.
- Returns:
The task IDs confirmed touched or missed by the backend.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async null_heartbeats(task_ids: list[UUID], *, expected_retry_count: int | None = None) None[source]#
Clear heartbeat timestamps for task IDs.
- Parameters:
task_ids – Queue record identifiers.
expected_retry_count – When provided, clear only records that still match this retry count.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async requeue_stale_running(*, stale_after: timedelta, limit: int | None = None) StaleTaskRecoveryResult[source]#
Recover running tasks with stale heartbeats.
- Parameters:
stale_after – Heartbeat age past which a running task is stale.
limit – When provided, recover at most this many records ordered oldest-first (oldest heartbeat, then record id).
Nonepreserves the historical unbounded behavior; bounded maintenance always supplies a positive limit.
- Returns:
Summary of requeued, failed, skipped, and handler-needed records.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async expire_overdue(*, limit: int | None = None) list[QueuedTaskRecord][source]#
Transition overdue pending or scheduled records to
expired.- Returns:
Records transitioned to
expired.- Raises:
NotImplementedError – Always; every backend must answer this.
- async acquire_worker_lock(name: str, *, ttl: timedelta) bool[source]#
Acquire a backend-scoped worker coordination lock.
Fleet coordination and maintenance ownership are the same primitive, so this routes to
acquire_maintenance()under a fresh token. The lock is never released explicitly:ttlbounds it so a worker that dies mid-pass cannot wedge the fleet, and the next holder takes over once the stored ownership expires.- Returns:
True when the caller should run the coordinated worker action.
- async acquire_maintenance(name: str, token: str, *, ttl: timedelta) bool[source]#
Acquire token-fenced distributed maintenance ownership.
Only backends advertising
supports_maintenanceimplement a real coordination record. The base raises so maintenance fails closed rather than silently running unfenced on a backend that cannot prevent overlapping runs.- Raises:
NotImplementedError – Always, on backends without maintenance support.
- async release_maintenance(name: str, token: str) bool[source]#
Release maintenance ownership held under
token.Releases only when the persisted token matches
token, so a stale holder can never delete a successor’s ownership record.- Returns:
True when ownership held under
tokenwas released.- Raises:
NotImplementedError – Always, on backends without maintenance support.
- async set_execution_ref(task_id: UUID, execution_backend: str, execution_ref: str, *, execution_profile: str | None = None) QueuedTaskRecord | None[source]#
Persist an external execution reference for a running task.
- Returns:
The updated queued task record, if one exists.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async reserve_external_dispatch(task_id: UUID, execution_backend: str, reservation_ref: str, *, execution_profile: str | None = None, expected_retry_count: int | None = None) QueuedTaskRecord | None[source]#
Atomically reserve a due, unexpired task for external dispatch.
The default rejects dispatch because a read-then-write fallback cannot protect the external side effect.
- async clear_execution_ref(task_id: UUID, expected_retry_count: int, expected_execution_ref: str) QueuedTaskRecord | None[source]#
Clear an exact pending external attempt and wake dispatchers.
- async replace_execution_ref(task_id: UUID, expected_retry_count: int, expected_execution_ref: str, execution_ref: str) QueuedTaskRecord | None[source]#
Atomically rotate an exact pending external attempt reference.
- async release_external_dispatch(task_id: UUID, reservation_ref: str, execution_backend: str, *, execution_profile: str | None = None) QueuedTaskRecord | None[source]#
Release a matching external-dispatch reservation.
- async finalize_external_dispatch(task_id: UUID, reservation_ref: str, execution_backend: str, execution_ref: str, *, execution_profile: str | None = None) QueuedTaskRecord | None[source]#
Replace an owned dispatch reservation with its execution reference.
- async set_execution_backend(task_id: UUID, execution_backend: str, *, execution_profile: str | None = None) QueuedTaskRecord | None[source]#
Persist an execution backend/profile change for a queued task.
- Returns:
The updated queued task record, if one exists.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async list_running_external(*, limit: int | None = None) list[QueuedTaskRecord][source]#
Return externally dispatched tasks with references to reconcile.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async get_statistics(*, queue: str | None = None) QueueStatistics[source]#
Return queue status counts.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async list_completed_by_task(task_name: str, *, since: datetime | None = None, limit: int = 10) list[QueuedTaskRecord][source]#
Return recent completed records for a task name.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async cleanup_terminal(before: datetime, *, limit: int | None = None) int[source]#
Delete terminal records completed before a cutoff.
Routine terminal cleanup never touches
unique_until="forever"reservations; onlyreset_identity()removes them.- Parameters:
before – Delete terminal records completed strictly before this UTC cutoff.
limit – When provided, delete at most this many records ordered oldest-first (oldest
completed_at, then record id).Nonepreserves the historical unbounded behavior; bounded maintenance always supplies a positive limit.
- Returns:
The number of deleted records.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async reserve_identity(key: str, *, task_id: UUID, task_name: str) TaskReservation | None[source]#
Atomically reserve a
unique_until="forever"identity.Reservation is atomic: exactly one concurrent caller wins a given key. The winner receives
Noneand owns the durable reservation; every other caller receives the existing owner reservation. Reservation is the only way a reservation is created and must run before the executable record is persisted so a committed forever task can never lack its reservation.- Parameters:
key – The effective identity key to reserve.
task_id – The originating task id (shared with the executable record).
task_name – The originating registered task name.
- Returns:
Nonewhen this caller won the reservation; otherwise the existing owner reservation.
- async has_identity(key: str) TaskReservation | None[source]#
Return the reservation owning a reserved forever identity, if any.
- async reset_identity(key: str, *, expected_task_id: UUID | None = None) bool[source]#
Delete a forever identity reservation.
This is the only reservation deletion path; routine terminal and event maintenance never remove reservations. When
expected_task_idis provided, delete only when that task still owns the reservation. This compare-and-delete form lets enqueue recovery release its own failed reservation without deleting a successor created after an explicit reset. Omitting it preserves the explicit administrative reset behavior.- Parameters:
key – The exact effective identity key.
expected_task_id – Optional task owner required for deletion.
- Returns:
Truewhen a reservation was removed.
- async notify_new_task(record: QueuedTaskRecord) None[source]#
Notify waiters that a new task is available.
- async notify_new_tasks(records: Sequence[QueuedTaskRecord]) None[source]#
Emit one worker-wakeup hint for a batch of newly available tasks.
- async wait_for_wakeups(timeout: float | None = None) bool[source]#
Wait until backend notification arrives.
- Returns:
True when a notification was observed.
- async time_until_next_due(*, queues: tuple[str, ...] = ()) float | None[source]#
Return seconds until the earliest not-yet-due pending/scheduled record.
Bounds the worker’s adaptive polling wait so a scheduled or retried task is never discovered later than its own due time: no backend has a push notification for “a record’s scheduled time arrived,” so a worker asleep on a long backoff wait would otherwise only notice after that wait elapses. The default reports
None(unknown); concrete backends that can answer this cheaply override it. An unfiltered or slightly-early answer is always safe here (it can only wake the worker sooner than strictly necessary, never later).- Returns:
Seconds until the next due record across
queues(all queues when empty), orNonewhen there is no upcoming scheduled work or the backend does not support this query.
- async wait_for_completion(task_id: UUID, *, timeout: float | None = None) bool[source]#
Wait for a terminal-completion signal for one task.
Backends that advertise
supports_completion_eventsoverride this to subscribe to a completion channel. The default returnsFalseso callers fall back to polling.- Returns:
True when a completion signal for
task_idwas observed.
- litestar_queues.backends.base.attempts_consumed(record: QueuedTaskRecord) int[source]#
Return the retry attempts a record has actually consumed.
An interruption bumps
retry_countso the old owner’s fences can never settle the reclaimed attempt, but it is not a failed attempt: it must not spend the record’s retry budget.- Returns:
retry_countless the recorded interruptions.
- litestar_queues.backends.base.interruption_count(record: QueuedTaskRecord) int[source]#
Return how many times an attempt has been interrupted by a shutdown.
- Returns:
The recorded interruption count, or
0when it is absent or unusable.
Memory#
- class litestar_queues.backends.memory.backend.InMemoryQueueBackend(config: QueueConfig | None = None)[source]#
Bases:
BaseQueueBackendIn-process queue backend for tests, local development, and examples.
- __init__(config: QueueConfig | None = None) None[source]#
Initialize the queue backend.
- property capabilities: QueueBackendCapabilities#
Backend behavior capabilities.
- get_event_log(config: EventHistoryConfig) QueueEventLog | None[source]#
Return bounded, process-local queue event history when enabled.
- async enqueue(task_name: str, *, args: tuple[Any, ...] = (), kwargs: dict[str, Any] | None = None, queue: str = 'default', priority: int = 0, max_retries: int = 0, scheduled_at: datetime | None = None, expires_at: datetime | None = None, key: str | None = None, execution_backend: str = 'local', execution_profile: str | None = None, metadata: dict[str, Any] | None = None, id: UUID | None = None) QueuedTaskRecord[source]#
Persist a queued task.
When
idis provided the persisted record uses it instead of a freshly generated identifier; the service pre-generates it forunique_until="forever"enqueues so the identity reservation and the executable record share one id.
- async enqueue_many(requests: Sequence[TaskRequest]) list[QueuedTaskRecord][source]#
Persist multiple in-memory tasks while signaling waiters once.
- Returns:
Queue task records in the same order as
requests.
- async get_task(task_id: UUID) QueuedTaskRecord | None[source]#
Return a queued task by ID.
- async get_task_by_key(key: str) QueuedTaskRecord | None[source]#
Return a queued task by deduplication key.
- async get_tasks(task_ids: Sequence[UUID]) list[QueuedTaskRecord][source]#
Return existing records for the supplied identifiers.
- async notify_worker_control(worker_id: str | None) None[source]#
Publish a best-effort worker-control hint.
worker_idis the record’s persisted owner, orNonewhen the record was cancelled before any worker claimed it. It travels for observability only: the control channel is shared and every subscribed worker reconciles its own running tasks against durable status on receipt.Worker-control hints are lossy: durable status remains authoritative, and a dropped hint costs cancellation latency, never correctness.
- async assign_worker(task_id: UUID, *, worker_id: str, expected_retry_count: int) QueuedTaskRecord | None[source]#
Persist the owner of a running retry generation.
The write is fenced on
status='running' AND retry_count = expectedso a worker can never claim ownership of a generation it lost.- Parameters:
task_id – Queue record identifier.
worker_id – Identity to persist as the record owner.
expected_retry_count – Retry generation the caller believes it owns.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async list_pending(*, limit: int = 1, queue: str | None = None, execution_backend: str | None = None) list[QueuedTaskRecord][source]#
Return due pending or scheduled tasks ordered for execution.
- async claim_task(task_id: UUID, *, expected_retry_count: int | None = None, expected_execution_ref: str | None = None) QueuedTaskRecord | None[source]#
Atomically claim a pending task.
- async claim_task_with_expired(task_id: UUID, *, expected_retry_count: int | None = None, expected_execution_ref: str | None = None) tuple[QueuedTaskRecord | None, QueuedTaskRecord | None][source]#
Claim one task and return an expiry transitioned under the same lock.
- async claim_many(*, limit: int, queues: tuple[str, ...] = (), execution_backend: str | None = None, queue_limits: Mapping[str, int] | None = None) list[QueuedTaskRecord][source]#
Claim up to
limitdue tasks under a single lock acquisition.Selects eligible records with the same queue/execution/due filter and priority ordering as
list_pending(), then transitions them torunninginside one critical section using a singlenowsnapshot. The returned records carry the same owner/start/heartbeat fields a sequentialclaim_next()loop would produce.- Returns:
Claimed task records in claim order.
- async claim_many_with_expired(*, limit: int, queues: tuple[str, ...] = (), execution_backend: str | None = None, queue_limits: Mapping[str, int] | None = None) tuple[list[QueuedTaskRecord], list[QueuedTaskRecord]][source]#
Claim records and return overdue records expired under the same lock.
- async complete_task(task_id: UUID, *, result: Any = None, expected_retry_count: int | None = None) QueuedTaskRecord | None[source]#
Mark a task as completed.
- Parameters:
task_id – Queue record identifier.
result – Task result payload.
expected_retry_count – When provided, update only if the record is still running with this retry count.
- async fail_task(task_id: UUID, error: str, *, retry: bool = True, expected_retry_count: int | None = None, retry_at: datetime | None = None, queued_at: datetime | None = None) QueuedTaskRecord | None[source]#
Mark a task as failed or retry it.
- Parameters:
task_id – Queue record identifier.
error – Error message to persist.
retry – Whether retry policy may requeue the task.
expected_retry_count – When provided, update only if the record is still running with this retry count.
retry_at – Scheduled eligibility timestamp for a delayed retry.
queued_at – Queue ordering timestamp for the new retry attempt.
- async cancel_task(task_id: UUID, *, include_running: bool = False, expected_retry_count: int | None = None) bool[source]#
Cancel a task.
- Parameters:
task_id – ID of the task to cancel.
include_running – Whether to cancel a task that is currently running.
expected_retry_count – Only cancel if the task is still on this retry generation.
- Returns:
True if the task was successfully cancelled, False otherwise.
- async interrupt_task(task_id: UUID, *, expected_retry_count: int, worker_id: str, queued_at: datetime) QueuedTaskRecord | None[source]#
Return an owned running attempt to pending after interruption.
The write is fenced on
status='running' AND retry_count = expected AND worker_id = worker_id. It resets the record topendingwith a freshqueued_atand clearsscheduled_at,started_at,heartbeat_at,completed_at,execution_ref, andworker_id.- Parameters:
task_id – Queue record identifier.
expected_retry_count – Retry generation the caller owns.
worker_id – Identity that must currently own the record.
queued_at – Requeue timestamp used for fair claim ordering.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async cancel_tasks(*, task_name: str | None = None, queue: str | None = None, kwargs: Mapping[str, Any] | None = None, metadata: Mapping[str, Any] | None = None, include_running: bool = False) int[source]#
Cancel tasks matching a domain predicate.
- Parameters:
task_name – Optional task name exact match.
queue – Optional queue exact match.
kwargs – Optional top-level kwargs exact-match subset.
metadata – Optional top-level metadata exact-match subset.
include_running – When true, running records are included for cooperative cancellation.
- Returns:
Number of records cancelled.
- async touch_heartbeats(touches: Sequence[HeartbeatTouch]) HeartbeatTouchResult[source]#
Update heartbeat timestamps for running tasks.
- Returns:
The task IDs confirmed touched or missed by the backend.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async null_heartbeats(task_ids: list[UUID], *, expected_retry_count: int | None = None) None[source]#
Clear heartbeat timestamps for task IDs.
- Parameters:
task_ids – Queue record identifiers.
expected_retry_count – When provided, clear only records that still match this retry count.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async requeue_stale_running(*, stale_after: timedelta, limit: int | None = None) StaleTaskRecoveryResult[source]#
Recover running tasks with stale heartbeats.
- Parameters:
stale_after – Heartbeat age past which a running task is stale.
limit – When provided, recover at most this many records ordered oldest-first (oldest heartbeat, then record id).
Nonepreserves the historical unbounded behavior; bounded maintenance always supplies a positive limit.
- Returns:
Summary of requeued, failed, skipped, and handler-needed records.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async expire_overdue(*, limit: int | None = None) list[QueuedTaskRecord][source]#
Transition overdue pending or scheduled records to
expired.- Returns:
Records transitioned during this call.
- async reserve_external_dispatch(task_id: UUID, execution_backend: str, reservation_ref: str, *, execution_profile: str | None = None, expected_retry_count: int | None = None) QueuedTaskRecord | None[source]#
Atomically reserve a due, unexpired task for external dispatch.
The default rejects dispatch because a read-then-write fallback cannot protect the external side effect.
- async clear_execution_ref(task_id: UUID, expected_retry_count: int, expected_execution_ref: str) QueuedTaskRecord | None[source]#
Clear an exact pending external attempt and wake dispatchers.
- async replace_execution_ref(task_id: UUID, expected_retry_count: int, expected_execution_ref: str, execution_ref: str) QueuedTaskRecord | None[source]#
Atomically rotate an exact pending external attempt reference.
- async release_external_dispatch(task_id: UUID, reservation_ref: str, execution_backend: str, *, execution_profile: str | None = None) QueuedTaskRecord | None[source]#
Release a matching external-dispatch reservation.
- async finalize_external_dispatch(task_id: UUID, reservation_ref: str, execution_backend: str, execution_ref: str, *, execution_profile: str | None = None) QueuedTaskRecord | None[source]#
Replace an owned dispatch reservation with its execution reference.
- async set_execution_ref(task_id: UUID, execution_backend: str, execution_ref: str, *, execution_profile: str | None = None) QueuedTaskRecord | None[source]#
Persist an external execution reference for a running task.
- Returns:
The updated queued task record, if one exists.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async set_execution_backend(task_id: UUID, execution_backend: str, *, execution_profile: str | None = None) QueuedTaskRecord | None[source]#
Persist an execution backend/profile change for a queued task.
- Returns:
The updated queued task record, if one exists.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async list_running_external(*, limit: int | None = None) list[QueuedTaskRecord][source]#
Return externally dispatched tasks with references to reconcile.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async get_statistics(*, queue: str | None = None) QueueStatistics[source]#
Return queue status counts.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async list_completed_by_task(task_name: str, *, since: datetime | None = None, limit: int = 10) list[QueuedTaskRecord][source]#
Return recent completed records for a task name.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async cleanup_terminal(before: datetime, *, limit: int | None = None) int[source]#
Delete terminal records completed before a cutoff.
Routine terminal cleanup never touches
unique_until="forever"reservations; onlyreset_identity()removes them.- Parameters:
before – Delete terminal records completed strictly before this UTC cutoff.
limit – When provided, delete at most this many records ordered oldest-first (oldest
completed_at, then record id).Nonepreserves the historical unbounded behavior; bounded maintenance always supplies a positive limit.
- Returns:
The number of deleted records.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async acquire_maintenance(name: str, token: str, *, ttl: timedelta) bool[source]#
Acquire expiring, token-fenced maintenance ownership under the async lock.
- Returns:
True when ownership was granted to
token.
- async release_maintenance(name: str, token: str) bool[source]#
Release maintenance ownership only when
tokenmatches the holder.- Returns:
True when ownership held under
tokenwas released.
- async reserve_identity(key: str, *, task_id: UUID, task_name: str) TaskReservation | None[source]#
Reserve a forever identity under the shared lock beside key ownership.
- Returns:
Nonewhen this caller won the reservation; otherwise the existing owner reservation.
- async has_identity(key: str) TaskReservation | None[source]#
Return the reservation owning a reserved forever identity, if any.
- async reset_identity(key: str, *, expected_task_id: UUID | None = None) bool[source]#
Delete a forever identity reservation under the shared lock.
- Parameters:
key – The exact effective identity key.
expected_task_id – Optional task owner required for deletion.
- Returns:
Truewhen a reservation was removed.
- async notify_new_task(record: QueuedTaskRecord) None[source]#
Notify waiters that a new task is available.
- async wait_for_wakeups(timeout: float | None = None) bool[source]#
Wait until backend notification arrives.
- Returns:
True when a notification was observed.
- async wait_for_worker_control(*, worker_id: str, timeout: float | None = None) bool[source]#
Wait for a best-effort worker-control hint.
Mirrors
wait_for_wakeups(): polling-only backends inherit this sleep-and-report-nothing default and stay pure-poll.- Returns:
True when a control hint was observed.
In-memory queue event history.
- class litestar_queues.backends.memory.event_log.InMemoryQueueEventLog(config: EventHistoryConfig)[source]#
Bases:
objectProcess-local, bounded queue event history for tests and local usage.
- __init__(config: EventHistoryConfig) None[source]#
- async publish_event(event: QueueEvent) None[source]#
Append an event history record and prune the oldest records.
- async flush_events() None[source]#
Flush buffered events.
The memory event log writes immediately, so this is intentionally a no-op.
- async query_events(query: QueueEventQuery | None = None, *, extra: Mapping[str, str] | None = None) OffsetPagination[QueueEventLogRecord][source]#
Return a filtered, ordered page of event history records.
- Returns:
The matching page.
- async summarize_stages(query: QueueEventQuery | None = None) list[QueueEventStageSummary][source]#
Return per-stage aggregates for the matching records.
- Raises:
QueueConfigurationError – If
querysets ordering or pagination.- Returns:
One summary per distinct stage.
- async cleanup_events(*, before: datetime, match: QueueEventQuery | None = None, exclude: Sequence[QueueEventQuery] = (), limit: int | None = None) int[source]#
Delete the oldest matching records occurring before
before.A record is deleted only when it matches
matchand matches none ofexclude. Deletion order is the ascending stable order key, so repeated bounded calls converge.- Returns:
Number of deleted records.
SQLSpec#
SQLSpec queue backend.
- class litestar_queues.backends.sqlspec.backend.SQLSpecQueueBackend(config: QueueConfig | None = None, *, backend_config: SQLSpecBackendConfig | None = None)[source]#
Bases:
BaseQueueBackendSQLSpec-backed queue backend.
- __init__(config: QueueConfig | None = None, *, backend_config: SQLSpecBackendConfig | None = None) None[source]#
Initialize the queue backend.
- get_event_log(config: EventHistoryConfig) QueueEventLog | None[source]#
Return SQLSpec-managed durable queue event history when enabled.
- property capabilities: QueueBackendCapabilities#
Backend behavior capabilities.
- async enqueue(task_name: str, *, args: tuple[Any, ...] = (), kwargs: dict[str, Any] | None = None, queue: str = 'default', priority: int = 0, max_retries: int = 0, scheduled_at: datetime | None = None, expires_at: datetime | None = None, key: str | None = None, execution_backend: str = 'local', execution_profile: str | None = None, metadata: dict[str, Any] | None = None, id: UUID | None = None) QueuedTaskRecord[source]#
Persist a queued task.
When
idis provided the persisted record uses it instead of a freshly generated identifier; the service pre-generates it forunique_until="forever"enqueues so the identity reservation and the executable record share one id.
- async enqueue_many(requests: Sequence[TaskRequest]) list[QueuedTaskRecord][source]#
Persist many tasks via the adapter’s fastest bulk path.
Resolves existing deduplication keys in one round trip, then inserts the remaining rows through the native Arrow ingest path (
load_from_records()) when the adapter supports it, otherwise via a batchedexecute_many. Returns records in input order, with existing non-terminal keyed tasks returned as-is (no duplicate insert) to match the semantics ofenqueue().- Returns:
Queue task records in the same order as
requests.
- async get_task(task_id: UUID) QueuedTaskRecord | None[source]#
Return a queued task by ID.
- async get_task_by_key(key: str) QueuedTaskRecord | None[source]#
Return a queued task by deduplication key.
- async reserve_identity(key: str, *, task_id: UUID, task_name: str) TaskReservation | None[source]#
Reserve a forever identity via an optimistic insert with a unique-violation fallback.
The reservation table’s identity-key PRIMARY KEY is the atomicity arbiter: exactly one concurrent insert wins; a loser catches the unique violation and reads the winning owner. Serializable engines (CockroachDB) may abort a losing transaction with a serialization/retry error before the unique violation surfaces, so those are retried with bounded backoff. The reservation table is separate from the queue table and terminal cleanup never touches it.
- Returns:
Nonewhen this caller won the reservation; otherwise the existing owner reservation.
- async has_identity(key: str) TaskReservation | None[source]#
Return the reservation owning a reserved forever identity, if any.
- async reset_identity(key: str, *, expected_task_id: UUID | None = None) bool[source]#
Delete a forever identity reservation via count-then-delete.
- Returns:
Truewhen a reservation was removed.
- async list_pending(*, limit: int = 1, queue: str | None = None, execution_backend: str | None = None) list[QueuedTaskRecord][source]#
Return due pending or scheduled tasks ordered for execution.
- async claim_task(task_id: UUID, *, expected_retry_count: int | None = None, expected_execution_ref: str | None = None) QueuedTaskRecord | None[source]#
Atomically claim a pending task.
- async claim_task_with_expired(task_id: UUID, *, expected_retry_count: int | None = None, expected_execution_ref: str | None = None) tuple[QueuedTaskRecord | None, QueuedTaskRecord | None][source]#
Claim one task and identify a claim-time expiry owned by this call.
- async expire_overdue(*, limit: int | None = None) list[QueuedTaskRecord][source]#
Transition overdue pending or scheduled records to
expired.
- async claim_many(*, limit: int, queues: tuple[str, ...] = (), execution_backend: str | None = None, queue_limits: Mapping[str, int] | None = None) list[QueuedTaskRecord][source]#
Claim up to
limitdue tasks.Postgres-family stores use one autocommit
UPDATE ... FROM (SELECT ... FOR UPDATE SKIP LOCKED LIMIT $n) ... RETURNINGstatement. Other adapters fall back to the per-record claim loop.- Returns:
Claimed task records.
- async claim_many_with_expired(*, limit: int, queues: tuple[str, ...] = (), execution_backend: str | None = None, queue_limits: Mapping[str, int] | None = None) tuple[list[QueuedTaskRecord], list[QueuedTaskRecord]][source]#
Claim records and report every expiry transition owned by this call.
- async claim_next(*, queues: tuple[str, ...] = (), execution_backend: str | None = None) QueuedTaskRecord | None[source]#
Claim the next due task across the requested queues.
An empty
queuestuple claims across all queues.- Returns:
The claimed task record, if one was available.
- async complete_task(task_id: UUID, *, result: Any | None = None, expected_retry_count: int | None = None) QueuedTaskRecord | None[source]#
Mark a task as completed.
- Parameters:
task_id – Queue record identifier.
result – Task result payload.
expected_retry_count – When provided, update only if the record is still running with this retry count.
- async fail_task(task_id: UUID, error: str, *, retry: bool = True, expected_retry_count: int | None = None, retry_at: datetime | None = None, queued_at: datetime | None = None) QueuedTaskRecord | None[source]#
Mark a task as failed or retry it.
- Parameters:
task_id – Queue record identifier.
error – Error message to persist.
retry – Whether retry policy may requeue the task.
expected_retry_count – When provided, update only if the record is still running with this retry count.
retry_at – Scheduled eligibility timestamp for a delayed retry.
queued_at – Queue ordering timestamp for the new retry attempt.
- async assign_worker(task_id: UUID, *, worker_id: str, expected_retry_count: int) QueuedTaskRecord | None[source]#
Persist the owner of a running retry generation.
The write is fenced on
status='running' AND retry_count = expectedso a worker can never claim ownership of a generation it lost.- Parameters:
task_id – Queue record identifier.
worker_id – Identity to persist as the record owner.
expected_retry_count – Retry generation the caller believes it owns.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async interrupt_task(task_id: UUID, *, expected_retry_count: int, worker_id: str, queued_at: datetime) QueuedTaskRecord | None[source]#
Return an owned running attempt to pending after interruption.
The write is fenced on
status='running' AND retry_count = expected AND worker_id = worker_id. It resets the record topendingwith a freshqueued_atand clearsscheduled_at,started_at,heartbeat_at,completed_at,execution_ref, andworker_id.- Parameters:
task_id – Queue record identifier.
expected_retry_count – Retry generation the caller owns.
worker_id – Identity that must currently own the record.
queued_at – Requeue timestamp used for fair claim ordering.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async cancel_task(task_id: UUID, *, include_running: bool = False, expected_retry_count: int | None = None) bool[source]#
Cancel a task.
- Parameters:
task_id – ID of the task to cancel.
include_running – Whether to cancel a task that is currently running.
expected_retry_count – Only cancel if the task is still on this retry generation.
- Returns:
True if the task was successfully cancelled, False otherwise.
- async cancel_tasks(*, task_name: str | None = None, queue: str | None = None, kwargs: Mapping[str, Any] | None = None, metadata: Mapping[str, Any] | None = None, include_running: bool = False) int[source]#
Cancel tasks matching a domain predicate.
- Parameters:
task_name – Optional task name exact match.
queue – Optional queue exact match.
kwargs – Optional top-level kwargs exact-match subset.
metadata – Optional top-level metadata exact-match subset.
include_running – When true, running records are included for cooperative cancellation.
- Returns:
Number of records cancelled.
- async touch_heartbeats(touches: Sequence[HeartbeatTouch]) HeartbeatTouchResult[source]#
Update heartbeat timestamps for running tasks.
- Returns:
The task IDs confirmed touched or missed by the backend.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async null_heartbeats(task_ids: list[UUID], *, expected_retry_count: int | None = None) None[source]#
Clear heartbeat timestamps for task IDs.
- Parameters:
task_ids – Queue record identifiers.
expected_retry_count – When provided, clear only records that still match this retry count.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async requeue_stale_running(*, stale_after: timedelta, limit: int | None = None) StaleTaskRecoveryResult[source]#
Recover running tasks with stale heartbeats.
- Parameters:
stale_after – Heartbeat age past which a running task is stale.
limit – When provided, recover at most this many records ordered oldest-first (oldest heartbeat, then record id).
Nonepreserves the historical unbounded behavior; bounded maintenance always supplies a positive limit.
- Returns:
Summary of requeued, failed, skipped, and handler-needed records.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async set_execution_ref(task_id: UUID, execution_backend: str, execution_ref: str, *, execution_profile: str | None = None) QueuedTaskRecord | None[source]#
Persist an external execution reference for a running task.
- Returns:
The updated queued task record, if one exists.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async reserve_external_dispatch(task_id: UUID, execution_backend: str, reservation_ref: str, *, execution_profile: str | None = None, expected_retry_count: int | None = None) QueuedTaskRecord | None[source]#
Atomically reserve a due, unexpired task for external dispatch.
The default rejects dispatch because a read-then-write fallback cannot protect the external side effect.
- async clear_execution_ref(task_id: UUID, expected_retry_count: int, expected_execution_ref: str) QueuedTaskRecord | None[source]#
Clear an exact pending external attempt and wake dispatchers.
- async replace_execution_ref(task_id: UUID, expected_retry_count: int, expected_execution_ref: str, execution_ref: str) QueuedTaskRecord | None[source]#
Atomically rotate an exact pending external attempt reference.
- async release_external_dispatch(task_id: UUID, reservation_ref: str, execution_backend: str, *, execution_profile: str | None = None) QueuedTaskRecord | None[source]#
Release a matching external-dispatch reservation.
- async finalize_external_dispatch(task_id: UUID, reservation_ref: str, execution_backend: str, execution_ref: str, *, execution_profile: str | None = None) QueuedTaskRecord | None[source]#
Replace an owned dispatch reservation with its execution reference.
- async set_execution_backend(task_id: UUID, execution_backend: str, *, execution_profile: str | None = None) QueuedTaskRecord | None[source]#
Persist an execution backend/profile change for a queued task.
- Returns:
The updated queued task record, if one exists.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async list_running_external(*, limit: int | None = None) list[QueuedTaskRecord][source]#
Return externally dispatched tasks with references to reconcile.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async get_statistics(*, queue: str | None = None) QueueStatistics[source]#
Return queue status counts.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async iter_all(*, chunk_size: int = 1000) AsyncIterator[QueuedTaskRecord][source]#
Stream every queue record without materializing the full table.
Uses SQLSpec
select_streamso large administrative scans and exports consume rows in chunks ofchunk_sizerather than loading the entire result set into memory. The backend session stays open for the duration of iteration, so callers should consume the iterator promptly.- Yields:
Queue task records from the backing SQLSpec table.
- async list_completed_by_task(task_name: str, *, since: datetime | None = None, limit: int = 10) list[QueuedTaskRecord][source]#
Return recent completed records for a task name.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async cleanup_terminal(before: datetime, *, limit: int | None = None) int[source]#
Delete terminal records completed before a cutoff.
Routine terminal cleanup never touches
unique_until="forever"reservations; onlyreset_identity()removes them.- Parameters:
before – Delete terminal records completed strictly before this UTC cutoff.
limit – When provided, delete at most this many records ordered oldest-first (oldest
completed_at, then record id).Nonepreserves the historical unbounded behavior; bounded maintenance always supplies a positive limit.
- Returns:
The number of deleted records.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async acquire_maintenance(name: str, token: str, *, ttl: timedelta) bool[source]#
Acquire maintenance ownership via an adapter-portable compare-and-set.
Updates the named row to this token when its stored ownership has expired; if a live row is present the update matches nothing and the row’s token differs, so ownership is denied. When no row exists a fresh one is inserted, and a uniqueness race is treated as ownership denial. The select-after-update read makes correctness independent of the adapter’s
rows_affectedreliability.- Returns:
True when maintenance ownership is held under
token.
- async release_maintenance(name: str, token: str) bool[source]#
Release maintenance ownership only when the stored token matches.
- Returns:
True when ownership held under
tokenwas deleted and no successor replaced it before the transaction’s postcondition check.
- async notify_new_task(record: QueuedTaskRecord) None[source]#
Publish a SQLSpec event when configured queue work becomes available.
- async wait_for_wakeups(timeout: float | None = None) bool[source]#
Wait for a SQLSpec event when queue notifications are configured.
One
iter_eventsstream and its pendinganextread are retained across worker poll timeouts; only an event, a driver failure, or backend close ends them.- Returns:
True when a notification was received.
- async notify_worker_control(worker_id: str | None) None[source]#
Publish a worker-control hint on the SQLSpec events channel.
On the Postgres drivers this is a LISTEN/NOTIFY message. The hint is lossy by contract: it only shortens the wait before the owning worker reconciles durable status.
- async wait_for_worker_control(*, worker_id: str, timeout: float | None = None) bool[source]#
Wait for a SQLSpec worker-control hint.
One
iter_eventsstream and its pending read are retained across worker poll timeouts, exactly like the wakeup stream, and are never shared with it.- Returns:
True when a control hint was observed.
- Raises:
Exception – Whatever the event read raised, after the stream is closed so the next wait re-establishes it.
SQLSpec backend configuration.
- litestar_queues.backends.sqlspec.config.WAKEUP_TRANSPORTS: frozenset[str] = frozenset({'aq', 'notify', 'notify_queue', 'poll_queue', 'polling', 'txeventq'})#
Valid worker-wakeup transports for
SQLSpecWorkerWakeupConfig.transport.notifyuses native push wakeups,notify_queueuses native push wakeups with a durable queue fallback,poll_queueuses the durable events table,aqandtxeventquse Oracle Advanced Queuing backends, andpollingdisables push wakeups so workers fall back to interval polling.
- class litestar_queues.backends.sqlspec.config.SQLSpecBackendConfig(sqlspec: SQLSpec | None = None, sqlspec_config: SQLSpecStoreConfig | None = None, heartbeat_pool_config: SQLSpecStoreConfig | None = None, queue_table_name: str | None = None, worker_wakeups: SQLSpecWorkerWakeupConfig | None = <factory>, event_history_table_name: str | None = None, event_history_extra_columns: tuple[EventHistoryExtraColumn, ...] = (), maintenance_table_name: str | None = None, task_reservation_table_name: str | None = None, column_map: Mapping[str, str] = <factory>, native_json_columns: frozenset[str] = <factory>, manage_schema: bool = True)[source]#
Bases:
objectConfiguration values for the SQLSpec queue backend.
- sqlspec: SQLSpec | None#
Injected SQLSpec manager;
Nonecreates a manager owned by the queue backend.
- sqlspec_config: SQLSpecStoreConfig | None#
SQLSpec adapter configuration used for queue operations;
Noneresolves or creates one.
- heartbeat_pool_config: SQLSpecStoreConfig | None#
Dedicated heartbeat adapter configuration;
Nonereuses normal queue operations.
- queue_table_name: str | None#
Queue-task table name;
Noneusesqueue_taskor SQLSpec extension settings.
- __init__(sqlspec: SQLSpec | None = None, sqlspec_config: SQLSpecStoreConfig | None = None, heartbeat_pool_config: SQLSpecStoreConfig | None = None, queue_table_name: str | None = None, worker_wakeups: SQLSpecWorkerWakeupConfig | None = <factory>, event_history_table_name: str | None = None, event_history_extra_columns: tuple[EventHistoryExtraColumn, ...] = (), maintenance_table_name: str | None = None, task_reservation_table_name: str | None = None, column_map: Mapping[str, str] = <factory>, native_json_columns: frozenset[str] = <factory>, manage_schema: bool = True) None#
- worker_wakeups: SQLSpecWorkerWakeupConfig | None#
Worker wakeup transport configuration;
Nonedisables wakeups.
- event_history_table_name: str | None#
Task-event history table name;
Nonederives it from the queue-task table.
- event_history_extra_columns: tuple[EventHistoryExtraColumn, ...]#
Adopter-declared extra scoping columns on the event-history table.
- maintenance_table_name: str | None#
Maintenance coordination table name;
Nonederives the package default.
- task_reservation_table_name: str | None#
Permanent task-reservation table name;
Nonederives it from the queue-task table.
- column_map: Mapping[str, str]#
Overrides mapping logical queue fields to adopter-owned database columns.
- configure_migrations(config: QueueConfig) None[source]#
Register the queue and durable-events migrations with the SQLSpec config.
Implements
MigrationConfiguringBackend, soQueuePluginreaches this without importing the SQLSpec backend.
- class litestar_queues.backends.sqlspec.config.SQLSpecWorkerWakeupConfig(channel: AsyncEventChannel | None = None, transport: str | None = None, channel_name: str | None = None, queue_table_name: str | None = None, poll_interval: float | None = None, settings: dict[str, Any] = <factory>)[source]#
Bases:
objectSQLSpec worker-wakeup channel and transport configuration.
- channel: AsyncEventChannel | None#
Explicit SQLSpec event channel;
Noneconstructs one from configuration.
Schema and migration helpers for the SQLSpec queue backend.
- litestar_queues.backends.sqlspec.schema.EVENT_HISTORY_COLUMNS = ('event_id', 'event_type', 'task_id', 'task_name', 'queue', 'worker_id', 'execution_backend', 'execution_profile', 'actor_type', 'actor_id', 'stage', 'level', 'message', 'detail', 'progress_current', 'progress_total', 'progress_percent', 'duration_ms', 'sequence', 'occurred_at', 'created_at', 'scope', 'scope_key', 'actor', 'entity')#
Physical columns the package owns on the SQLSpec event-history table.
- litestar_queues.backends.sqlspec.schema.event_history_table_name_for(table_name: str) str[source]#
Return the default event-history table for a queue table name.
Schema-qualified names keep their schema and append
DEFAULT_EVENT_HISTORY_TABLE_SUFFIXto the table part.
- litestar_queues.backends.sqlspec.schema.maintenance_table_name_for(table_name: str) str[source]#
Return the default maintenance table for a queue table name.
Schema-qualified names keep their schema and append
DEFAULT_MAINTENANCE_TABLE_SUFFIXto the table part. When the derived name would exceed the portable identifier limit it is deterministically shortened (truncated table part plus a stable hash) so the packaged migration and the runtime backend agree on one name.
- litestar_queues.backends.sqlspec.schema.migration_directory() Path[source]#
Return the packaged SQLSpec queue extension migration directory.
- litestar_queues.backends.sqlspec.schema.migration_paths() tuple[str, ...][source]#
Return packaged SQLSpec migration file paths.
- litestar_queues.backends.sqlspec.schema.resolve_column_map(column_map: Mapping[str, str] | None = None) dict[str, str][source]#
Return the default physical column map with adopter overrides applied.
- litestar_queues.backends.sqlspec.schema.task_reservation_table_name_for(table_name: str) str[source]#
Return the default forever-uniqueness reservation table for a queue table.
Schema-qualified names keep their schema and append
DEFAULT_TASK_RESERVATION_TABLE_SUFFIXto the table part. Long derived names use the same portable deterministic shortening as maintenance tables.
- litestar_queues.backends.sqlspec.schema.validate_column_map(column_map: Mapping[str, str]) dict[str, str][source]#
Validate a canonical-to-adopter column map.
- Returns:
A defensive copy of the validated map.
- Raises:
QueueConfigurationError – If a canonical name is unknown or a mapped name is not a valid SQL identifier.
- litestar_queues.backends.sqlspec.schema.validate_native_json_columns(columns: frozenset[str]) frozenset[str][source]#
Validate native JSON passthrough columns.
- Returns:
The validated column set.
- Raises:
QueueConfigurationError – If any column is not a canonical JSON column.
- litestar_queues.backends.sqlspec.schema.validate_table_name(table_name: str) str[source]#
Validate a SQL identifier used for the queue table name.
- Returns:
The validated table name, normalized to unquoted SQLSpec identifier parts.
- Raises:
QueueConfigurationError – If the table name is not a valid SQL identifier.
SQLSpec queue store factory.
- litestar_queues.backends.sqlspec.stores.factory.create_queue_store(config: SQLSpecStoreConfig, *, table_name: str | None = None, column_map: Mapping[str, str] | None = None, native_json_columns: frozenset[str] | None = None, manage_schema: bool = True) SQLSpecQueueStore[source]#
Create a queue store for a SQLSpec adapter configuration.
- Returns:
The queue store implementation for the SQLSpec adapter.
SQLSpec-backed queue event history.
- class litestar_queues.backends.sqlspec.event_log.SQLSpecQueueEventLog(*, session_factory: Callable[[], AbstractAsyncContextManager[SQLSpecDriver]], datetime_serializer: Callable[[datetime], datetime | str], config: EventHistoryConfig, store: SQLSpecQueueEventLogStore, runtime_logger: logging.Logger | None = None)[source]#
Bases:
objectBuffered SQLSpec event-history writer and query interface.
- __init__(*, session_factory: Callable[[], AbstractAsyncContextManager[SQLSpecDriver]], datetime_serializer: Callable[[datetime], datetime | str], config: EventHistoryConfig, store: SQLSpecQueueEventLogStore, runtime_logger: logging.Logger | None = None) None[source]#
- property extra_columns: tuple[EventHistoryExtraColumn, ...]#
Declared extra scoping columns for this event log.
- async publish_event(event: QueueEvent) None[source]#
Buffer a queue event and flush when configured thresholds are reached.
- async query_events(query: QueueEventQuery | None = None, *, extra: Mapping[str, str] | None = None) OffsetPagination[QueueEventLogRecord][source]#
Query durable event history records.
- async summarize_stages(query: QueueEventQuery | None = None) list[QueueEventStageSummary][source]#
Return per-stage event history aggregates.
- async cleanup_events(*, before: datetime, match: QueueEventQuery | None = None, exclude: Sequence[QueueEventQuery] = (), limit: int | None = None) int[source]#
Delete event history older than
before.limitbounds one batch, deleting the oldest matching rows first (oldestoccurred_at, thenevent_id).- Returns:
Number of deleted event-history rows.
- class litestar_queues.backends.sqlspec.event_log.SQLSpecQueueEventLogStore(*args: Any, extra_columns: Sequence[EventHistoryExtraColumn] | None = None, **kwargs: Any)[source]#
Bases:
SQLSpecQueueStoreSQLSpec statement store for backend-managed queue event history.
- __init__(*args: Any, extra_columns: Sequence[EventHistoryExtraColumn] | None = None, **kwargs: Any) None[source]#
- property extra_columns: tuple[EventHistoryExtraColumn, ...]#
Adopter-declared extra scoping columns on this event-history table.
- create_statements() list[str][source]#
Return statements that create the event-log table and indexes.
- select_events(query: QueueEventQuery, extra: Mapping[str, str] | None = None) Select[source]#
Return a SELECT for event-log records.
- Raises:
ValueError – If
extranames a column that was not declared.
- summarize_stages(*, task_name: str | None = None) tuple[str, dict[str, Any]][source]#
Return SQL and parameters for per-stage event summaries.
- select_event_ids_before(*, before: DatetimeParam, limit: int | None) Select[source]#
Return a SELECT of the oldest bounded event ids before a cutoff.
- Raises:
ValueError – If
limitis less than 1.
- delete_events_by_ids(*, event_ids: Sequence[str]) Delete[source]#
Return a DELETE statement scoped to the given event ids.
- class litestar_queues.backends.sqlspec.event_log.SpannerQueueEventLogStore(*args: Any, extra_columns: Sequence[EventHistoryExtraColumn] | None = None, **kwargs: Any)[source]#
Bases:
SQLSpecQueueEventLogStore,SpannerQueueStoreSpanner event-log store using native DDL operations.
- litestar_queues.backends.sqlspec.event_log.create_event_log_store(config: SQLSpecStoreConfig, *, queue_table_name: str, event_history_table_name: str | None = None, manage_schema: bool = True, extra_columns: Sequence[EventHistoryExtraColumn] = ()) SQLSpecQueueEventLogStore[source]#
Create an event-log store for a SQLSpec adapter configuration.
- Returns:
SQLSpec event-log store configured for the resolved event-log table.
- litestar_queues.backends.sqlspec.event_log.resolve_event_history_table_name(queue_table_name: str, *, event_history_table_name: str | None = None) str[source]#
Resolve the SQLSpec event-log table name for a queue table.
- Returns:
The explicit event-log table name, or the derived queue-table event log name.
Advanced Alchemy#
Advanced Alchemy queue backend.
- class litestar_queues.backends.advanced_alchemy.backend.SQLAlchemyBackend(config: QueueConfig | None = None, *, backend_config: SQLAlchemyBackendConfig | None = None)[source]#
Bases:
BaseQueueBackendSQLAlchemy queue backend using Advanced Alchemy services.
- __init__(config: QueueConfig | None = None, *, backend_config: SQLAlchemyBackendConfig | None = None) None[source]#
Initialize the queue backend.
- property capabilities: QueueBackendCapabilities#
Backend behavior capabilities.
- get_event_log(config: EventHistoryConfig) AdvancedAlchemyQueueEventLog[source]#
Return Advanced Alchemy-managed queue event history.
- async enqueue(task_name: str, *, args: tuple[Any, ...] = (), kwargs: dict[str, Any] | None = None, queue: str = 'default', priority: int = 0, max_retries: int = 0, scheduled_at: datetime | None = None, expires_at: datetime | None = None, key: str | None = None, execution_backend: str = 'local', execution_profile: str | None = None, metadata: dict[str, Any] | None = None, id: UUID | None = None) QueuedTaskRecord[source]#
Persist a queued task.
When
idis provided the persisted record uses it instead of a freshly generated identifier; the service pre-generates it forunique_until="forever"enqueues so the identity reservation and the executable record share one id.
- async enqueue_many(requests: Sequence[TaskRequest]) list[QueuedTaskRecord][source]#
Persist multiple queued tasks in one Advanced Alchemy operation.
- Returns:
Queue task records in input order.
- async get_task(task_id: UUID) QueuedTaskRecord | None[source]#
Return a queued task by ID.
- async get_task_by_key(key: str) QueuedTaskRecord | None[source]#
Return a queued task by deduplication key.
- async list_pending(*, limit: int = 1, queue: str | None = None, execution_backend: str | None = None) list[QueuedTaskRecord][source]#
Return due pending or scheduled tasks ordered for execution.
- async time_until_next_due(*, queues: tuple[str, ...] = ()) float | None[source]#
Return seconds until the earliest not-yet-due pending/scheduled record.
- Returns:
Seconds until the next due record, or
Nonewhen there is no upcoming scheduled work.
- async claim_task(task_id: UUID, *, expected_retry_count: int | None = None, expected_execution_ref: str | None = None) QueuedTaskRecord | None[source]#
Atomically claim a pending task.
- async claim_task_with_expired(task_id: UUID, *, expected_retry_count: int | None = None, expected_execution_ref: str | None = None) tuple[QueuedTaskRecord | None, QueuedTaskRecord | None][source]#
Claim one task and report when this call expires that task.
- Returns:
The claimed record and the expired record, at most one of which is set.
- async claim_next(*, queues: tuple[str, ...] = (), execution_backend: str | None = None) QueuedTaskRecord | None[source]#
Claim the next due task across the requested queues.
An empty
queuestuple claims across all queues.- Returns:
The claimed task record, if one was available.
- async claim_many(*, limit: int, queues: tuple[str, ...] = (), execution_backend: str | None = None, queue_limits: Mapping[str, int] | None = None) list[QueuedTaskRecord][source]#
Claim up to
limitdue tasks across the requested queues.- Returns:
Claimed task records.
- async claim_many_with_expired(*, limit: int, queues: tuple[str, ...] = (), execution_backend: str | None = None, queue_limits: Mapping[str, int] | None = None) tuple[list[QueuedTaskRecord], list[QueuedTaskRecord]][source]#
Claim records and report expiry transitions from the same transactions.
- async complete_task(task_id: UUID, *, result: Any = None, expected_retry_count: int | None = None) QueuedTaskRecord | None[source]#
Mark a task as completed.
- Parameters:
task_id – Queue record identifier.
result – Task result payload.
expected_retry_count – When provided, update only if the record is still running with this retry count.
- async fail_task(task_id: UUID, error: str, *, retry: bool = True, expected_retry_count: int | None = None, retry_at: datetime | None = None, queued_at: datetime | None = None) QueuedTaskRecord | None[source]#
Mark a task as failed or retry it.
- Parameters:
task_id – Queue record identifier.
error – Error message to persist.
retry – Whether retry policy may requeue the task.
expected_retry_count – When provided, update only if the record is still running with this retry count.
retry_at – Scheduled eligibility timestamp for a delayed retry.
queued_at – Queue ordering timestamp for the new retry attempt.
- async assign_worker(task_id: UUID, *, worker_id: str, expected_retry_count: int) QueuedTaskRecord | None[source]#
Persist the owner of a running retry generation.
The write is fenced on
status='running' AND retry_count = expectedso a worker can never claim ownership of a generation it lost.- Parameters:
task_id – Queue record identifier.
worker_id – Identity to persist as the record owner.
expected_retry_count – Retry generation the caller believes it owns.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async interrupt_task(task_id: UUID, *, expected_retry_count: int, worker_id: str, queued_at: datetime) QueuedTaskRecord | None[source]#
Return an owned running attempt to pending after interruption.
The write is fenced on
status='running' AND retry_count = expected AND worker_id = worker_id. It resets the record topendingwith a freshqueued_atand clearsscheduled_at,started_at,heartbeat_at,completed_at,execution_ref, andworker_id.- Parameters:
task_id – Queue record identifier.
expected_retry_count – Retry generation the caller owns.
worker_id – Identity that must currently own the record.
queued_at – Requeue timestamp used for fair claim ordering.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async cancel_task(task_id: UUID, *, include_running: bool = False, expected_retry_count: int | None = None) bool[source]#
Cancel a task.
- Parameters:
task_id – ID of the task to cancel.
include_running – Whether to cancel a task that is currently running.
expected_retry_count – Only cancel if the task is still on this retry generation.
- Returns:
True if the task was successfully cancelled, False otherwise.
- async cancel_tasks(*, task_name: str | None = None, queue: str | None = None, kwargs: Mapping[str, Any] | None = None, metadata: Mapping[str, Any] | None = None, include_running: bool = False) int[source]#
Cancel tasks matching a domain predicate.
- Parameters:
task_name – Optional task name exact match.
queue – Optional queue exact match.
kwargs – Optional top-level kwargs exact-match subset.
metadata – Optional top-level metadata exact-match subset.
include_running – When true, running records are included for cooperative cancellation.
- Returns:
Number of records cancelled.
- async touch_heartbeats(touches: Sequence[HeartbeatTouch]) HeartbeatTouchResult[source]#
Update heartbeat timestamps for running tasks.
- Returns:
The task IDs confirmed touched or missed by the backend.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async null_heartbeats(task_ids: list[UUID], *, expected_retry_count: int | None = None) None[source]#
Clear heartbeat timestamps for task IDs.
- Parameters:
task_ids – Queue record identifiers.
expected_retry_count – When provided, clear only records that still match this retry count.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async requeue_stale_running(*, stale_after: timedelta, limit: int | None = None) StaleTaskRecoveryResult[source]#
Recover running tasks with stale heartbeats.
- Parameters:
stale_after – Heartbeat age past which a running task is stale.
limit – When provided, recover at most this many records ordered oldest-first (oldest heartbeat, then record id).
Nonepreserves the historical unbounded behavior; bounded maintenance always supplies a positive limit.
- Returns:
Summary of requeued, failed, skipped, and handler-needed records.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async set_execution_ref(task_id: UUID, execution_backend: str, execution_ref: str, *, execution_profile: str | None = None) QueuedTaskRecord | None[source]#
Persist an external execution reference for a running task.
- Returns:
The updated queued task record, if one exists.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async reserve_external_dispatch(task_id: UUID, execution_backend: str, reservation_ref: str, *, execution_profile: str | None = None, expected_retry_count: int | None = None) QueuedTaskRecord | None[source]#
Atomically reserve a due, unexpired task for external dispatch.
The default rejects dispatch because a read-then-write fallback cannot protect the external side effect.
- async clear_execution_ref(task_id: UUID, expected_retry_count: int, expected_execution_ref: str) QueuedTaskRecord | None[source]#
Clear an exact pending external attempt and wake dispatchers.
- async replace_execution_ref(task_id: UUID, expected_retry_count: int, expected_execution_ref: str, execution_ref: str) QueuedTaskRecord | None[source]#
Atomically rotate an exact pending external attempt reference.
- async release_external_dispatch(task_id: UUID, reservation_ref: str, execution_backend: str, *, execution_profile: str | None = None) QueuedTaskRecord | None[source]#
Release a matching external-dispatch reservation.
- async finalize_external_dispatch(task_id: UUID, reservation_ref: str, execution_backend: str, execution_ref: str, *, execution_profile: str | None = None) QueuedTaskRecord | None[source]#
Replace an owned dispatch reservation with its execution reference.
- async set_execution_backend(task_id: UUID, execution_backend: str, *, execution_profile: str | None = None) QueuedTaskRecord | None[source]#
Persist an execution backend/profile change for a queued task.
- Returns:
The updated queued task record, if one exists.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async notify_new_task(record: QueuedTaskRecord) None[source]#
Publish a PostgreSQL worker wakeup marker when enabled.
- async notify_new_tasks(records: Sequence[QueuedTaskRecord]) None[source]#
Coalesce a batch of task records into at most one wakeup marker.
- async wait_for_wakeups(timeout: float | None = None) bool[source]#
Wait for a PostgreSQL worker wakeup marker when configured.
- Returns:
True when a wakeup marker or due-row reconciliation is observed.
- async list_running_external(*, limit: int | None = None) list[QueuedTaskRecord][source]#
Return externally dispatched tasks with references to reconcile.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async get_statistics(*, queue: str | None = None) QueueStatistics[source]#
Return queue status counts.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async expire_overdue(*, limit: int | None = None) list[QueuedTaskRecord][source]#
Transition overdue pending or scheduled records to
expired.- Returns:
Records transitioned to
expired.- Raises:
NotImplementedError – Always; every backend must answer this.
- async list_completed_by_task(task_name: str, *, since: datetime | None = None, limit: int = 10) list[QueuedTaskRecord][source]#
Return recent completed records for a task name.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async cleanup_terminal(before: datetime, *, limit: int | None = None) int[source]#
Delete terminal records completed before a cutoff.
Routine terminal cleanup never touches
unique_until="forever"reservations; onlyreset_identity()removes them.- Parameters:
before – Delete terminal records completed strictly before this UTC cutoff.
limit – When provided, delete at most this many records ordered oldest-first (oldest
completed_at, then record id).Nonepreserves the historical unbounded behavior; bounded maintenance always supplies a positive limit.
- Returns:
The number of deleted records.
- Raises:
NotImplementedError – Always; every backend must answer this.
- async acquire_maintenance(name: str, token: str, *, ttl: timedelta) bool[source]#
Acquire maintenance ownership via a portable compare-and-set.
Updates an existing expired row for
nameto this token; if no row was expired, inserts a fresh one inside a savepoint so a uniqueness race (live ownership held elsewhere) is treated as a denied acquisition.- Returns:
True when maintenance ownership is held under
token.
- async release_maintenance(name: str, token: str) bool[source]#
Release maintenance ownership only when
tokenmatches the holder.- Returns:
True when ownership held under
tokenwas deleted.
- async reserve_identity(key: str, *, task_id: UUID, task_name: str) TaskReservation | None[source]#
Reserve a forever identity via select-then-insert with an integrity fallback.
The reservation table’s unique
identity_keycolumn is the atomicity arbiter: a losing concurrent insert surfaces an integrity error and the loser re-reads the winning owner. The reservation table is separate from the task table and terminal cleanup never touches it.- Returns:
Nonewhen this caller won the reservation; otherwise the existing owner reservation.
- async has_identity(key: str) TaskReservation | None[source]#
Return the reservation owning a reserved forever identity, if any.
- async reset_identity(key: str, *, expected_task_id: UUID | None = None) bool[source]#
Delete a forever identity reservation via atomic compare-and-delete.
- Parameters:
key – The exact effective identity key.
expected_task_id – Optional task owner required for deletion.
- Returns:
Truewhen a reservation was removed.
Advanced Alchemy backend configuration.
- class litestar_queues.backends.advanced_alchemy.config.SQLAlchemyBackendConfig(sqlalchemy_config: SQLAlchemyAsyncConfig | None = None, heartbeat_session_maker: async_sessionmaker[AsyncSession] | None = None, model_class: type[object] | None = <factory>, event_history_model_class: type[object] | None = <factory>, maintenance_model_class: type[object] | None = <factory>, task_reservation_model_class: type[object] | None = <factory>, worker_wakeups: bool = False, wakeup_channel: str | None = None, wakeup_poll_interval: float | None = None)[source]#
Bases:
objectConfiguration values for the SQLAlchemy queue backend.
- sqlalchemy_config: SQLAlchemyAsyncConfig | None#
Advanced Alchemy async configuration;
Nonerequires an explicit session maker.
- heartbeat_session_maker: async_sessionmaker[AsyncSession] | None#
Dedicated heartbeat session factory;
Nonereuses the configured database path.
- model_class: type[object] | None#
Queue-task ORM model;
Nonedisables package-managed task persistence.
- event_history_model_class: type[object] | None#
Task-event history ORM model;
Nonedisables history support.
- maintenance_model_class: type[object] | None#
Maintenance coordination ORM model;
Nonedisables maintenance support.
- __init__(sqlalchemy_config: SQLAlchemyAsyncConfig | None = None, heartbeat_session_maker: async_sessionmaker[AsyncSession] | None = None, model_class: type[object] | None = <factory>, event_history_model_class: type[object] | None = <factory>, maintenance_model_class: type[object] | None = <factory>, task_reservation_model_class: type[object] | None = <factory>, worker_wakeups: bool = False, wakeup_channel: str | None = None, wakeup_poll_interval: float | None = None) None#
- task_reservation_model_class: type[object] | None#
Permanent task-reservation ORM model;
Nonedisables durable reservations.
Advanced Alchemy queue task mixins.
- class litestar_queues.backends.advanced_alchemy.mixins.QueueEventHistoryModelMixin[source]#
Bases:
objectDeclarative mixin carrying generic queue event-history columns and indexes.
- event_id = <sqlalchemy.orm.properties.MappedColumn object>#
- event_type = <sqlalchemy.orm.properties.MappedColumn object>#
- task_id = <sqlalchemy.orm.properties.MappedColumn object>#
- task_name = <sqlalchemy.orm.properties.MappedColumn object>#
- queue = <sqlalchemy.orm.properties.MappedColumn object>#
- worker_id = <sqlalchemy.orm.properties.MappedColumn object>#
- execution_backend = <sqlalchemy.orm.properties.MappedColumn object>#
- execution_profile = <sqlalchemy.orm.properties.MappedColumn object>#
- actor_type = <sqlalchemy.orm.properties.MappedColumn object>#
- actor_id = <sqlalchemy.orm.properties.MappedColumn object>#
- level = <sqlalchemy.orm.properties.MappedColumn object>#
- message = <sqlalchemy.orm.properties.MappedColumn object>#
- stage = <sqlalchemy.orm.properties.MappedColumn object>#
- scope = <sqlalchemy.orm.properties.MappedColumn object>#
- scope_key = <sqlalchemy.orm.properties.MappedColumn object>#
- actor = <sqlalchemy.orm.properties.MappedColumn object>#
- entity = <sqlalchemy.orm.properties.MappedColumn object>#
- detail_json = <sqlalchemy.orm.properties.MappedColumn object>#
- progress_current = <sqlalchemy.orm.properties.MappedColumn object>#
- progress_total = <sqlalchemy.orm.properties.MappedColumn object>#
- progress_percent = <sqlalchemy.orm.properties.MappedColumn object>#
- duration_ms = <sqlalchemy.orm.properties.MappedColumn object>#
- sequence = <sqlalchemy.orm.properties.MappedColumn object>#
- occurred_at = <sqlalchemy.orm.properties.MappedColumn object>#
- class litestar_queues.backends.advanced_alchemy.mixins.QueueMaintenanceModelMixin[source]#
Bases:
objectDeclarative mixin carrying distributed maintenance coordination columns.
Compose this with an application-owned Advanced Alchemy base that provides a compatible
idprimary key. Adopter-owned model and migration setups must include the resulting table; the queue backend never callsmetadata.create_all.- name = <sqlalchemy.orm.properties.MappedColumn object>#
- token = <sqlalchemy.orm.properties.MappedColumn object>#
- expires_at = <sqlalchemy.orm.properties.MappedColumn object>#
- class litestar_queues.backends.advanced_alchemy.mixins.QueueTaskModelMixin[source]#
Bases:
objectDeclarative mixin carrying queue task columns and indexes.
Compose this with an application-owned Advanced Alchemy base that provides compatible
idandcreated_atcolumns.- task_name = <sqlalchemy.orm.properties.MappedColumn object>#
- args_json = <sqlalchemy.orm.properties.MappedColumn object>#
- kwargs_json = <sqlalchemy.orm.properties.MappedColumn object>#
- queue = <sqlalchemy.orm.properties.MappedColumn object>#
- execution_backend = <sqlalchemy.orm.properties.MappedColumn object>#
- execution_profile = <sqlalchemy.orm.properties.MappedColumn object>#
- execution_ref = <sqlalchemy.orm.properties.MappedColumn object>#
- worker_id = <sqlalchemy.orm.properties.MappedColumn object>#
- status = <sqlalchemy.orm.properties.MappedColumn object>#
- priority = <sqlalchemy.orm.properties.MappedColumn object>#
- max_retries = <sqlalchemy.orm.properties.MappedColumn object>#
- retry_count = <sqlalchemy.orm.properties.MappedColumn object>#
- scheduled_at = <sqlalchemy.orm.properties.MappedColumn object>#
- expires_at = <sqlalchemy.orm.properties.MappedColumn object>#
- queued_at = <sqlalchemy.orm.properties.MappedColumn object>#
- started_at = <sqlalchemy.orm.properties.MappedColumn object>#
- completed_at = <sqlalchemy.orm.properties.MappedColumn object>#
- heartbeat_at = <sqlalchemy.orm.properties.MappedColumn object>#
- result_json = <sqlalchemy.orm.properties.MappedColumn object>#
- error = <sqlalchemy.orm.properties.MappedColumn object>#
- task_key = <sqlalchemy.orm.properties.MappedColumn object>#
- metadata_json = <sqlalchemy.orm.properties.MappedColumn object>#
- class litestar_queues.backends.advanced_alchemy.mixins.QueueTaskReservationModelMixin[source]#
Bases:
objectDeclarative mixin carrying forever-uniqueness reservation columns.
Compose this with an application-owned Advanced Alchemy base that provides compatible
idandcreated_atcolumns. The uniqueidentity_keycolumn is the atomicity arbiter for forever reservations; the table is separate from the queue task table so routine terminal cleanup never touches it. It stores only the identity key and the originating task id/name.- identity_key = <sqlalchemy.orm.properties.MappedColumn object>#
- task_id = <sqlalchemy.orm.properties.MappedColumn object>#
- task_name = <sqlalchemy.orm.properties.MappedColumn object>#
Advanced Alchemy queue task repository.
- class litestar_queues.backends.advanced_alchemy.repository.QueueEventLogRepository(*, statement: ~sqlalchemy.sql.selectable.Select | None = None, session: ~sqlalchemy.ext.asyncio.session.AsyncSession | ~sqlalchemy.ext.asyncio.scoping.async_scoped_session[~sqlalchemy.ext.asyncio.session.AsyncSession], auto_expunge: bool = False, auto_refresh: bool = True, auto_commit: bool = False, order_by: ~typing.List[tuple[str | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any], bool] | ~sqlalchemy.sql.elements.UnaryExpression[~typing.Any]] | tuple[str | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any], bool] | ~sqlalchemy.sql.elements.UnaryExpression[~typing.Any] | None = None, error_messages: ~advanced_alchemy.exceptions.ErrorMessages | type[~advanced_alchemy.utils.dataclass.Empty] | None = <class 'advanced_alchemy.utils.dataclass.Empty'>, load: ~collections.abc.Sequence[~sqlalchemy.orm.strategy_options._AbstractLoad | ~typing.Literal['*'] | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any] | ~sqlalchemy.orm.relationships.RelationshipProperty[~typing.Any] | ~sqlalchemy.orm.interfaces.MapperProperty[~typing.Any] | ~collections.abc.Sequence[~sqlalchemy.orm.strategy_options._AbstractLoad | ~typing.Literal['*'] | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any] | ~sqlalchemy.orm.relationships.RelationshipProperty[~typing.Any] | ~sqlalchemy.orm.interfaces.MapperProperty[~typing.Any]]] | ~sqlalchemy.orm.strategy_options._AbstractLoad | ~typing.Literal['*'] | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any] | ~sqlalchemy.orm.relationships.RelationshipProperty[~typing.Any] | ~sqlalchemy.orm.interfaces.MapperProperty[~typing.Any] | ~sqlalchemy.sql.base.ExecutableOption | ~collections.abc.Sequence[~sqlalchemy.sql.base.ExecutableOption] | None = None, execution_options: dict[str, ~typing.Any] | None = None, wrap_exceptions: bool = True, uniquify: bool | None = None, count_with_window_function: bool | None = None, cache_manager: CacheManager | None = None, bind_group: str | None = None, **kwargs: ~typing.Any)[source]#
Bases:
SQLAlchemyAsyncRepository[Any]Repository for queue event-history records.
- classmethod for_model(model_class: type[QueueEventHistoryModelMixin]) type['QueueEventLogRepository'][source]#
Return a repository subclass bound to
model_class.
- class litestar_queues.backends.advanced_alchemy.repository.QueueTaskRepository(*, statement: ~sqlalchemy.sql.selectable.Select | None = None, session: ~sqlalchemy.ext.asyncio.session.AsyncSession | ~sqlalchemy.ext.asyncio.scoping.async_scoped_session[~sqlalchemy.ext.asyncio.session.AsyncSession], auto_expunge: bool = False, auto_refresh: bool = True, auto_commit: bool = False, order_by: ~typing.List[tuple[str | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any], bool] | ~sqlalchemy.sql.elements.UnaryExpression[~typing.Any]] | tuple[str | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any], bool] | ~sqlalchemy.sql.elements.UnaryExpression[~typing.Any] | None = None, error_messages: ~advanced_alchemy.exceptions.ErrorMessages | type[~advanced_alchemy.utils.dataclass.Empty] | None = <class 'advanced_alchemy.utils.dataclass.Empty'>, load: ~collections.abc.Sequence[~sqlalchemy.orm.strategy_options._AbstractLoad | ~typing.Literal['*'] | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any] | ~sqlalchemy.orm.relationships.RelationshipProperty[~typing.Any] | ~sqlalchemy.orm.interfaces.MapperProperty[~typing.Any] | ~collections.abc.Sequence[~sqlalchemy.orm.strategy_options._AbstractLoad | ~typing.Literal['*'] | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any] | ~sqlalchemy.orm.relationships.RelationshipProperty[~typing.Any] | ~sqlalchemy.orm.interfaces.MapperProperty[~typing.Any]]] | ~sqlalchemy.orm.strategy_options._AbstractLoad | ~typing.Literal['*'] | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any] | ~sqlalchemy.orm.relationships.RelationshipProperty[~typing.Any] | ~sqlalchemy.orm.interfaces.MapperProperty[~typing.Any] | ~sqlalchemy.sql.base.ExecutableOption | ~collections.abc.Sequence[~sqlalchemy.sql.base.ExecutableOption] | None = None, execution_options: dict[str, ~typing.Any] | None = None, wrap_exceptions: bool = True, uniquify: bool | None = None, count_with_window_function: bool | None = None, cache_manager: CacheManager | None = None, bind_group: str | None = None, **kwargs: ~typing.Any)[source]#
Bases:
SQLAlchemyAsyncRepository[Any]Repository for queue task records.
- classmethod for_model(model_class: type[QueueTaskModelMixin]) type['QueueTaskRepository'][source]#
Return a repository subclass bound to
model_class.
- class litestar_queues.backends.advanced_alchemy.repository.QueueTaskReservationRepository(*, statement: ~sqlalchemy.sql.selectable.Select | None = None, session: ~sqlalchemy.ext.asyncio.session.AsyncSession | ~sqlalchemy.ext.asyncio.scoping.async_scoped_session[~sqlalchemy.ext.asyncio.session.AsyncSession], auto_expunge: bool = False, auto_refresh: bool = True, auto_commit: bool = False, order_by: ~typing.List[tuple[str | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any], bool] | ~sqlalchemy.sql.elements.UnaryExpression[~typing.Any]] | tuple[str | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any], bool] | ~sqlalchemy.sql.elements.UnaryExpression[~typing.Any] | None = None, error_messages: ~advanced_alchemy.exceptions.ErrorMessages | type[~advanced_alchemy.utils.dataclass.Empty] | None = <class 'advanced_alchemy.utils.dataclass.Empty'>, load: ~collections.abc.Sequence[~sqlalchemy.orm.strategy_options._AbstractLoad | ~typing.Literal['*'] | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any] | ~sqlalchemy.orm.relationships.RelationshipProperty[~typing.Any] | ~sqlalchemy.orm.interfaces.MapperProperty[~typing.Any] | ~collections.abc.Sequence[~sqlalchemy.orm.strategy_options._AbstractLoad | ~typing.Literal['*'] | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any] | ~sqlalchemy.orm.relationships.RelationshipProperty[~typing.Any] | ~sqlalchemy.orm.interfaces.MapperProperty[~typing.Any]]] | ~sqlalchemy.orm.strategy_options._AbstractLoad | ~typing.Literal['*'] | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any] | ~sqlalchemy.orm.relationships.RelationshipProperty[~typing.Any] | ~sqlalchemy.orm.interfaces.MapperProperty[~typing.Any] | ~sqlalchemy.sql.base.ExecutableOption | ~collections.abc.Sequence[~sqlalchemy.sql.base.ExecutableOption] | None = None, execution_options: dict[str, ~typing.Any] | None = None, wrap_exceptions: bool = True, uniquify: bool | None = None, count_with_window_function: bool | None = None, cache_manager: CacheManager | None = None, bind_group: str | None = None, **kwargs: ~typing.Any)[source]#
Bases:
SQLAlchemyAsyncRepository[Any]Repository for forever-uniqueness reservations.
- classmethod for_model(model_class: type[QueueTaskReservationModelMixin]) type['QueueTaskReservationRepository'][source]#
Return a repository subclass bound to
model_class.
Advanced Alchemy queue persistence service.
- class litestar_queues.backends.advanced_alchemy.service.QueueEventLogService(session: ~sqlalchemy.ext.asyncio.session.AsyncSession | ~sqlalchemy.ext.asyncio.scoping.async_scoped_session[~sqlalchemy.ext.asyncio.session.AsyncSession], *, statement: ~sqlalchemy.sql.selectable.Select | None = None, auto_expunge: bool = False, auto_refresh: bool = True, auto_commit: bool = False, order_by: ~typing.List[tuple[str | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any], bool] | ~sqlalchemy.sql.elements.UnaryExpression[~typing.Any]] | tuple[str | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any], bool] | ~sqlalchemy.sql.elements.UnaryExpression[~typing.Any] | None = None, error_messages: ~advanced_alchemy.exceptions.ErrorMessages | type[~advanced_alchemy.utils.dataclass.Empty] | None = <class 'advanced_alchemy.utils.dataclass.Empty'>, wrap_exceptions: bool = True, load: ~collections.abc.Sequence[~sqlalchemy.orm.strategy_options._AbstractLoad | ~typing.Literal['*'] | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any] | ~sqlalchemy.orm.relationships.RelationshipProperty[~typing.Any] | ~sqlalchemy.orm.interfaces.MapperProperty[~typing.Any] | ~collections.abc.Sequence[~sqlalchemy.orm.strategy_options._AbstractLoad | ~typing.Literal['*'] | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any] | ~sqlalchemy.orm.relationships.RelationshipProperty[~typing.Any] | ~sqlalchemy.orm.interfaces.MapperProperty[~typing.Any]]] | ~sqlalchemy.orm.strategy_options._AbstractLoad | ~typing.Literal['*'] | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any] | ~sqlalchemy.orm.relationships.RelationshipProperty[~typing.Any] | ~sqlalchemy.orm.interfaces.MapperProperty[~typing.Any] | ~sqlalchemy.sql.base.ExecutableOption | ~collections.abc.Sequence[~sqlalchemy.sql.base.ExecutableOption] | None = None, execution_options: dict[str, ~typing.Any] | None = None, uniquify: bool | None = None, count_with_window_function: bool | None = None, **repo_kwargs: ~typing.Any)[source]#
Bases:
SQLAlchemyAsyncRepositoryService[Any]Persistence operations for Advanced Alchemy queue event-history records.
- classmethod for_model(model_class: type[QueueEventHistoryModelMixin]) type['QueueEventLogService'][source]#
Return a service subclass bound to
model_class.
- async add_records(records: Sequence[QueueEventLogRecord]) None[source]#
Persist event-history records.
- async summarize_stages(query: QueueEventQuery | None = None) list[QueueEventStageSummary][source]#
- async cleanup_events(before: datetime, *, limit: int | None = None, match: QueueEventQuery | None = None, exclude: tuple[QueueEventQuery, ...] | None = None) int[source]#
Delete event-history records older than
before.limitbounds one batch, deleting the oldest matching rows first (oldestoccurred_at, then id).- Returns:
Number of deleted event-history rows.
- model_from_record(record: QueueEventLogRecord) Any[source]#
Convert a backend-neutral event-history record into an ORM model.
- Returns:
Advanced Alchemy event-history model.
- static record_from_model(model: Any) QueueEventLogRecord[source]#
Convert an ORM model into a backend-neutral event-history record.
- Returns:
Backend-neutral event-history record.
- class litestar_queues.backends.advanced_alchemy.service.QueueTaskReservationService(session: ~sqlalchemy.ext.asyncio.session.AsyncSession | ~sqlalchemy.ext.asyncio.scoping.async_scoped_session[~sqlalchemy.ext.asyncio.session.AsyncSession], *, statement: ~sqlalchemy.sql.selectable.Select | None = None, auto_expunge: bool = False, auto_refresh: bool = True, auto_commit: bool = False, order_by: ~typing.List[tuple[str | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any], bool] | ~sqlalchemy.sql.elements.UnaryExpression[~typing.Any]] | tuple[str | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any], bool] | ~sqlalchemy.sql.elements.UnaryExpression[~typing.Any] | None = None, error_messages: ~advanced_alchemy.exceptions.ErrorMessages | type[~advanced_alchemy.utils.dataclass.Empty] | None = <class 'advanced_alchemy.utils.dataclass.Empty'>, wrap_exceptions: bool = True, load: ~collections.abc.Sequence[~sqlalchemy.orm.strategy_options._AbstractLoad | ~typing.Literal['*'] | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any] | ~sqlalchemy.orm.relationships.RelationshipProperty[~typing.Any] | ~sqlalchemy.orm.interfaces.MapperProperty[~typing.Any] | ~collections.abc.Sequence[~sqlalchemy.orm.strategy_options._AbstractLoad | ~typing.Literal['*'] | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any] | ~sqlalchemy.orm.relationships.RelationshipProperty[~typing.Any] | ~sqlalchemy.orm.interfaces.MapperProperty[~typing.Any]]] | ~sqlalchemy.orm.strategy_options._AbstractLoad | ~typing.Literal['*'] | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any] | ~sqlalchemy.orm.relationships.RelationshipProperty[~typing.Any] | ~sqlalchemy.orm.interfaces.MapperProperty[~typing.Any] | ~sqlalchemy.sql.base.ExecutableOption | ~collections.abc.Sequence[~sqlalchemy.sql.base.ExecutableOption] | None = None, execution_options: dict[str, ~typing.Any] | None = None, uniquify: bool | None = None, count_with_window_function: bool | None = None, **repo_kwargs: ~typing.Any)[source]#
Bases:
SQLAlchemyAsyncRepositoryService[Any]Persistence operations for forever-uniqueness reservations.
- classmethod for_model(model_class: type[QueueTaskReservationModelMixin]) type['QueueTaskReservationService'][source]#
Return a service subclass bound to
model_class.
- async reserve(key: str, *, task_id: UUID, task_name: str) Any | None[source]#
Reserve
keyby select-then-insert within the caller’s transaction.- Returns:
Nonewhen the reservation was inserted; otherwise the existing owner model.
- async delete_by_key(key: str, *, expected_task_id: UUID | None = None) bool[source]#
Delete the reservation for
keywith optional owner fencing.- Parameters:
key – The exact effective identity key.
expected_task_id – Optional task owner required for deletion.
- Returns:
Truewhen a reservation row was removed.
- class litestar_queues.backends.advanced_alchemy.service.QueueTaskService(session: ~sqlalchemy.ext.asyncio.session.AsyncSession | ~sqlalchemy.ext.asyncio.scoping.async_scoped_session[~sqlalchemy.ext.asyncio.session.AsyncSession], *, statement: ~sqlalchemy.sql.selectable.Select | None = None, auto_expunge: bool = False, auto_refresh: bool = True, auto_commit: bool = False, order_by: ~typing.List[tuple[str | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any], bool] | ~sqlalchemy.sql.elements.UnaryExpression[~typing.Any]] | tuple[str | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any], bool] | ~sqlalchemy.sql.elements.UnaryExpression[~typing.Any] | None = None, error_messages: ~advanced_alchemy.exceptions.ErrorMessages | type[~advanced_alchemy.utils.dataclass.Empty] | None = <class 'advanced_alchemy.utils.dataclass.Empty'>, wrap_exceptions: bool = True, load: ~collections.abc.Sequence[~sqlalchemy.orm.strategy_options._AbstractLoad | ~typing.Literal['*'] | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any] | ~sqlalchemy.orm.relationships.RelationshipProperty[~typing.Any] | ~sqlalchemy.orm.interfaces.MapperProperty[~typing.Any] | ~collections.abc.Sequence[~sqlalchemy.orm.strategy_options._AbstractLoad | ~typing.Literal['*'] | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any] | ~sqlalchemy.orm.relationships.RelationshipProperty[~typing.Any] | ~sqlalchemy.orm.interfaces.MapperProperty[~typing.Any]]] | ~sqlalchemy.orm.strategy_options._AbstractLoad | ~typing.Literal['*'] | ~sqlalchemy.orm.attributes.InstrumentedAttribute[~typing.Any] | ~sqlalchemy.orm.relationships.RelationshipProperty[~typing.Any] | ~sqlalchemy.orm.interfaces.MapperProperty[~typing.Any] | ~sqlalchemy.sql.base.ExecutableOption | ~collections.abc.Sequence[~sqlalchemy.sql.base.ExecutableOption] | None = None, execution_options: dict[str, ~typing.Any] | None = None, uniquify: bool | None = None, count_with_window_function: bool | None = None, **repo_kwargs: ~typing.Any)[source]#
Bases:
SQLAlchemyAsyncRepositoryService[Any]Persistence operations for Advanced Alchemy queue records.
- classmethod for_model(model_class: type[QueueTaskModelMixin]) type['QueueTaskService'][source]#
Return a service subclass bound to
model_class.
- async enqueue(task_name: str, *, args: tuple[Any, ...], kwargs: dict[str, Any], queue: str, priority: int, max_retries: int, scheduled_at: datetime | None, expires_at: datetime | None = None, key: str | None, execution_backend: str, execution_profile: str | None, metadata: dict[str, Any], id: UUID | None = None) QueuedTaskRecord[source]#
- async enqueue_many(requests: Sequence[TaskRequest]) list[QueuedTaskRecord][source]#
Persist many task requests in the current repository transaction.
- Returns:
Queue task records in input order.
- async get_task(task_id: UUID) QueuedTaskRecord | None[source]#
- async get_task_by_key(key: str) QueuedTaskRecord | None[source]#
- async list_pending(*, limit: int, queue: str | None, execution_backend: str | None) list[QueuedTaskRecord][source]#
- async next_scheduled_at(*, queues: Sequence[str] = ()) datetime | None[source]#
Return the earliest not-yet-due
scheduled_atamong pending/scheduled records.Used to bound the worker’s adaptive polling wait so a scheduled or retried task is never discovered later than its own due time.
- Returns:
The earliest future
scheduled_at, orNonewhen there is no upcoming scheduled work.
- async claim_task(task_id: UUID, *, expected_retry_count: int | None = None, expected_execution_ref: str | None = None) QueuedTaskRecord | None[source]#
- async claim_task_with_expired(task_id: UUID, *, expected_retry_count: int | None = None, expected_execution_ref: str | None = None) tuple[QueuedTaskRecord | None, QueuedTaskRecord | None][source]#
Claim one task and identify a claim-time expiry owned by this call.
- async claim_next(*, queue: str | None, execution_backend: str | None) QueuedTaskRecord | None[source]#
- async claim_many(*, limit: int, queue: str | None, execution_backend: str | None) list[QueuedTaskRecord][source]#
Claim up to
limitrecords in the current repository transaction.- Returns:
Claimed task records.
- async claim_many_with_expired(*, limit: int, queue: str | None, execution_backend: str | None) tuple[list[QueuedTaskRecord], list[QueuedTaskRecord]][source]#
Claim records and report all expiry transitions owned by this transaction.
- async complete_task(task_id: UUID, *, result: Any | None = None, expected_retry_count: int | None = None) QueuedTaskRecord | None[source]#
- async fail_task(task_id: UUID, error: str, *, retry: bool, expected_retry_count: int | None = None, retry_at: datetime | None = None, queued_at: datetime | None = None) QueuedTaskRecord | None[source]#
- async assign_worker(task_id: UUID, *, worker_id: str, expected_retry_count: int) QueuedTaskRecord | None[source]#
Persist running-record ownership behind a status/generation fence.
- Returns:
The owned record, or
Nonewhen the fence was lost.
- async interrupt_task(task_id: UUID, *, expected_retry_count: int, worker_id: str, queued_at: datetime) QueuedTaskRecord | None[source]#
Return an owned running attempt to pending behind an owner/generation fence.
- Returns:
The requeued record, or
Nonewhen the fence was lost.
- async cancel_task(task_id: UUID, *, include_running: bool = False, expected_retry_count: int | None = None) bool[source]#
- async cancel_tasks(*, task_name: str | None = None, queue: str | None = None, kwargs: Mapping[str, Any] | None = None, metadata: Mapping[str, Any] | None = None, include_running: bool = False) int[source]#
- async touch_heartbeats(touches: Sequence[HeartbeatTouch]) HeartbeatTouchResult[source]#
- async null_heartbeats(task_ids: list[UUID], *, expected_retry_count: int | None = None) None[source]#
- async requeue_stale_running(*, stale_after: timedelta, limit: int | None = None, priority_policy: StaleRequeuePriority = 'preserve') StaleTaskRecoveryResult[source]#
- async set_execution_ref(task_id: UUID, execution_backend: str, execution_ref: str, *, execution_profile: str | None) QueuedTaskRecord | None[source]#
- async reserve_external_dispatch(task_id: UUID, execution_backend: str, reservation_ref: str, *, execution_profile: str | None, expected_retry_count: int | None = None) QueuedTaskRecord | None[source]#
- async clear_execution_ref(task_id: UUID, expected_retry_count: int, expected_execution_ref: str) QueuedTaskRecord | None[source]#
- async replace_execution_ref(task_id: UUID, expected_retry_count: int, expected_execution_ref: str, execution_ref: str) QueuedTaskRecord | None[source]#
- async release_external_dispatch(task_id: UUID, reservation_ref: str, execution_backend: str, *, execution_profile: str | None) QueuedTaskRecord | None[source]#
- async finalize_external_dispatch(task_id: UUID, reservation_ref: str, execution_backend: str, execution_ref: str, *, execution_profile: str | None) QueuedTaskRecord | None[source]#
- async set_execution_backend(task_id: UUID, execution_backend: str, *, execution_profile: str | None) QueuedTaskRecord | None[source]#
- async get_statistics(*, queue: str | None = None) QueueStatistics[source]#
- async list_completed_by_task(task_name: str, *, since: datetime | None, limit: int) list[QueuedTaskRecord][source]#
- model_from_record(record: QueuedTaskRecord) Any[source]#
Convert a backend-neutral record into an Advanced Alchemy model.
- Returns:
The Advanced Alchemy queue task model.
- static record_from_model(model: Any) QueuedTaskRecord[source]#
Convert an Advanced Alchemy model into a backend-neutral record.
- Returns:
The backend-neutral queued task record.
Advanced Alchemy-backed queue event history.
- class litestar_queues.backends.advanced_alchemy.event_log.AdvancedAlchemyQueueEventLog(config: EventHistoryConfig, *, service_factory: Callable[[], AbstractAsyncContextManager['QueueEventLogService']], transaction_factory: Callable[[], AbstractAsyncContextManager['QueueEventLogService']], runtime_logger: logging.Logger | None = None)[source]#
Bases:
objectBuffered Advanced Alchemy event-history writer and query interface.
- __init__(config: EventHistoryConfig, *, service_factory: Callable[[], AbstractAsyncContextManager['QueueEventLogService']], transaction_factory: Callable[[], AbstractAsyncContextManager['QueueEventLogService']], runtime_logger: logging.Logger | None = None) None[source]#
- async publish_event(event: QueueEvent) None[source]#
Buffer a queue event and flush when configured thresholds are reached.
- async query_events(query: QueueEventQuery | None = None, *, extra: Mapping[str, str] | None = None) OffsetPagination[QueueEventLogRecord][source]#
Query durable event history records.
- async summarize_stages(query: QueueEventQuery | None = None) list[QueueEventStageSummary][source]#
Return per-stage event history aggregates.
Advanced Alchemy queue models.
- class litestar_queues.backends.advanced_alchemy.models.QueueEventHistoryModel(**kwargs)[source]#
Bases:
UUIDAuditBase,QueueEventHistoryModelMixinDefault queue event-history model for the Advanced Alchemy backend.
- __init__(**kwargs)#
A simple constructor that allows initialization from kwargs.
Sets attributes on the constructed instance using the names and values in
kwargs.Only keys that are present as attributes of the instance’s class are allowed. These could be, for example, any mapped columns or relationships.
- actor#
- actor_id#
- actor_type#
- created_at: Mapped[datetime.datetime]#
Date/time of instance creation.
- detail_json#
- duration_ms#
- entity#
- event_id#
- event_type#
- execution_backend#
- execution_profile#
- id: Mapped[UUID]#
UUID Primary key column.
- level#
- message#
- occurred_at#
- progress_current#
- progress_percent#
- progress_total#
- queue#
- scope#
- scope_key#
- sequence#
- stage#
- task_id#
- task_name#
- updated_at: Mapped[datetime.datetime]#
Date/time of instance last update.
- worker_id#
- class litestar_queues.backends.advanced_alchemy.models.QueueMaintenanceModel(**kwargs)[source]#
Bases:
UUIDAuditBase,QueueMaintenanceModelMixinDefault distributed maintenance coordination model for the Advanced Alchemy backend.
- __init__(**kwargs)#
A simple constructor that allows initialization from kwargs.
Sets attributes on the constructed instance using the names and values in
kwargs.Only keys that are present as attributes of the instance’s class are allowed. These could be, for example, any mapped columns or relationships.
- created_at: Mapped[datetime.datetime]#
Date/time of instance creation.
- expires_at#
- id: Mapped[UUID]#
UUID Primary key column.
- name#
- token#
- updated_at: Mapped[datetime.datetime]#
Date/time of instance last update.
- class litestar_queues.backends.advanced_alchemy.models.QueueTaskModel(**kwargs)[source]#
Bases:
UUIDAuditBase,QueueTaskModelMixinDefault queue task model for the Advanced Alchemy backend.
- __init__(**kwargs)#
A simple constructor that allows initialization from kwargs.
Sets attributes on the constructed instance using the names and values in
kwargs.Only keys that are present as attributes of the instance’s class are allowed. These could be, for example, any mapped columns or relationships.
- args_json#
- completed_at#
- created_at: Mapped[datetime.datetime]#
Date/time of instance creation.
- error#
- execution_backend#
- execution_profile#
- execution_ref#
- expires_at#
- heartbeat_at#
- id: Mapped[UUID]#
UUID Primary key column.
- kwargs_json#
- max_retries#
- metadata_json#
- priority#
- queue#
- queued_at#
- result_json#
- retry_count#
- scheduled_at#
- started_at#
- status#
- task_key#
- task_name#
- updated_at: Mapped[datetime.datetime]#
Date/time of instance last update.
- worker_id#
- class litestar_queues.backends.advanced_alchemy.models.QueueTaskReservationModel(**kwargs)[source]#
Bases:
UUIDAuditBase,QueueTaskReservationModelMixinDefault forever-uniqueness reservation model for the Advanced Alchemy backend.
- __init__(**kwargs)#
A simple constructor that allows initialization from kwargs.
Sets attributes on the constructed instance using the names and values in
kwargs.Only keys that are present as attributes of the instance’s class are allowed. These could be, for example, any mapped columns or relationships.
- created_at: Mapped[datetime.datetime]#
Date/time of instance creation.
- id: Mapped[UUID]#
UUID Primary key column.
- identity_key#
- task_id#
- task_name#
- updated_at: Mapped[datetime.datetime]#
Date/time of instance last update.
Redis#
Redis queue backend.
Stores queued task records in a Redis-protocol key-value server. The
implementation lives directly on RedisQueueBackend; the Valkey
backend inherits from this class and only swaps the client factory and
_backend_name ClassVar.
- class litestar_queues.backends.redis.backend.RedisQueueBackend(config: QueueConfig | None = None, *, backend_config: _RedisBackendConfig | None = None)[source]#
Bases:
BaseQueueBackendQueue backend that stores records in a Redis-protocol key-value server.
Ready work lives in one global
{prefix}:readysorted set scored priority-major / created_at-minor, so the claim pops the globally-correct next task with one orderedZRANGEinstead of a Python-side sort over anHGETALLof every due candidate. A separate{prefix}:scheduledsorted set scored byscheduled_atpreserves exact delayed-promotion due-gating: the claim script promotes now-due scheduled ids intoreadybefore scanning, so future-scheduled tasks are never claimable early. Keeping one globalreadyset rather than per-queue sets makes the claim a singleEVALwith no queue enumeration; the queue and execution_backend filters skip non-matching top entries inside the script.Ready scores are IEEE-754 doubles, exact for integers up to 2^53. With stride
1e13andcreated_msnear1.7e12the priority band(-priority) * 1e13stays exact forabs(priority) <= 450, far beyond realistic priorities; ties break oncreated_msascending at millisecond resolution.All Lua scripts build their keys from a
key_prefixARG via string concatenation, which is single-node/replica only. Redis Cluster is out of scope: multi-key scripts on a cluster require same-slot hash-tagged keys and no hash-tag support is added. The composite-scoreready/scheduledlayout replaces the old{prefix}:pendingzset outright with no data migration; records enqueued under the old layout are stranded (benchmark namespaces are ephemeral).- __init__(config: QueueConfig | None = None, *, backend_config: _RedisBackendConfig | None = None) None[source]#
Initialize the queue backend.
- property capabilities: QueueBackendCapabilities#
Backend behavior capabilities.
- async open() bool[source]#
Open Redis-protocol client resources.
- Returns:
True when the client is ready.
- get_event_log(config: EventHistoryConfig) RedisQueueEventLog[source]#
Return a backend-owned queue event history implementation, if supported.
- async enqueue(task_name: str, *, args: tuple[Any, ...] = (), kwargs: dict[str, Any] | None = None, queue: str = 'default', priority: int = 0, max_retries: int = 0, scheduled_at: datetime | None = None, expires_at: datetime | None = None, key: str | None = None, execution_backend: str = 'local', execution_profile: str | None = None, metadata: dict[str, Any] | None = None, id: UUID | None = None) QueuedTaskRecord[source]#
Persist a queued task.
- Returns:
The created or deduplicated queued task record.
- async enqueue_many(requests: Sequence[TaskRequest]) list[QueuedTaskRecord][source]#
Persist a batch of Redis-backed tasks and coalesce worker wakeups.
- Returns:
Queue task records in the same order as
requests.
- async get_task(task_id: UUID) QueuedTaskRecord | None[source]#
Return a queued task by ID.
- async get_task_by_key(key: str) QueuedTaskRecord | None[source]#
Return a queued task by deduplication key.
- async list_pending(*, limit: int = 1, queue: str | None = None, execution_backend: str | None = None) list[QueuedTaskRecord][source]#
Return due pending or scheduled tasks ordered for execution.
- async claim_task(task_id: UUID, *, expected_retry_count: int | None = None, expected_execution_ref: str | None = None) QueuedTaskRecord | None[source]#
Atomically claim a pending task.
- async claim_task_with_expired(task_id: UUID, *, expected_retry_count: int | None = None, expected_execution_ref: str | None = None) tuple[QueuedTaskRecord | None, QueuedTaskRecord | None][source]#
Atomically claim a pending task via a single fenced script.
- Returns:
The claimed record and the expired record, at most one of which is set.
- async claim_many(*, limit: int, queues: tuple[str, ...] = (), execution_backend: str | None = None, queue_limits: Mapping[str, int] | None = None) list[QueuedTaskRecord][source]#
Claim up to
limitdue tasks in a single fencedEVAL.- Returns:
Claimed task records in claim order.
- async claim_many_with_expired(*, limit: int, queues: tuple[str, ...] = (), execution_backend: str | None = None, queue_limits: Mapping[str, int] | None = None) tuple[list[QueuedTaskRecord], list[QueuedTaskRecord]][source]#
Claim records and report expirations owned by the same Lua script.
- async complete_task(task_id: UUID, *, result: Any | None = None, expected_retry_count: int | None = None) QueuedTaskRecord | None[source]#
Mark a task as completed via a single fenced script.
- Returns:
The completed record, if it exists.
- async fail_task(task_id: UUID, error: str, *, retry: bool = True, expected_retry_count: int | None = None, retry_at: datetime | None = None, queued_at: datetime | None = None) QueuedTaskRecord | None[source]#
Mark a task as failed or retry it via a single fenced script.
- Returns:
The updated record, if it exists.
- async assign_worker(task_id: UUID, *, worker_id: str, expected_retry_count: int) QueuedTaskRecord | None[source]#
Persist running-record ownership through the fenced transition script.
- Returns:
The owned record, or
Nonewhen the fence was lost.
- async interrupt_task(task_id: UUID, *, expected_retry_count: int, worker_id: str, queued_at: datetime) QueuedTaskRecord | None[source]#
Return an owned running attempt to pending through the fenced transition script.
- Returns:
The requeued record, or
Nonewhen the fence was lost.
- async cancel_task(task_id: UUID, *, include_running: bool = False, expected_retry_count: int | None = None) bool[source]#
Cancel a task via a single fenced script.
- Returns:
True when the task was cancelled.
- async cancel_tasks(*, task_name: str | None = None, queue: str | None = None, kwargs: Mapping[str, Any] | None = None, metadata: Mapping[str, Any] | None = None, include_running: bool = False) int[source]#
Cancel tasks matching a domain predicate.
- Returns:
Number of records cancelled.
- async touch_heartbeats(touches: Sequence[HeartbeatTouch]) HeartbeatTouchResult[source]#
Update heartbeat timestamps for running tasks.
- Returns:
The task IDs confirmed touched or missed by the backend.
- async null_heartbeats(task_ids: list[UUID], *, expected_retry_count: int | None = None) None[source]#
Clear heartbeat timestamps for task IDs via a fenced script.
- async requeue_stale_running(*, stale_after: timedelta, limit: int | None = None) StaleTaskRecoveryResult[source]#
Requeue running tasks with stale heartbeats.
Candidates are ordered oldest-heartbeat-first (then by id) and capped at
limitbefore any mutation so one maintenance batch is bounded.- Returns:
Summary of recovered records.
- async set_execution_ref(task_id: UUID, execution_backend: str, execution_ref: str, *, execution_profile: str | None = None) QueuedTaskRecord | None[source]#
Persist an external execution reference for a running task via a fenced script.
- Returns:
The updated record, if it exists.
- async reserve_external_dispatch(task_id: UUID, execution_backend: str, reservation_ref: str, *, execution_profile: str | None = None, expected_retry_count: int | None = None) QueuedTaskRecord | None[source]#
Atomically reserve a due, unexpired task for external dispatch.
The default rejects dispatch because a read-then-write fallback cannot protect the external side effect.
- async clear_execution_ref(task_id: UUID, expected_retry_count: int, expected_execution_ref: str) QueuedTaskRecord | None[source]#
Clear an exact pending external attempt and wake dispatchers.
- async replace_execution_ref(task_id: UUID, expected_retry_count: int, expected_execution_ref: str, execution_ref: str) QueuedTaskRecord | None[source]#
Atomically rotate an exact pending external attempt reference.
- async release_external_dispatch(task_id: UUID, reservation_ref: str, execution_backend: str, *, execution_profile: str | None = None) QueuedTaskRecord | None[source]#
Release a matching external-dispatch reservation.
- async finalize_external_dispatch(task_id: UUID, reservation_ref: str, execution_backend: str, execution_ref: str, *, execution_profile: str | None = None) QueuedTaskRecord | None[source]#
Replace an owned dispatch reservation with its execution reference.
- async set_execution_backend(task_id: UUID, execution_backend: str, *, execution_profile: str | None = None) QueuedTaskRecord | None[source]#
Persist an execution backend/profile change for a queued task via a fenced script.
- Returns:
The updated record, if it exists.
- async list_running_external(*, limit: int | None = None) list[QueuedTaskRecord][source]#
Return externally dispatched tasks with references to reconcile.
- async get_statistics(*, queue: str | None = None) QueueStatistics[source]#
Return queue status counts.
- async expire_overdue(*, limit: int | None = None) list[QueuedTaskRecord][source]#
Transition overdue pending and scheduled records to
expired.
- async list_completed_by_task(task_name: str, *, since: datetime | None = None, limit: int = 10) list[QueuedTaskRecord][source]#
Return recent completed records for a task name.
- async cleanup_terminal(before: datetime, *, limit: int | None = None) int[source]#
Delete terminal records completed before a cutoff.
Candidates are ordered oldest-completion-first (then by id) and capped at
limitbefore any deletion so one maintenance batch is bounded.- Returns:
Number of deleted records.
- async rebuild_maintenance_indexes() int[source]#
Rebuild ordered maintenance indexes for a populated pre-index namespace.
This is an intentionally unbounded, one-time upgrade operation. Stop all queue writers using this Redis/Valkey namespace before calling it. Interrupted calls are safe to retry because the version marker is written only after every task has been reindexed.
- Returns:
Number of queue records indexed.
- async acquire_maintenance(name: str, token: str, *, ttl: timedelta) bool[source]#
Acquire namespaced
SET NX PXmaintenance ownership.- Returns:
True when ownership was set for
token.
- async release_maintenance(name: str, token: str) bool[source]#
Release maintenance ownership via token-checked Lua compare-and-delete.
- Returns:
True when ownership held under
tokenwas deleted.
- async reserve_identity(key: str, *, task_id: UUID, task_name: str) TaskReservation | None[source]#
Reserve a forever identity via an atomic HGET-or-HSET script.
The task-reservation hash is separate from
:task:/:keysand is never touched by terminal cleanup.- Returns:
Nonewhen this caller won the reservation; otherwise the existing owner reservation.
- async has_identity(key: str) TaskReservation | None[source]#
Return the reservation owning a reserved forever identity, if any.
- async reset_identity(key: str, *, expected_task_id: UUID | None = None) bool[source]#
Delete a forever identity reservation via atomic compare-and-delete.
- Parameters:
key – The exact effective identity key.
expected_task_id – Optional task owner required for deletion.
- Returns:
Truewhen a reservation was removed.
- async notify_new_task(record: QueuedTaskRecord) None[source]#
Publish a Redis-protocol pub/sub message when work is available.
- async wait_for_wakeups(timeout: float | None = None) bool[source]#
Wait for a Redis-protocol pub/sub message when notifications are enabled.
A single pub/sub receive is retained across worker poll timeouts; only a real message, a read failure, or backend close ends it.
- Returns:
True when a notification was observed.
- async notify_worker_control(worker_id: str | None) None[source]#
Publish a worker-control hint on the Redis-protocol control channel.
The hint is lossy by contract: it only shortens the wait before the owning worker reconciles durable status.
- async wait_for_worker_control(*, worker_id: str, timeout: float | None = None) bool[source]#
Wait for a Redis-protocol worker-control hint.
The control subscription and its pending receive are retained across worker poll timeouts, exactly like the wakeup subscription, and are never shared with it: one in-flight read per subscription.
- Returns:
True when a control hint was observed.
- Raises:
Exception – Whatever the pub/sub receive raised, after the subscription is reset so the next wait reconnects.
- async time_until_next_due(*, queues: tuple[str, ...] = ()) float | None[source]#
Return seconds until the earliest not-yet-due scheduled record.
Reads the lowest-scored member of the global
scheduledsorted set (scored byscheduled_at): an O(1) lookup independent of queue size.queuesis not applied because the sorted set is not queue-scoped; an unfiltered bound is always safe here (it can only wake the worker sooner than strictly necessary, never later).- Returns:
Seconds until the next due record, or
Nonewhen there is no upcoming scheduled work.
Redis queue backend configuration.
- class litestar_queues.backends.redis.config.RedisBackendConfig(url: str = 'redis://localhost:6379/0', key_prefix: str | None = None, worker_wakeups: bool = True, wakeup_channel: str | None = None, client: Redis | None = None)[source]#
Bases:
objectConfiguration for the Redis queue backend.
- key_prefix: str | None#
Prefix applied to every queue key;
Nonederives it fromQueueConfig.namespace.
- __init__(url: str = 'redis://localhost:6379/0', key_prefix: str | None = None, worker_wakeups: bool = True, wakeup_channel: str | None = None, client: Redis | None = None) None#
Redis-protocol queue event history.
- class litestar_queues.backends.redis.event_log.RedisQueueEventLog(*, backend: RedisQueueBackend, config: EventHistoryConfig)[source]#
Bases:
objectBuffered Redis-protocol event-history writer and query interface.
- __init__(*, backend: RedisQueueBackend, config: EventHistoryConfig) None[source]#
- async publish_event(event: QueueEvent) None[source]#
Buffer a queue event and flush when configured thresholds are reached.
- async query_events(query: QueueEventQuery | None = None, *, extra: Mapping[str, str] | None = None) OffsetPagination[QueueEventLogRecord][source]#
Return a filtered, ordered page of event history records.
- Returns:
The matching page.
- async summarize_stages(query: QueueEventQuery | None = None) list[QueueEventStageSummary][source]#
Return per-stage event history aggregates.
Valkey#
Valkey queue backend.
The Valkey wire protocol is API-compatible with Redis, so this backend
inherits the full RedisQueueBackend implementation and only overrides
the client factory (uses valkey.asyncio instead of redis.asyncio)
plus the _backend_name ClassVar that drives lock-name error messages
and the valkey-pubsub notification capability label.
- class litestar_queues.backends.valkey.backend.ValkeyQueueBackend(config: QueueConfig | None = None, *, backend_config: ValkeyBackendConfig | None = None)[source]#
Bases:
RedisQueueBackendValkey-backed queue backend.
- __init__(config: QueueConfig | None = None, *, backend_config: ValkeyBackendConfig | None = None) None[source]#
Initialize the queue backend.
Valkey queue backend configuration.
- class litestar_queues.backends.valkey.config.ValkeyBackendConfig(url: str = 'redis://localhost:6379/0', key_prefix: str | None = None, worker_wakeups: bool = True, wakeup_channel: str | None = None, client: Valkey | None = None)[source]#
Bases:
objectConfiguration for the Valkey queue backend.
- key_prefix: str | None#
Prefix applied to every queue key;
Nonederives it fromQueueConfig.namespace.
- __init__(url: str = 'redis://localhost:6379/0', key_prefix: str | None = None, worker_wakeups: bool = True, wakeup_channel: str | None = None, client: Valkey | None = None) None#