Skip to content

Commit 4548f75

Browse files
committed
fix(awareness-service): handle transient DB outages quietly in delivery engine
When Postgres restarts or is in recovery (57P03 and friends), the delivery tick threw every 2s and dumped a full stack trace each time. Detect transient DB-unavailable errors and log a single concise warning per outage; the engine resumes automatically once the database is back.
1 parent 929a167 commit 4548f75

1 file changed

Lines changed: 33 additions & 1 deletion

File tree

services/awareness-service/api/src/services/DeliveryEngine.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,24 @@ import type { AwarenessPayload } from "../types";
1111

1212
const BATCH_SIZE = 50;
1313

14+
/**
15+
* True for transient "Postgres is not ready" errors - server restarting, in
16+
* recovery, or unreachable. These resolve on their own once the DB is back.
17+
*/
18+
function isDbUnavailable(err: any): boolean {
19+
const code = err?.code ?? err?.driverError?.code;
20+
return (
21+
code === "57P03" || // cannot connect now / in recovery
22+
code === "57P01" || // admin shutdown
23+
code === "08006" || // connection failure
24+
code === "08001" || // unable to establish connection
25+
code === "08003" || // connection does not exist
26+
code === "ECONNREFUSED" ||
27+
code === "ETIMEDOUT" ||
28+
code === "ENOTFOUND"
29+
);
30+
}
31+
1432
/**
1533
* Background worker that drains the deliveries queue. Each tick atomically
1634
* claims a batch of due deliveries (FOR UPDATE SKIP LOCKED so concurrent ticks
@@ -21,6 +39,7 @@ const BATCH_SIZE = 50;
2139
export class DeliveryEngine {
2240
private timer?: NodeJS.Timeout;
2341
private running = false;
42+
private dbDown = false;
2443

2544
start(): void {
2645
this.timer = setInterval(() => {
@@ -43,8 +62,21 @@ export class DeliveryEngine {
4362
for (const delivery of claimed) {
4463
await this.attemptDelivery(delivery);
4564
}
65+
this.dbDown = false;
4666
} catch (err) {
47-
console.error("[aaas] delivery tick failed:", err);
67+
if (isDbUnavailable(err)) {
68+
// Postgres is restarting / in recovery - transient. Log once
69+
// per outage instead of dumping a stack trace every tick.
70+
if (!this.dbDown) {
71+
this.dbDown = true;
72+
console.warn(
73+
"[aaas] database unavailable, pausing delivery until it recovers",
74+
);
75+
}
76+
} else {
77+
this.dbDown = false;
78+
console.error("[aaas] delivery tick failed:", err);
79+
}
4880
} finally {
4981
this.running = false;
5082
}

0 commit comments

Comments
 (0)