@kronos-ts/postgres 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/dist/adapters/bun-sql.d.ts +2 -1
- package/dist/adapters/bun-sql.d.ts.map +1 -1
- package/dist/adapters/bun-sql.js +5 -0
- package/dist/adapters/bun-sql.js.map +1 -1
- package/dist/adapters/pg.d.ts +2 -1
- package/dist/adapters/pg.d.ts.map +1 -1
- package/dist/adapters/pg.js +5 -0
- package/dist/adapters/pg.js.map +1 -1
- package/dist/adapters/postgres.d.ts +2 -1
- package/dist/adapters/postgres.d.ts.map +1 -1
- package/dist/adapters/postgres.js +5 -0
- package/dist/adapters/postgres.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/postgres-event-scheduler.js +3 -3
- package/dist/postgres-event-scheduler.js.map +1 -1
- package/dist/postgres-event-store.js +5 -5
- package/dist/postgres-event-store.js.map +1 -1
- package/dist/postgres-transaction-manager.d.ts +1 -20
- package/dist/postgres-transaction-manager.d.ts.map +1 -1
- package/dist/postgres-transaction-manager.js +4 -26
- package/dist/postgres-transaction-manager.js.map +1 -1
- package/dist/postgres.d.ts +0 -8
- package/dist/postgres.d.ts.map +1 -1
- package/dist/postgres.js +5 -1
- package/dist/postgres.js.map +1 -1
- package/dist/schema.d.ts +9 -7
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +17 -15
- package/dist/schema.js.map +1 -1
- package/dist/session-timeouts.d.ts +47 -0
- package/dist/session-timeouts.d.ts.map +1 -0
- package/dist/session-timeouts.js +44 -0
- package/dist/session-timeouts.js.map +1 -0
- package/package.json +4 -4
- package/src/adapters/bun-sql.ts +10 -1
- package/src/adapters/pg.ts +10 -1
- package/src/adapters/postgres.ts +10 -1
- package/src/index.ts +10 -0
- package/src/postgres-event-scheduler.ts +4 -4
- package/src/postgres-event-store.ts +8 -8
- package/src/postgres-transaction-manager.ts +3 -51
- package/src/postgres.ts +5 -9
- package/src/schema.ts +17 -15
- package/src/session-timeouts.ts +77 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-transaction safety timeouts, armed via `SET LOCAL` by each adapter's
|
|
3
|
+
* `transaction()` at BEGIN. Living on the adapter (not the transaction
|
|
4
|
+
* manager) means EVERY postgres transaction is bounded — UoW-scoped commits,
|
|
5
|
+
* the event store's own-tx append/publish, and the scheduler worker tick alike
|
|
6
|
+
* — and each adapter instance carries its own settings, so two adapters
|
|
7
|
+
* pointed at two different databases stay fully decoupled.
|
|
8
|
+
*
|
|
9
|
+
* A non-postgres adapter (e.g. a future sqlite one) arms its own
|
|
10
|
+
* dialect-appropriate settings, or none.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { PostgresAdapterTransaction } from "./adapter.js"
|
|
14
|
+
|
|
15
|
+
export interface SessionTimeoutOptions {
|
|
16
|
+
/**
|
|
17
|
+
* `idle_in_transaction_session_timeout` (ms) applied via `SET LOCAL` on every
|
|
18
|
+
* transaction. A transaction that begins but stalls before commit/rollback
|
|
19
|
+
* would otherwise hold its connection — and pin `pg_snapshot_xmin`, which
|
|
20
|
+
* gates the gap-free tailing query in the event store — open indefinitely,
|
|
21
|
+
* stalling all streaming processors until the process restarts. This bounds
|
|
22
|
+
* that window: postgres aborts the idle transaction and the connection (and
|
|
23
|
+
* xmin) is freed. Default 30000 (30s). Set 0 to disable (postgres default).
|
|
24
|
+
*/
|
|
25
|
+
readonly idleInTransactionTimeoutMs?: number
|
|
26
|
+
/**
|
|
27
|
+
* `statement_timeout` (ms) applied via `SET LOCAL` on every transaction.
|
|
28
|
+
* Bounds a single hung statement inside the tx. Default 0 (disabled) — large
|
|
29
|
+
* appends / replays can legitimately run long, so opt in per deployment.
|
|
30
|
+
*/
|
|
31
|
+
readonly statementTimeoutMs?: number
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface ResolvedSessionTimeouts {
|
|
35
|
+
readonly idleInTransactionTimeoutMs: number
|
|
36
|
+
readonly statementTimeoutMs: number
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const DEFAULT_IDLE_IN_TRANSACTION_TIMEOUT_MS = 30_000
|
|
40
|
+
|
|
41
|
+
/** Resolve config to concrete, normalized timeouts (applying defaults). */
|
|
42
|
+
export function resolveSessionTimeouts(opts?: SessionTimeoutOptions): ResolvedSessionTimeouts {
|
|
43
|
+
return {
|
|
44
|
+
idleInTransactionTimeoutMs: normalizeTimeoutMs(
|
|
45
|
+
opts?.idleInTransactionTimeoutMs ?? DEFAULT_IDLE_IN_TRANSACTION_TIMEOUT_MS,
|
|
46
|
+
),
|
|
47
|
+
statementTimeoutMs: normalizeTimeoutMs(opts?.statementTimeoutMs ?? 0),
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Arm the resolved timeouts on a freshly-opened transaction. No-op for any
|
|
53
|
+
* timeout resolved to 0.
|
|
54
|
+
*
|
|
55
|
+
* GUCs cannot be parameterized ($1) — the value is a config-supplied integer,
|
|
56
|
+
* normalized to a non-negative whole number, so inlining is injection-safe.
|
|
57
|
+
* `SET LOCAL` auto-resets at COMMIT/ROLLBACK, so it never leaks onto pooled
|
|
58
|
+
* connections.
|
|
59
|
+
*/
|
|
60
|
+
export async function applySessionTimeouts(
|
|
61
|
+
tx: PostgresAdapterTransaction,
|
|
62
|
+
timeouts: ResolvedSessionTimeouts,
|
|
63
|
+
): Promise<void> {
|
|
64
|
+
if (timeouts.idleInTransactionTimeoutMs > 0) {
|
|
65
|
+
await tx.query(`SET LOCAL idle_in_transaction_session_timeout = ${timeouts.idleInTransactionTimeoutMs}`)
|
|
66
|
+
}
|
|
67
|
+
if (timeouts.statementTimeoutMs > 0) {
|
|
68
|
+
await tx.query(`SET LOCAL statement_timeout = ${timeouts.statementTimeoutMs}`)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Coerce a config timeout to a non-negative whole number of milliseconds.
|
|
73
|
+
* Non-finite or negative values disable the timeout (treated as 0). */
|
|
74
|
+
function normalizeTimeoutMs(value: number): number {
|
|
75
|
+
if (!Number.isFinite(value) || value <= 0) return 0
|
|
76
|
+
return Math.floor(value)
|
|
77
|
+
}
|