@nodii/saga 0.0.2 → 0.2.1

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 (90) hide show
  1. package/dist/admin-service.d.ts +55 -0
  2. package/dist/admin-service.d.ts.map +1 -0
  3. package/dist/admin-service.js +161 -0
  4. package/dist/admin-service.js.map +1 -0
  5. package/dist/async-step.d.ts +43 -0
  6. package/dist/async-step.d.ts.map +1 -0
  7. package/dist/async-step.js +166 -0
  8. package/dist/async-step.js.map +1 -0
  9. package/dist/context.d.ts +18 -0
  10. package/dist/context.d.ts.map +1 -0
  11. package/dist/context.js +28 -0
  12. package/dist/context.js.map +1 -0
  13. package/dist/decorator.d.ts +24 -0
  14. package/dist/decorator.d.ts.map +1 -0
  15. package/dist/decorator.js +69 -0
  16. package/dist/decorator.js.map +1 -0
  17. package/dist/idempotency.d.ts +22 -0
  18. package/dist/idempotency.d.ts.map +1 -0
  19. package/dist/idempotency.js +44 -0
  20. package/dist/idempotency.js.map +1 -0
  21. package/dist/index.d.ts +20 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +34 -4
  24. package/dist/index.js.map +1 -1
  25. package/dist/init.d.ts +45 -0
  26. package/dist/init.d.ts.map +1 -0
  27. package/dist/init.js +86 -0
  28. package/dist/init.js.map +1 -0
  29. package/dist/interceptor.d.ts +5 -0
  30. package/dist/interceptor.d.ts.map +1 -0
  31. package/dist/interceptor.js +34 -0
  32. package/dist/interceptor.js.map +1 -0
  33. package/dist/migrations/index.d.ts +19 -0
  34. package/dist/migrations/index.d.ts.map +1 -0
  35. package/dist/migrations/index.js +106 -0
  36. package/dist/migrations/index.js.map +1 -0
  37. package/dist/reaper.d.ts +27 -0
  38. package/dist/reaper.d.ts.map +1 -0
  39. package/dist/reaper.js +79 -0
  40. package/dist/reaper.js.map +1 -0
  41. package/dist/registry.d.ts +7 -0
  42. package/dist/registry.d.ts.map +1 -0
  43. package/dist/registry.js +23 -0
  44. package/dist/registry.js.map +1 -0
  45. package/dist/saga.d.ts +48 -0
  46. package/dist/saga.d.ts.map +1 -0
  47. package/dist/saga.js +384 -0
  48. package/dist/saga.js.map +1 -0
  49. package/dist/signal-bus/index.d.ts +2 -0
  50. package/dist/signal-bus/index.d.ts.map +1 -0
  51. package/dist/signal-bus/index.js +6 -0
  52. package/dist/signal-bus/index.js.map +1 -0
  53. package/dist/signal-bus/redis-stream.d.ts +43 -0
  54. package/dist/signal-bus/redis-stream.d.ts.map +1 -0
  55. package/dist/signal-bus/redis-stream.js +189 -0
  56. package/dist/signal-bus/redis-stream.js.map +1 -0
  57. package/dist/signals.d.ts +29 -0
  58. package/dist/signals.d.ts.map +1 -0
  59. package/dist/signals.js +113 -0
  60. package/dist/signals.js.map +1 -0
  61. package/dist/state-store/index.d.ts +2 -0
  62. package/dist/state-store/index.d.ts.map +1 -0
  63. package/dist/state-store/index.js +6 -0
  64. package/dist/state-store/index.js.map +1 -0
  65. package/dist/state-store/postgres.d.ts +47 -0
  66. package/dist/state-store/postgres.d.ts.map +1 -0
  67. package/dist/state-store/postgres.js +270 -0
  68. package/dist/state-store/postgres.js.map +1 -0
  69. package/dist/test-doubles/in-memory-signal-bus.d.ts +38 -0
  70. package/dist/test-doubles/in-memory-signal-bus.d.ts.map +1 -0
  71. package/dist/test-doubles/in-memory-signal-bus.js +68 -0
  72. package/dist/test-doubles/in-memory-signal-bus.js.map +1 -0
  73. package/dist/test-doubles/in-memory-state-store.d.ts +26 -0
  74. package/dist/test-doubles/in-memory-state-store.d.ts.map +1 -0
  75. package/dist/test-doubles/in-memory-state-store.js +87 -0
  76. package/dist/test-doubles/in-memory-state-store.js.map +1 -0
  77. package/dist/test-doubles/index.d.ts +4 -0
  78. package/dist/test-doubles/index.d.ts.map +1 -0
  79. package/dist/test-doubles/index.js +14 -0
  80. package/dist/test-doubles/index.js.map +1 -0
  81. package/dist/types.d.ts +260 -0
  82. package/dist/types.d.ts.map +1 -0
  83. package/dist/types.js +103 -0
  84. package/dist/types.js.map +1 -0
  85. package/dist/uuid.d.ts +3 -0
  86. package/dist/uuid.d.ts.map +1 -0
  87. package/dist/uuid.js +62 -0
  88. package/dist/uuid.js.map +1 -0
  89. package/package.json +33 -7
  90. package/src/migrations/001-saga-state.sql +79 -0
