Postgres engine: queues — Queue (validated constructor over the handle's QueueOpts stamps), the FOR UPDATE SKIP LOCKED claim (one statement, the pre-claim exhausted-reclaimable sweep in the atomic claim frame), JobHandle (one-shot ack/retry/fail in tx frames under the uniform validity predicate, absolute-reset heartbeat, engine-side equal-jitter backoff), dead-letter moves transactional (the #133 class excluded), worker-less ack_batch, unconditional cancel, dead-visible get_job, both-states+retention sweep, best-effort queue-channel wake, wake-driven claim loop pinned (task pg-engine-queues)

This commit is contained in:
glm-5.3-flash committed 2026-10-09 08:44:59 +00:00
1 parent cb067bb4be
commit 3dd83791ff
7 files changed
+2640 -53

No files matched your search

+55 -34
View File
@@ -192,20 +192,10 @@ impl PgTxHandle {
.to_string()
}
fn enqueue_row_sql(&self) -> String {
format!(
"INSERT INTO {} (queue, payload, run_at, priority, max_attempts,
expires_at, created_at, visibility_timeout_s,
backoff_base_s, dead_letter_retention_s)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
RETURNING id",
self.table(tables::JOB)
)
}
/// The plain-queue enqueue's shared write (the `enqueue_tx` /
/// `outbox_enqueue_tx` INSERT), called with this handle's
/// qualified job table.
/// qualified job table — the module-level [`enqueue_row`]'s
/// handle-side bridge.
async fn enqueue_row(
&self,
client: &tokio_postgres::Client,
@@ -214,31 +204,62 @@ impl PgTxHandle {
opts: &EnqueueOpts,
base: crate::resolution::Stamps,
) -> Result<i64> {
let now = crate::resolution::now_unix();
let ResolvedEnqueue { run_at, expires_at } = resolve_enqueue_opts(now, opts);
let stamps = stamps_with_override(base, opts);
let row = client
.query_one(
&self.enqueue_row_sql(),
&[
&queue,
&bytes,
&run_at,
&opts.priority,
&stamps.max_attempts,
&expires_at,
&now,
&stamps.visibility_timeout_s,
&stamps.backoff_base_s,
&stamps.dead_letter_retention_s,
],
)
.await
.map_err(pg_error)?;
Ok(row.get(0))
enqueue_row(client, &self.schema, queue, bytes, opts, base).await
}
}
/// The enqueue INSERT — the one owner of the plain-queue row write.
/// The tx paths (`enqueue_tx` over the plain-queue defaults,
/// `outbox_enqueue_tx` over the outbox's 60/5/5 set) and the auto-commit
/// `Queue::enqueue` over the handle's `QueueOpts` ride it; one clock
/// read per enqueue (the `now` the resolution and the write share).
pub(crate) async fn enqueue_row(
client: &tokio_postgres::Client,
schema: &str,
queue: &str,
bytes: Vec<u8>,
opts: &EnqueueOpts,
base: crate::resolution::Stamps,
) -> Result<i64> {
let now = crate::resolution::now_unix();
let ResolvedEnqueue { run_at, expires_at } = resolve_enqueue_opts(now, opts);
let stamps = stamps_with_override(base, opts);
let row = client
.query_one(
&enqueue_row_sql(schema),
&[
&queue,
&bytes,
&run_at,
&opts.priority,
&stamps.max_attempts,
&expires_at,
&now,
&stamps.visibility_timeout_s,
&stamps.backoff_base_s,
&stamps.dead_letter_retention_s,
],
)
.await
.map_err(pg_error)?;
Ok(row.get(0))
}
/// The enqueue INSERT's SQL (schema-qualified job table).
fn enqueue_row_sql(schema: &str) -> String {
format!(
"INSERT INTO {} (queue, payload, run_at, priority, max_attempts,
expires_at, created_at, visibility_timeout_s,
backoff_base_s, dead_letter_retention_s)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
RETURNING id",
QualifiedTable {
schema,
name: tables::JOB
}
)
}
/// Encode a trait-crossing payload `Value` into the exact stored bytes
/// (the serde_json serialization — ADR-020 §4). The notify carriage
/// reuses it: the JSON serialization is valid UTF-8 text by