@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.
Files changed (48) hide show
  1. package/README.md +13 -0
  2. package/dist/adapters/bun-sql.d.ts +2 -1
  3. package/dist/adapters/bun-sql.d.ts.map +1 -1
  4. package/dist/adapters/bun-sql.js +5 -0
  5. package/dist/adapters/bun-sql.js.map +1 -1
  6. package/dist/adapters/pg.d.ts +2 -1
  7. package/dist/adapters/pg.d.ts.map +1 -1
  8. package/dist/adapters/pg.js +5 -0
  9. package/dist/adapters/pg.js.map +1 -1
  10. package/dist/adapters/postgres.d.ts +2 -1
  11. package/dist/adapters/postgres.d.ts.map +1 -1
  12. package/dist/adapters/postgres.js +5 -0
  13. package/dist/adapters/postgres.js.map +1 -1
  14. package/dist/index.d.ts +1 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +4 -0
  17. package/dist/index.js.map +1 -1
  18. package/dist/postgres-event-scheduler.js +3 -3
  19. package/dist/postgres-event-scheduler.js.map +1 -1
  20. package/dist/postgres-event-store.js +5 -5
  21. package/dist/postgres-event-store.js.map +1 -1
  22. package/dist/postgres-transaction-manager.d.ts +1 -20
  23. package/dist/postgres-transaction-manager.d.ts.map +1 -1
  24. package/dist/postgres-transaction-manager.js +4 -26
  25. package/dist/postgres-transaction-manager.js.map +1 -1
  26. package/dist/postgres.d.ts +0 -8
  27. package/dist/postgres.d.ts.map +1 -1
  28. package/dist/postgres.js +5 -1
  29. package/dist/postgres.js.map +1 -1
  30. package/dist/schema.d.ts +9 -7
  31. package/dist/schema.d.ts.map +1 -1
  32. package/dist/schema.js +17 -15
  33. package/dist/schema.js.map +1 -1
  34. package/dist/session-timeouts.d.ts +47 -0
  35. package/dist/session-timeouts.d.ts.map +1 -0
  36. package/dist/session-timeouts.js +44 -0
  37. package/dist/session-timeouts.js.map +1 -0
  38. package/package.json +4 -4
  39. package/src/adapters/bun-sql.ts +10 -1
  40. package/src/adapters/pg.ts +10 -1
  41. package/src/adapters/postgres.ts +10 -1
  42. package/src/index.ts +10 -0
  43. package/src/postgres-event-scheduler.ts +4 -4
  44. package/src/postgres-event-store.ts +8 -8
  45. package/src/postgres-transaction-manager.ts +3 -51
  46. package/src/postgres.ts +5 -9
  47. package/src/schema.ts +17 -15
  48. 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
+ }