@@ -0,0 +1,189 @@
1
+ // RedisSignalBus — real, Redis-Streams-backed implementation of
2
+ // `SagaSignalBus`. Spec § 5.9 + comm doctrine § 9.2.
3
+ //
4
+ // Wire design:
5
+ // - One Redis stream per service: `nodii:<serviceId>:saga:signals`.
6
+ // - Each saga that calls `awaitSagaSignal` opens an XREAD with its own
7
+ // consumer group keyed by `saga:<sagaId>`. This gives per-saga
8
+ // isolation — a parent and child saga listening for the same event
9
+ // type don't steal each other's messages.
10
+ // - Sibling fan-out uses the `to` field on the message body; the
11
+ // consume() filter rejects messages addressed to a different saga.
12
+ // - We claim with a short block (50ms) so callers can poll without
13
+ // blocking forever; the higher-level `awaitSagaSignal` does the
14
+ // timeout-budget loop.
15
+ export class RedisSignalBus {
16
+ redis;
17
+ stream;
18
+ blockMs;
19
+ // Consumer group / consumer name dedup. We attempt MKSTREAM-create
20
+ // lazily; second concurrent call collides but Redis errors are
21
+ // benignly ignored.
22
+ groupsEnsured = new Set();
23
+ constructor(opts) {
24
+ this.redis = opts.redis;
25
+ this.stream = opts.streamName ?? `nodii:${opts.serviceId}:saga:signals`;
26
+ this.blockMs = opts.blockMs ?? 50;
27
+ }
28
+ async emit(args) {
29
+ await this.redis.xadd(this.stream, "*", "saga_id", args.sagaId, "event_type", args.eventType, "payload", JSON.stringify(args.payload ?? null), "scope", args.scope ?? "siblings", "to", args.to ?? "");
30
+ }
31
+ async consume(args) {
32
+ const group = `saga:${args.sagaId}`;
33
+ await this.ensureGroup(group);
34
+ const consumer = `c:${args.sagaId}`;
35
+ // XREADGROUP with `>` to pick up new messages only. We pull up to 32
36
+ // and filter in-memory because Redis Streams don't support
37
+ // server-side payload predicates.
38
+ // biome-ignore lint/suspicious/noExplicitAny: ioredis XREADGROUP returns nested string arrays — we narrow to the structure we know
39
+ const raw = await this.redis.xreadgroup("GROUP", group, consumer, "COUNT", 32, "BLOCK", this.blockMs, "STREAMS", this.stream, ">");
40
+ if (!raw)
41
+ return null;
42
+ const messages = extractMessages(raw, this.stream);
43
+ for (const msg of messages) {
44
+ const sig = parseSignal(msg.id, msg.fields);
45
+ if (!sig) {
46
+ // Bad message — XACK + skip.
47
+ await this.redis.xack(this.stream, group, msg.id);
48
+ continue;
49
+ }
50
+ if (sig.eventType !== args.eventType) {
51
+ // Not what this caller wants — XACK so the same group doesn't
52
+ // see it again (it's addressed to the saga, not to a particular
53
+ // event-type subscription).
54
+ await this.redis.xack(this.stream, group, msg.id);
55
+ continue;
56
+ }
57
+ if (sig.to && sig.to !== args.sagaId) {
58
+ await this.redis.xack(this.stream, group, msg.id);
59
+ continue;
60
+ }
61
+ if (args.from && sig.sagaId !== args.from) {
62
+ await this.redis.xack(this.stream, group, msg.id);
63
+ continue;
64
+ }
65
+ if (args.predicate && !args.predicate(sig.payload)) {
66
+ await this.redis.xack(this.stream, group, msg.id);
67
+ continue;
68
+ }
69
+ await this.redis.xack(this.stream, group, msg.id);
70
+ return sig.payload;
71
+ }
72
+ return null;
73
+ }
74
+ async list(args) {
75
+ // XRANGE pulls the full stream; for v0.1.0 this is acceptable since
76
+ // saga.signals is per-service and bounded. Production may layer
77
+ // pagination on top.
78
+ // biome-ignore lint/suspicious/noExplicitAny: XRANGE returns [id, [field, value, ...]][]
79
+ const raw = await this.redis.xrange(this.stream, "-", "+");
80
+ const out = [];
81
+ if (!Array.isArray(raw))
82
+ return out;
83
+ for (const entry of raw) {
84
+ if (!Array.isArray(entry) || entry.length < 2)
85
+ continue;
86
+ const id = entry[0];
87
+ const fields = entry[1];
88
+ const sig = parseSignal(id, fields);
89
+ if (!sig)
90
+ continue;
91
+ if (sig.to && sig.to !== args.sagaId)
92
+ continue;
93
+ if (args.eventType && sig.eventType !== args.eventType)
94
+ continue;
95
+ out.push({
96
+ sagaId: sig.sagaId,
97
+ eventType: sig.eventType,
98
+ payload: sig.payload,
99
+ });
100
+ }
101
+ return out;
102
+ }
103
+ /** Test helper — drop the stream + reset ensure cache. */
104
+ async resetForTests() {
105
+ try {
106
+ await this.redis.del(this.stream);
107
+ }
108
+ catch {
109
+ /* swallow */
110
+ }
111
+ this.groupsEnsured.clear();
112
+ }
113
+ async close() {
114
+ /* leaves Redis connection management to the caller */
115
+ }
116
+ async ensureGroup(group) {
117
+ if (this.groupsEnsured.has(group))
118
+ return;
119
+ try {
120
+ await this.redis.xgroup("CREATE", this.stream, group, "0", "MKSTREAM");
121
+ }
122
+ catch (err) {
123
+ // BUSYGROUP is fine — group already exists.
124
+ const msg = err instanceof Error ? err.message : String(err);
125
+ if (!msg.includes("BUSYGROUP")) {
126
+ // Other errors are surfaced; XREADGROUP would also fail.
127
+ }
128
+ }
129
+ this.groupsEnsured.add(group);
130
+ }
131
+ }
132
+ function extractMessages(raw, expectedStream) {
133
+ // raw shape: [[ streamName, [[ id, [field, value, ...] ], ...] ], ...]
134
+ const out = [];
135
+ if (!Array.isArray(raw))
136
+ return out;
137
+ for (const streamEntry of raw) {
138
+ if (!Array.isArray(streamEntry) || streamEntry.length < 2)
139
+ continue;
140
+ const streamName = streamEntry[0];
141
+ if (streamName !== expectedStream)
142
+ continue;
143
+ const entries = streamEntry[1];
144
+ if (!Array.isArray(entries))
145
+ continue;
146
+ for (const entry of entries) {
147
+ if (!Array.isArray(entry) || entry.length < 2)
148
+ continue;
149
+ const id = entry[0];
150
+ const fields = entry[1];
151
+ if (typeof id === "string" && Array.isArray(fields)) {
152
+ out.push({ id, fields: fields });
153
+ }
154
+ }
155
+ }
156
+ return out;
157
+ }
158
+ function parseSignal(id, fields) {
159
+ const map = new Map();
160
+ for (let i = 0; i + 1 < fields.length; i += 2) {
161
+ const k = fields[i];
162
+ const v = fields[i + 1];
163
+ if (k !== undefined && v !== undefined)
164
+ map.set(k, v);
165
+ }
166
+ const sagaId = map.get("saga_id");
167
+ const eventType = map.get("event_type");
168
+ const payloadStr = map.get("payload");
169
+ if (!sagaId || !eventType || payloadStr === undefined)
170
+ return null;
171
+ let payload;
172
+ try {
173
+ payload = JSON.parse(payloadStr);
174
+ }
175
+ catch {
176
+ payload = payloadStr;
177
+ }
178
+ const scope = map.get("scope") === "global" ? "global" : "siblings";
179
+ const to = map.get("to");
180
+ return {
181
+ id,
182
+ sagaId,
183
+ eventType,
184
+ payload,
185
+ scope,
186
+ to: to === undefined || to === "" ? null : to,
187
+ };
188
+ }
189
+ //# sourceMappingURL=redis-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis-stream.js","sourceRoot":"","sources":["../../src/signal-bus/redis-stream.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ export declare function emitSagaSignal(eventType: string, payload: unknown, opts?: {
2
+ to?: string;
3
+ scope?: "siblings" | "global";
4
+ }): Promise<void>;
5
+ export declare function awaitSagaSignal<T = unknown>(eventType: string, opts?: {
6
+ from?: string;
7
+ predicate?: (payload: unknown) => boolean;
8
+ /** Poll budget in milliseconds. Default 0 = single check. */
9
+ timeoutMs?: number;
10
+ /** Test hook — defaults to setTimeout. */
11
+ sleep?: (ms: number) => Promise<void>;
12
+ }): Promise<T | null>;
13
+ export declare function awaitChildren(childIds: readonly string[], opts?: {
14
+ status?: "completed" | "any-terminal";
15
+ timeoutMs?: number;
16
+ sleep?: (ms: number) => Promise<void>;
17
+ }): Promise<void>;
18
+ export declare function awaitAnySibling<T = unknown>(eventType: string, opts?: {
19
+ predicate?: (payload: unknown) => boolean;
20
+ timeoutMs?: number;
21
+ sleep?: (ms: number) => Promise<void>;
22
+ }): Promise<T | null>;
23
+ export declare function getSiblings(opts?: {
24
+ status?: string;
25
+ }): Promise<{
26
+ id: string;
27
+ status: string;
28
+ }[]>;
29
+ //# sourceMappingURL=signals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signals.d.ts","sourceRoot":"","sources":["../src/signals.ts"],"names":[],"mappings":"AAOA,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,EAChB,IAAI,GAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAA;CAAO,GACxD,OAAO,CAAC,IAAI,CAAC,CAkBf;AAED,wBAAsB,eAAe,CAAC,CAAC,GAAG,OAAO,EAC/C,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE;IACJ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;IAC1C,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC,GACL,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CA8BnB;AAED,wBAAsB,aAAa,CACjC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,IAAI,GAAE;IACJ,MAAM,CAAC,EAAE,WAAW,GAAG,cAAc,CAAC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC,GACL,OAAO,CAAC,IAAI,CAAC,CA+Bf;AAYD,wBAAsB,eAAe,CAAC,CAAC,GAAG,OAAO,EAC/C,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE;IACJ,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC,GACL,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAEnB;AAED,wBAAsB,WAAW,CAC/B,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAC7B,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAc3C"}
@@ -0,0 +1,113 @@
1
+ // Cross-saga primitives — § 5.9. Layered on the pluggable SagaSignalBus so
2
+ // the v0.1.0 in-memory bus and the deferred Redis-stream bus expose the
3
+ // same surface.
4
+ import { requireSagaContext } from "./context";
5
+ import { requireSaga } from "./init";
6
+ export async function emitSagaSignal(eventType, payload, opts = {}) {
7
+ const cfg = requireSaga();
8
+ const ctx = requireSagaContext("emitSagaSignal");
9
+ await cfg.signalBus.emit({
10
+ sagaId: ctx.row.id,
11
+ eventType,
12
+ payload,
13
+ scope: opts.scope ?? "siblings",
14
+ to: opts.to,
15
+ });
16
+ if (cfg.telemetryAudit) {
17
+ await cfg.telemetryAudit.emit({
18
+ action: "saga_signal_emitted",
19
+ target_kind: "saga",
20
+ target_id: ctx.row.id,
21
+ payload: { event_type: eventType },
22
+ });
23
+ }
24
+ }
25
+ export async function awaitSagaSignal(eventType, opts = {}) {
26
+ const cfg = requireSaga();
27
+ const ctx = requireSagaContext("awaitSagaSignal");
28
+ const start = Date.now();
29
+ const timeoutMs = opts.timeoutMs ?? 0;
30
+ const sleep = opts.sleep ??
31
+ ((ms) => new Promise((res) => setTimeout(res, ms)));
32
+ for (;;) {
33
+ const hit = await cfg.signalBus.consume({
34
+ sagaId: ctx.row.id,
35
+ eventType,
36
+ from: opts.from,
37
+ predicate: opts.predicate,
38
+ });
39
+ if (hit !== null) {
40
+ if (cfg.telemetryAudit) {
41
+ await cfg.telemetryAudit.emit({
42
+ action: "saga_signal_received",
43
+ target_kind: "saga",
44
+ target_id: ctx.row.id,
45
+ payload: { event_type: eventType },
46
+ });
47
+ }
48
+ return hit;
49
+ }
50
+ if (Date.now() - start >= timeoutMs)
51
+ return null;
52
+ await sleep(10);
53
+ }
54
+ }
55
+ export async function awaitChildren(childIds, opts = {}) {
56
+ const cfg = requireSaga();
57
+ requireSagaContext("awaitChildren");
58
+ const want = opts.status ?? "any-terminal";
59
+ const start = Date.now();
60
+ const timeoutMs = opts.timeoutMs ?? 0;
61
+ const sleep = opts.sleep ??
62
+ ((ms) => new Promise((res) => setTimeout(res, ms)));
63
+ for (;;) {
64
+ let allDone = true;
65
+ for (const childId of childIds) {
66
+ const row = await cfg.stateStore.getSaga(childId);
67
+ if (!row) {
68
+ allDone = false;
69
+ break;
70
+ }
71
+ if (want === "completed" && row.status !== "completed") {
72
+ allDone = false;
73
+ break;
74
+ }
75
+ if (want === "any-terminal" && !TERMINAL_STATUSES.has(row.status)) {
76
+ allDone = false;
77
+ break;
78
+ }
79
+ }
80
+ if (allDone)
81
+ return;
82
+ if (Date.now() - start >= timeoutMs)
83
+ return;
84
+ await sleep(10);
85
+ }
86
+ }
87
+ const TERMINAL_STATUSES = new Set([
88
+ "completed",
89
+ "compensated",
90
+ "compensation_failed",
91
+ "compensated_with_errors",
92
+ "compensated_manual",
93
+ "technical_failure",
94
+ "cancelled",
95
+ ]);
96
+ export async function awaitAnySibling(eventType, opts = {}) {
97
+ return awaitSagaSignal(eventType, opts);
98
+ }
99
+ export async function getSiblings(opts = {}) {
100
+ const cfg = requireSaga();
101
+ const ctx = requireSagaContext("getSiblings");
102
+ if (!ctx.row.parent_saga_id)
103
+ return [];
104
+ // SagaStateStore.list is the public async accessor (matches Py + Go).
105
+ // Awaiting is mandatory — earlier versions cast to sync and `.filter`'d
106
+ // a Promise; the resulting TypeError was hidden by the cast.
107
+ const all = (await cfg.stateStore.list?.({})) ?? [];
108
+ return all
109
+ .filter((r) => r.parent_saga_id === ctx.row.parent_saga_id && r.id !== ctx.row.id)
110
+ .filter((r) => !opts.status || r.status === opts.status)
111
+ .map((r) => ({ id: r.id, status: r.status }));
112
+ }
113
+ //# sourceMappingURL=signals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signals.js","sourceRoot":"","sources":["../src/signals.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { PostgresSagaStateStore, type PostgresSagaStateStoreOpts, } from "./postgres";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/state-store/index.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,sBAAsB,EACtB,KAAK,0BAA0B,GAChC,MAAM,YAAY,CAAC"}
@@ -0,0 +1,6 @@
1
+ // Production-bound state-store exports.
2
+ //
3
+ // `PostgresSagaStateStore` is the only state store production code should
4
+ // use. For tests, see `@nodii/saga/test-doubles`.
5
+ export { PostgresSagaStateStore, } from "./postgres";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/state-store/index.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,EAAE;AACF,0EAA0E;AAC1E,kDAAkD;AAElD,OAAO,EACL,sBAAsB,GAEvB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,47 @@
1
+ import type { CompensationLogEntry, ListSagasFilter, SagaStateRow, SagaStateStore } from "../types";
2
+ type SqlClient = {
3
+ unsafe: (sql: string, args?: unknown[]) => Promise<any>;
4
+ end?: () => Promise<void>;
5
+ };
6
+ export interface PostgresSagaStateStoreOpts {
7
+ /** Live postgres.js client (or any object exposing `.unsafe(sql, args)`). */
8
+ sql: SqlClient;
9
+ /** Override the default table name; defaults to `saga_state`. */
10
+ tableName?: string;
11
+ /** Optional hook fired when an entry is truncated; used by tests + metrics. */
12
+ onTruncate?: (info: {
13
+ sagaId: string;
14
+ stepName: string;
15
+ originalBytes: number;
16
+ }) => void;
17
+ }
18
+ export declare class PostgresSagaStateStore implements SagaStateStore {
19
+ private readonly sql;
20
+ private readonly table;
21
+ private readonly onTruncate?;
22
+ constructor(opts: PostgresSagaStateStoreOpts);
23
+ createSaga(row: SagaStateRow): Promise<void>;
24
+ getSaga(sagaId: string): Promise<SagaStateRow | null>;
25
+ updateSagaStatus(sagaId: string, update: Partial<Pick<SagaStateRow, "status" | "current_step" | "completed_at" | "failure_reason" | "failure_step" | "last_admin_action" | "last_admin_actor_id" | "last_admin_at" | "cancel_reason" | "next_resume_at">>): Promise<void>;
26
+ appendStepOutput(sagaId: string, stepName: string, output: unknown): Promise<void>;
27
+ appendCompensationLog(sagaId: string, entry: CompensationLogEntry): Promise<void>;
28
+ list(filter?: ListSagasFilter): Promise<SagaStateRow[]>;
29
+ /** Reaper-side scan — used by `startSagaReaper`. */
30
+ listStalePaused(cutoffIso: string): Promise<SagaStateRow[]>;
31
+ /** Outbox helpers — see `async-step.ts`. */
32
+ writeOutboxBegin(args: {
33
+ sagaId: string;
34
+ stepName: string;
35
+ eventType: string;
36
+ payload: unknown;
37
+ tenantId: string | null;
38
+ }): Promise<void>;
39
+ readOutboxForSaga(sagaId: string): Promise<{
40
+ stepName: string;
41
+ eventType: string;
42
+ payload: unknown;
43
+ createdAt: string;
44
+ }[]>;
45
+ }
46
+ export {};
47
+ //# sourceMappingURL=postgres.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/state-store/postgres.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EACV,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,cAAc,EAEf,MAAM,UAAU,CAAC;AAIlB,KAAK,SAAS,GAAG;IAGf,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IACxD,GAAG,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B,CAAC;AAIF,MAAM,WAAW,0BAA0B;IACzC,6EAA6E;IAC7E,GAAG,EAAE,SAAS,CAAC;IACf,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,aAAa,EAAE,MAAM,CAAC;KACvB,KAAK,IAAI,CAAC;CACZ;AAED,qBAAa,sBAAuB,YAAW,cAAc;IAC3D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAY;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAIjB;gBAEC,IAAI,EAAE,0BAA0B;IAMtC,UAAU,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IA2C5C,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAmBrD,gBAAgB,CACpB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,OAAO,CACb,IAAI,CACF,YAAY,EACV,QAAQ,GACR,cAAc,GACd,cAAc,GACd,gBAAgB,GAChB,cAAc,GACd,mBAAmB,GACnB,qBAAqB,GACrB,eAAe,GACf,eAAe,GACf,gBAAgB,CACnB,CACF,GACA,OAAO,CAAC,IAAI,CAAC;IAkCV,gBAAgB,CACpB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,GACd,OAAO,CAAC,IAAI,CAAC;IA6BV,qBAAqB,CACzB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,oBAAoB,GAC1B,OAAO,CAAC,IAAI,CAAC;IAQV,IAAI,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAmC7D,oDAAoD;IAC9C,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAiBjE,4CAA4C;IACtC,gBAAgB,CAAC,IAAI,EAAE;QAC3B,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;KACzB,GAAG,OAAO,CAAC,IAAI,CAAC;IAYX,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAC9C;QACE,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,OAAO,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;KACnB,EAAE,CACJ;CAiBF"}