@plumbus/core 0.8.0-beta.1 → 0.8.0-beta.10

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 (272) hide show
  1. package/CHANGELOG.md +187 -0
  2. package/README.md +8 -1
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/ai/ai/cost-tracker.d.ts +22 -2
  5. package/dist/ai/ai/model-pricing.d.ts +8 -2
  6. package/dist/ai/ai/openai-strict-schema.d.ts +84 -0
  7. package/dist/ai/ai/provider.d.ts +90 -6
  8. package/dist/ai/ai-service.d.ts +53 -1
  9. package/dist/ai/ai-service.d.ts.map +1 -1
  10. package/dist/ai/ai-service.js +550 -119
  11. package/dist/ai/ai-service.js.map +1 -1
  12. package/dist/ai/cost-tracker.d.ts +22 -2
  13. package/dist/ai/cost-tracker.d.ts.map +1 -1
  14. package/dist/ai/cost-tracker.js +59 -20
  15. package/dist/ai/cost-tracker.js.map +1 -1
  16. package/dist/ai/explainability.d.ts +2 -1
  17. package/dist/ai/explainability.d.ts.map +1 -1
  18. package/dist/ai/explainability.js +1 -0
  19. package/dist/ai/explainability.js.map +1 -1
  20. package/dist/ai/index.d.ts +2 -2
  21. package/dist/ai/index.d.ts.map +1 -1
  22. package/dist/ai/index.js +1 -1
  23. package/dist/ai/index.js.map +1 -1
  24. package/dist/ai/model-pricing.d.ts +8 -2
  25. package/dist/ai/model-pricing.d.ts.map +1 -1
  26. package/dist/ai/model-pricing.js +113 -15
  27. package/dist/ai/model-pricing.js.map +1 -1
  28. package/dist/ai/openai-strict-schema.d.ts +85 -0
  29. package/dist/ai/openai-strict-schema.d.ts.map +1 -0
  30. package/dist/ai/openai-strict-schema.js +730 -0
  31. package/dist/ai/openai-strict-schema.js.map +1 -0
  32. package/dist/ai/prompt-overrides.d.ts +19 -0
  33. package/dist/ai/prompt-overrides.d.ts.map +1 -0
  34. package/dist/ai/prompt-overrides.js +60 -0
  35. package/dist/ai/prompt-overrides.js.map +1 -0
  36. package/dist/ai/provider-failure.d.ts +9 -0
  37. package/dist/ai/provider-failure.d.ts.map +1 -0
  38. package/dist/ai/provider-failure.js +112 -0
  39. package/dist/ai/provider-failure.js.map +1 -0
  40. package/dist/ai/provider.d.ts +90 -6
  41. package/dist/ai/provider.d.ts.map +1 -1
  42. package/dist/ai/provider.js +546 -97
  43. package/dist/ai/provider.js.map +1 -1
  44. package/dist/ai/rag/pipeline.d.ts +21 -1
  45. package/dist/ai/rag/pipeline.d.ts.map +1 -1
  46. package/dist/ai/rag/pipeline.js +17 -1
  47. package/dist/ai/rag/pipeline.js.map +1 -1
  48. package/dist/ai/tool-loop.d.ts +8 -1
  49. package/dist/ai/tool-loop.d.ts.map +1 -1
  50. package/dist/ai/tool-loop.js +7 -0
  51. package/dist/ai/tool-loop.js.map +1 -1
  52. package/dist/ai/types/config.d.ts +13 -0
  53. package/dist/ai/types/fields.d.ts +6 -0
  54. package/dist/ai/types/prompt.d.ts +9 -0
  55. package/dist/ai/usage-validation.d.ts.map +1 -1
  56. package/dist/ai/usage-validation.js +6 -1
  57. package/dist/ai/usage-validation.js.map +1 -1
  58. package/dist/ai/validation.d.ts +7 -3
  59. package/dist/ai/validation.d.ts.map +1 -1
  60. package/dist/ai/validation.js +38 -25
  61. package/dist/ai/validation.js.map +1 -1
  62. package/dist/ai/zod-to-provider-schema.d.ts.map +1 -1
  63. package/dist/ai/zod-to-provider-schema.js +246 -16
  64. package/dist/ai/zod-to-provider-schema.js.map +1 -1
  65. package/dist/api/route-generator.d.ts +2 -12
  66. package/dist/api/route-generator.d.ts.map +1 -1
  67. package/dist/api/route-generator.js +33 -41
  68. package/dist/api/route-generator.js.map +1 -1
  69. package/dist/approvals/index.d.ts +1 -1
  70. package/dist/approvals/index.d.ts.map +1 -1
  71. package/dist/approvals/index.js.map +1 -1
  72. package/dist/approvals/memory-store.d.ts.map +1 -1
  73. package/dist/approvals/memory-store.js +22 -0
  74. package/dist/approvals/memory-store.js.map +1 -1
  75. package/dist/approvals/schema.d.ts +34 -0
  76. package/dist/approvals/schema.d.ts.map +1 -1
  77. package/dist/approvals/schema.js +2 -0
  78. package/dist/approvals/schema.js.map +1 -1
  79. package/dist/approvals/service.d.ts.map +1 -1
  80. package/dist/approvals/service.js +36 -0
  81. package/dist/approvals/service.js.map +1 -1
  82. package/dist/approvals/sql-store.d.ts.map +1 -1
  83. package/dist/approvals/sql-store.js +42 -1
  84. package/dist/approvals/sql-store.js.map +1 -1
  85. package/dist/approvals/types.d.ts +11 -0
  86. package/dist/approvals/types.d.ts.map +1 -1
  87. package/dist/approvals/types.js +1 -0
  88. package/dist/approvals/types.js.map +1 -1
  89. package/dist/audit/service.d.ts.map +1 -1
  90. package/dist/audit/service.js +16 -1
  91. package/dist/audit/service.js.map +1 -1
  92. package/dist/cli/cli.d.ts.map +1 -1
  93. package/dist/cli/cli.js +2 -1
  94. package/dist/cli/cli.js.map +1 -1
  95. package/dist/cli/commands/browser-extension.d.ts +16 -0
  96. package/dist/cli/commands/browser-extension.d.ts.map +1 -1
  97. package/dist/cli/commands/browser-extension.js +16 -5
  98. package/dist/cli/commands/browser-extension.js.map +1 -1
  99. package/dist/cli/commands/dev.d.ts.map +1 -1
  100. package/dist/cli/commands/dev.js +7 -1
  101. package/dist/cli/commands/dev.js.map +1 -1
  102. package/dist/cli/commands/e2e.d.ts +12 -0
  103. package/dist/cli/commands/e2e.d.ts.map +1 -1
  104. package/dist/cli/commands/e2e.js +11 -0
  105. package/dist/cli/commands/e2e.js.map +1 -1
  106. package/dist/cli/commands/generate-openapi-from-zod.d.ts.map +1 -1
  107. package/dist/cli/commands/generate-openapi-from-zod.js +9 -1
  108. package/dist/cli/commands/generate-openapi-from-zod.js.map +1 -1
  109. package/dist/cli/commands/index.d.ts +1 -0
  110. package/dist/cli/commands/index.d.ts.map +1 -1
  111. package/dist/cli/commands/index.js +1 -0
  112. package/dist/cli/commands/index.js.map +1 -1
  113. package/dist/cli/commands/init.d.ts +1 -1
  114. package/dist/cli/commands/init.d.ts.map +1 -1
  115. package/dist/cli/commands/init.js +63 -3
  116. package/dist/cli/commands/init.js.map +1 -1
  117. package/dist/cli/commands/migrate.d.ts.map +1 -1
  118. package/dist/cli/commands/migrate.js +8 -14
  119. package/dist/cli/commands/migrate.js.map +1 -1
  120. package/dist/cli/commands/payments.d.ts +56 -0
  121. package/dist/cli/commands/payments.d.ts.map +1 -0
  122. package/dist/cli/commands/payments.js +184 -0
  123. package/dist/cli/commands/payments.js.map +1 -0
  124. package/dist/cli/commands/run.d.ts.map +1 -1
  125. package/dist/cli/commands/run.js +2 -7
  126. package/dist/cli/commands/run.js.map +1 -1
  127. package/dist/cli/commands/seed.d.ts.map +1 -1
  128. package/dist/cli/commands/seed.js +2 -7
  129. package/dist/cli/commands/seed.js.map +1 -1
  130. package/dist/cli/commands/start.d.ts.map +1 -1
  131. package/dist/cli/commands/start.js +9 -1
  132. package/dist/cli/commands/start.js.map +1 -1
  133. package/dist/cli/commands/worker.js +1 -1
  134. package/dist/cli/commands/worker.js.map +1 -1
  135. package/dist/cli/discover.d.ts +2 -0
  136. package/dist/cli/discover.d.ts.map +1 -1
  137. package/dist/cli/discover.js +39 -5
  138. package/dist/cli/discover.js.map +1 -1
  139. package/dist/config/loader.d.ts +4 -1
  140. package/dist/config/loader.d.ts.map +1 -1
  141. package/dist/config/loader.js +112 -24
  142. package/dist/config/loader.js.map +1 -1
  143. package/dist/data/connection.d.ts +23 -0
  144. package/dist/data/connection.d.ts.map +1 -1
  145. package/dist/data/connection.js +23 -6
  146. package/dist/data/connection.js.map +1 -1
  147. package/dist/data/schema-generator.d.ts.map +1 -1
  148. package/dist/data/schema-generator.js +2 -2
  149. package/dist/data/schema-generator.js.map +1 -1
  150. package/dist/define/definePrompt.d.ts.map +1 -1
  151. package/dist/define/definePrompt.js +6 -0
  152. package/dist/define/definePrompt.js.map +1 -1
  153. package/dist/durable/index.d.ts +2 -2
  154. package/dist/durable/index.d.ts.map +1 -1
  155. package/dist/durable/index.js +2 -2
  156. package/dist/durable/index.js.map +1 -1
  157. package/dist/durable/postgres-persist.d.ts +47 -2
  158. package/dist/durable/postgres-persist.d.ts.map +1 -1
  159. package/dist/durable/postgres-persist.js +152 -6
  160. package/dist/durable/postgres-persist.js.map +1 -1
  161. package/dist/durable/spine-claim.d.ts +22 -1
  162. package/dist/durable/spine-claim.d.ts.map +1 -1
  163. package/dist/durable/spine-claim.js +54 -3
  164. package/dist/durable/spine-claim.js.map +1 -1
  165. package/dist/events/dispatcher.d.ts +20 -0
  166. package/dist/events/dispatcher.d.ts.map +1 -1
  167. package/dist/events/dispatcher.js +61 -26
  168. package/dist/events/dispatcher.js.map +1 -1
  169. package/dist/events/pipeline-audit.d.ts +14 -0
  170. package/dist/events/pipeline-audit.d.ts.map +1 -0
  171. package/dist/events/pipeline-audit.js +29 -0
  172. package/dist/events/pipeline-audit.js.map +1 -0
  173. package/dist/events/worker.d.ts +3 -0
  174. package/dist/events/worker.d.ts.map +1 -1
  175. package/dist/events/worker.js +14 -14
  176. package/dist/events/worker.js.map +1 -1
  177. package/dist/execution/capability-error-hook.d.ts +24 -0
  178. package/dist/execution/capability-error-hook.d.ts.map +1 -0
  179. package/dist/execution/capability-error-hook.js +17 -0
  180. package/dist/execution/capability-error-hook.js.map +1 -0
  181. package/dist/execution/capability-executor.d.ts +2 -2
  182. package/dist/execution/capability-executor.d.ts.map +1 -1
  183. package/dist/execution/capability-executor.js +45 -7
  184. package/dist/execution/capability-executor.js.map +1 -1
  185. package/dist/execution/context-factory.d.ts.map +1 -1
  186. package/dist/execution/context-factory.js +9 -1
  187. package/dist/execution/context-factory.js.map +1 -1
  188. package/dist/execution/deferred-flow-service.d.ts.map +1 -1
  189. package/dist/execution/deferred-flow-service.js +7 -0
  190. package/dist/execution/deferred-flow-service.js.map +1 -1
  191. package/dist/execution/index.d.ts +1 -0
  192. package/dist/execution/index.d.ts.map +1 -1
  193. package/dist/execution/index.js.map +1 -1
  194. package/dist/fields/index.d.ts +7 -0
  195. package/dist/fields/index.d.ts.map +1 -1
  196. package/dist/fields/index.js +10 -1
  197. package/dist/fields/index.js.map +1 -1
  198. package/dist/flows/dead-letter.d.ts +18 -1
  199. package/dist/flows/dead-letter.d.ts.map +1 -1
  200. package/dist/flows/dead-letter.js +17 -1
  201. package/dist/flows/dead-letter.js.map +1 -1
  202. package/dist/flows/engine.d.ts +16 -1
  203. package/dist/flows/engine.d.ts.map +1 -1
  204. package/dist/flows/engine.js +218 -29
  205. package/dist/flows/engine.js.map +1 -1
  206. package/dist/flows/flow-service.d.ts.map +1 -1
  207. package/dist/flows/flow-service.js +3 -0
  208. package/dist/flows/flow-service.js.map +1 -1
  209. package/dist/flows/step-executor.d.ts +8 -0
  210. package/dist/flows/step-executor.d.ts.map +1 -1
  211. package/dist/flows/step-executor.js.map +1 -1
  212. package/dist/index.d.ts +4 -4
  213. package/dist/index.d.ts.map +1 -1
  214. package/dist/index.js +1 -1
  215. package/dist/index.js.map +1 -1
  216. package/dist/runtime/bootstrap.d.ts +18 -1
  217. package/dist/runtime/bootstrap.d.ts.map +1 -1
  218. package/dist/runtime/bootstrap.js +36 -5
  219. package/dist/runtime/bootstrap.js.map +1 -1
  220. package/dist/runtime/load-extensions.d.ts +2 -1
  221. package/dist/runtime/load-extensions.d.ts.map +1 -1
  222. package/dist/runtime/load-extensions.js +49 -1
  223. package/dist/runtime/load-extensions.js.map +1 -1
  224. package/dist/runtime/register-consumers.d.ts +3 -0
  225. package/dist/runtime/register-consumers.d.ts.map +1 -1
  226. package/dist/runtime/register-consumers.js +27 -6
  227. package/dist/runtime/register-consumers.js.map +1 -1
  228. package/dist/runtime/start-worker-pool.d.ts.map +1 -1
  229. package/dist/runtime/start-worker-pool.js +36 -15
  230. package/dist/runtime/start-worker-pool.js.map +1 -1
  231. package/dist/server/bootstrap.d.ts +42 -16
  232. package/dist/server/bootstrap.d.ts.map +1 -1
  233. package/dist/server/bootstrap.js +91 -21
  234. package/dist/server/bootstrap.js.map +1 -1
  235. package/dist/testing/context.d.ts +2 -0
  236. package/dist/testing/context.d.ts.map +1 -1
  237. package/dist/testing/context.js +8 -3
  238. package/dist/testing/context.js.map +1 -1
  239. package/dist/testing/field-validation.d.ts.map +1 -1
  240. package/dist/testing/field-validation.js +3 -0
  241. package/dist/testing/field-validation.js.map +1 -1
  242. package/dist/types/config.d.ts +13 -0
  243. package/dist/types/config.d.ts.map +1 -1
  244. package/dist/types/context.d.ts +70 -4
  245. package/dist/types/context.d.ts.map +1 -1
  246. package/dist/types/fields.d.ts +6 -0
  247. package/dist/types/fields.d.ts.map +1 -1
  248. package/dist/types/index.d.ts +1 -1
  249. package/dist/types/index.d.ts.map +1 -1
  250. package/dist/types/index.js.map +1 -1
  251. package/dist/types/prompt.d.ts +9 -0
  252. package/dist/types/prompt.d.ts.map +1 -1
  253. package/dist/worker/bootstrap.d.ts +19 -0
  254. package/dist/worker/bootstrap.d.ts.map +1 -1
  255. package/dist/worker/bootstrap.js +156 -84
  256. package/dist/worker/bootstrap.js.map +1 -1
  257. package/instructions/README.md +4 -1
  258. package/instructions/ai-classification.md +132 -0
  259. package/instructions/ai.md +94 -15
  260. package/instructions/cli.md +19 -1
  261. package/instructions/entities.md +3 -1
  262. package/instructions/flows.md +6 -0
  263. package/instructions/framework.md +13 -3
  264. package/instructions/peer-dependencies.md +2 -1
  265. package/instructions/prompts.md +2 -1
  266. package/migrations/durable-tenant/0002_approval_cancellation.sql +3 -0
  267. package/migrations/durable-tenant/meta/_journal.json +7 -0
  268. package/package.json +6 -5
  269. package/dist/ai/__typecheck-fixtures__/legacy-cost-api.d.ts +0 -5
  270. package/dist/ai/__typecheck-fixtures__/legacy-cost-api.d.ts.map +0 -1
  271. package/dist/ai/__typecheck-fixtures__/legacy-cost-api.js +0 -15
  272. package/dist/ai/__typecheck-fixtures__/legacy-cost-api.js.map +0 -1
@@ -1,10 +1,10 @@
1
1
  // Tenant-local Protocol A writes against real Postgres. Same CAS + outbox
2
2
  // pairing as persist-before-ack.ts; used by the flow engine when spineDispatch
3
3
  // is configured.
4
- import { sql } from 'drizzle-orm';
5
4
  import { randomUUID } from 'node:crypto';
6
- import { PlumbusError } from '../errors/index.js';
5
+ import { sql } from 'drizzle-orm';
7
6
  import { FRAMEWORK_SCHEMA } from '../data/schema-generator.js';
7
+ import { PlumbusError } from '../errors/index.js';
8
8
  import { qualifyTable } from './apply-ddl.js';
9
9
  import { createOpaqueDispatchRecord } from './opaque-dispatch.js';
10
10
  import { upsertSpineDispatch } from './spine-claim.js';
@@ -146,6 +146,125 @@ export async function casAdvanceExecution(db, input, schemaName = FRAMEWORK_SCHE
146
146
  }
147
147
  return 'ok';
148
148
  }
149
+ /**
150
+ * Persist a retry delay on the tenant plane before the current spine hint is acknowledged.
151
+ * The execution-state CAS, retry wait, and future-dated outbox row are one transaction.
152
+ */
153
+ export async function persistRetryScheduleOnDb(db, input, nowIso, schemaName = FRAMEWORK_SCHEMA) {
154
+ const executionTable = qualifyTable(schemaName, 'execution_state');
155
+ const waitTable = qualifyTable(schemaName, 'wait_state');
156
+ const outboxTable = qualifyTable(schemaName, 'dispatch_outbox');
157
+ return db.transaction(async (tx) => {
158
+ const scoped = tx;
159
+ const current = await loadExecutionState(scoped, input.executionId, schemaName);
160
+ if (!current)
161
+ return { kind: 'missing' };
162
+ if (current.tenantEpoch !== input.tenantEpoch)
163
+ return { kind: 'epoch-mismatch' };
164
+ if (current.revision !== input.expectedRevision || current.terminal) {
165
+ return { kind: 'stale', execution: current };
166
+ }
167
+ const updated = asRows(await scoped.execute(sql `
168
+ UPDATE ${sql.raw(executionTable)}
169
+ SET revision = ${input.expectedRevision + 1},
170
+ status = ${DurableExecutionStatus.RetryScheduled},
171
+ current_step_id = ${input.stepId},
172
+ attempt = attempt + 1,
173
+ wake_at = ${input.notBefore}::timestamptz,
174
+ updated_at = ${nowIso}::timestamptz,
175
+ terminal = false
176
+ WHERE execution_id = ${input.executionId}
177
+ AND revision = ${input.expectedRevision}
178
+ AND tenant_epoch = ${input.tenantEpoch}
179
+ AND terminal = false
180
+ RETURNING *
181
+ `));
182
+ const nextRow = updated[0];
183
+ if (!nextRow) {
184
+ const latest = await loadExecutionState(scoped, input.executionId, schemaName);
185
+ return latest ? { kind: 'stale', execution: latest } : { kind: 'missing' };
186
+ }
187
+ const next = mapExecution(nextRow);
188
+ const waitStateId = `wait:${input.executionId}:${next.revision}`;
189
+ await scoped.execute(sql `
190
+ INSERT INTO ${sql.raw(waitTable)} (
191
+ wait_state_id, execution_id, step_id, kind, state,
192
+ created_at, updated_at, not_before
193
+ ) VALUES (
194
+ ${waitStateId}, ${input.executionId}, ${input.stepId}, 'retry', 'waiting',
195
+ ${nowIso}::timestamptz, ${nowIso}::timestamptz, ${input.notBefore}::timestamptz
196
+ )
197
+ ON CONFLICT (wait_state_id) DO NOTHING
198
+ `);
199
+ const outboxId = `outbox:${input.executionId}:${next.revision}:${randomUUID()}`;
200
+ const inserted = asRows(await scoped.execute(sql `
201
+ INSERT INTO ${sql.raw(outboxTable)} (
202
+ outbox_id, execution_id, state_ref_id, expected_revision, tenant_epoch,
203
+ tenant_ref, step_id, definition_id, definition_version, correlation_id,
204
+ work_class_id, priority_class_id, not_before, created_at, superseded
205
+ ) VALUES (
206
+ ${outboxId}, ${next.executionId}, ${next.stateRefId}, ${next.revision},
207
+ ${next.tenantEpoch}, ${next.tenantRef}, ${input.stepId}, ${next.definitionId},
208
+ ${next.definitionVersion}, ${next.correlationId}, ${DEFAULT_WORK_CLASS_ID},
209
+ ${DEFAULT_PRIORITY_CLASS_ID}, ${input.notBefore}::timestamptz,
210
+ ${nowIso}::timestamptz, false
211
+ )
212
+ RETURNING *
213
+ `));
214
+ const outboxRow = inserted[0];
215
+ if (!outboxRow) {
216
+ throw new PlumbusError('internal', 'Retry schedule wrote no dispatch outbox row');
217
+ }
218
+ return {
219
+ kind: 'committed',
220
+ execution: next,
221
+ outbox: mapOutbox(outboxRow),
222
+ sideEffectApplied: false,
223
+ };
224
+ });
225
+ }
226
+ /**
227
+ * Closes a tenant execution's durable state without a claimed hint — an operator cancel, or
228
+ * any terminal transition taken outside the run loop. The spine hint, if one is still ready,
229
+ * is dropped by the next claim that sees the state terminal. No-op when the state is already
230
+ * terminal or absent.
231
+ */
232
+ export async function markExecutionStateTerminal(db, input, schemaName = FRAMEWORK_SCHEMA) {
233
+ const executionTable = qualifyTable(schemaName, 'execution_state');
234
+ const result = await db.execute(sql `
235
+ UPDATE ${sql.raw(executionTable)}
236
+ SET revision = revision + 1,
237
+ status = ${input.status},
238
+ terminal = true,
239
+ updated_at = ${input.nowIso}::timestamptz,
240
+ wake_at = NULL
241
+ WHERE execution_id = ${input.executionId}
242
+ AND terminal = false
243
+ RETURNING execution_id
244
+ `);
245
+ return asRows(result).length > 0;
246
+ }
247
+ /**
248
+ * Reopens a terminal tenant execution for an operator retry: a fresh revision, `created`,
249
+ * pointed at the step to run again. The caller publishes the outbox row this makes
250
+ * necessary. Undefined when the plane holds no durable state for the execution (a row
251
+ * started before tenant placement, or a control-plane flow).
252
+ */
253
+ export async function reopenExecutionState(db, input, schemaName = FRAMEWORK_SCHEMA) {
254
+ const executionTable = qualifyTable(schemaName, 'execution_state');
255
+ await db.execute(sql `
256
+ UPDATE ${sql.raw(executionTable)}
257
+ SET revision = revision + 1,
258
+ status = ${DurableExecutionStatus.Created},
259
+ current_step_id = ${input.stepId},
260
+ attempt = 0,
261
+ terminal = false,
262
+ updated_at = ${input.nowIso}::timestamptz,
263
+ wake_at = NULL
264
+ WHERE execution_id = ${input.executionId}
265
+ `);
266
+ return loadExecutionState(db, input.executionId, schemaName);
267
+ }
149
268
  export async function insertDispatchOutbox(db, execution, stepId, nowIso, schemaName = FRAMEWORK_SCHEMA) {
150
269
  const outboxTable = qualifyTable(schemaName, 'dispatch_outbox');
151
270
  const outboxId = `outbox:${execution.executionId}:${execution.revision}:${randomUUID()}`;
@@ -167,9 +286,14 @@ export async function insertDispatchOutbox(db, execution, stepId, nowIso, schema
167
286
  throw new PlumbusError('internal', 'Inserted dispatch outbox row could not be read');
168
287
  return mapOutbox(row);
169
288
  }
289
+ /**
290
+ * Outbox rows the spine has not been told about. A row that was published is the spine's
291
+ * until it is acknowledged — republishing it would reset a hint another worker holds the
292
+ * lease on; the reconciliation sweep, not the pump, is what re-examines published rows.
293
+ */
170
294
  export async function listUnpublishedOutbox(db, schemaName = FRAMEWORK_SCHEMA) {
171
295
  const outboxTable = qualifyTable(schemaName, 'dispatch_outbox');
172
- const result = await db.execute(sql `SELECT * FROM ${sql.raw(outboxTable)} WHERE superseded = false AND spine_acked_at IS NULL`);
296
+ const result = await db.execute(sql `SELECT * FROM ${sql.raw(outboxTable)} WHERE superseded = false AND spine_acked_at IS NULL AND published_at IS NULL`);
173
297
  return asRows(result).map(mapOutbox);
174
298
  }
175
299
  export async function markOutboxPublished(db, outboxId, spineRowId, nowIso, schemaName = FRAMEWORK_SCHEMA) {
@@ -188,7 +312,28 @@ export async function markOutboxAcked(db, outboxId, nowIso, schemaName = FRAMEWO
188
312
  WHERE outbox_id = ${outboxId}
189
313
  `);
190
314
  }
191
- export async function publishOutboxToSpine(tenantDb, spineDb, outbox, dispatchId, nowIso, schemaName = FRAMEWORK_SCHEMA) {
315
+ /** Closes the outbox row behind an acknowledged spine hint, by the spine row it was published as. */
316
+ export async function markOutboxAckedBySpineRow(db, spineRowId, nowIso, schemaName = FRAMEWORK_SCHEMA) {
317
+ const outboxTable = qualifyTable(schemaName, 'dispatch_outbox');
318
+ await db.execute(sql `
319
+ UPDATE ${sql.raw(outboxTable)}
320
+ SET spine_acked_at = ${nowIso}::timestamptz
321
+ WHERE spine_row_id = ${spineRowId}
322
+ AND spine_acked_at IS NULL
323
+ `);
324
+ }
325
+ /**
326
+ * Publishes an outbox row as a spine hint. With `lease`, the hint is born leased by that
327
+ * worker — the one that will run the step in the same drain without a claim in between —
328
+ * so no other worker claims it meanwhile; the lease lapses like any other if the worker dies.
329
+ */
330
+ export async function publishOutboxToSpine(tenantDb, spineDb, outbox, dispatchId, nowIso, schemaName = FRAMEWORK_SCHEMA, options) {
331
+ const leased = options !== undefined && 'workerId' in options;
332
+ const deliveryState = options !== undefined && 'deliveryState' in options
333
+ ? options.deliveryState
334
+ : leased
335
+ ? SpineDeliveryState.Leased
336
+ : SpineDeliveryState.Ready;
192
337
  const record = createOpaqueDispatchRecord({
193
338
  dispatchId,
194
339
  tenantRouteId: outbox.tenantRef,
@@ -201,9 +346,10 @@ export async function publishOutboxToSpine(tenantDb, spineDb, outbox, dispatchId
201
346
  tenantEpoch: outbox.tenantEpoch,
202
347
  workClassId: outbox.workClassId,
203
348
  priorityClassId: outbox.priorityClassId,
204
- deliveryState: SpineDeliveryState.Ready,
205
- attempt: 0,
349
+ deliveryState,
350
+ attempt: leased ? 1 : 0,
206
351
  notBefore: outbox.notBefore,
352
+ ...(leased ? { leaseRefId: options.workerId, leaseExpiresAt: options.leaseExpiresAt } : {}),
207
353
  correlationId: outbox.correlationId,
208
354
  createdAt: nowIso,
209
355
  updatedAt: nowIso,
@@ -1 +1 @@
1
- {"version":3,"file":"postgres-persist.js","sourceRoot":"","sources":["../../src/durable/postgres-persist.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"postgres-persist.js","sourceRoot":"","sources":["../../src/durable/postgres-persist.ts"],"names":[],"mappings":"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"}
@@ -6,11 +6,32 @@ export interface SpineClaimOptions {
6
6
  leaseDurationMs: number;
7
7
  limit?: number;
8
8
  }
9
+ export interface SpineLeaseOptions {
10
+ dispatchId: string;
11
+ workerId: string;
12
+ leaseDurationMs: number;
13
+ }
9
14
  /**
10
15
  * Claim ready (or lease-expired) spine rows. Concurrent callers each get
11
16
  * different rows because of FOR UPDATE SKIP LOCKED.
12
17
  */
13
18
  export declare function claimSpineDispatch(db: PostgresJsDatabase, options: SpineClaimOptions): Promise<OpaqueDispatchRecord[]>;
14
- export declare function ackSpineDispatch(db: PostgresJsDatabase, dispatchId: string): Promise<boolean>;
19
+ /**
20
+ * Extend one leased spine hint only while the same worker still owns it.
21
+ * A zero-row result is lease loss, not a transient database failure.
22
+ */
23
+ export declare function extendSpineDispatchLease(db: PostgresJsDatabase, options: SpineLeaseOptions): Promise<boolean>;
24
+ /**
25
+ * The tenant route the spine last dispatched an execution for, whatever the hint's state.
26
+ * A request-side engine that never claimed the execution uses this to find the plane its row
27
+ * lives on before it reads, cancels or resumes it. Undefined when the spine holds no hint.
28
+ */
29
+ export declare function findSpineDispatchTenantRoute(db: PostgresJsDatabase, executionId: string): Promise<string | undefined>;
30
+ export declare function ackSpineDispatch(db: PostgresJsDatabase, dispatchId: string, workerId?: string): Promise<boolean>;
31
+ /**
32
+ * Parks a hint no claim can act on — its tenant route cannot be resolved claim after claim —
33
+ * so it stops being re-leased on every poll. Left for an operator; never claimed again.
34
+ */
35
+ export declare function deadLetterSpineDispatch(db: PostgresJsDatabase, dispatchId: string, failureCategoryId: string): Promise<boolean>;
15
36
  export declare function upsertSpineDispatch(db: PostgresJsDatabase, record: OpaqueDispatchRecord): Promise<OpaqueDispatchRecord>;
16
37
  //# sourceMappingURL=spine-claim.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"spine-claim.d.ts","sourceRoot":"","sources":["../../src/durable/spine-claim.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAElE,OAAO,EAAsB,KAAK,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAqB3E,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,oBAAoB,CA0BlF;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,kBAAkB,EACtB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,oBAAoB,EAAE,CAAC,CA0BjC;AAED,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,kBAAkB,EACtB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC,CAWlB;AAED,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,kBAAkB,EACtB,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,oBAAoB,CAAC,CAgC/B"}
1
+ {"version":3,"file":"spine-claim.d.ts","sourceRoot":"","sources":["../../src/durable/spine-claim.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAElE,OAAO,EAAE,KAAK,oBAAoB,EAAsB,MAAM,YAAY,CAAC;AAqB3E,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,oBAAoB,CA0BlF;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,kBAAkB,EACtB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,oBAAoB,EAAE,CAAC,CA0BjC;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,EAAE,EAAE,kBAAkB,EACtB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,OAAO,CAAC,CAWlB;AAED;;;;GAIG;AACH,wBAAsB,4BAA4B,CAChD,EAAE,EAAE,kBAAkB,EACtB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAU7B;AAED,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,kBAAkB,EACtB,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAYlB;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,kBAAkB,EACtB,UAAU,EAAE,MAAM,EAClB,iBAAiB,EAAE,MAAM,GACxB,OAAO,CAAC,OAAO,CAAC,CAalB;AAED,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,kBAAkB,EACtB,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,oBAAoB,CAAC,CAgC/B"}
@@ -82,7 +82,39 @@ export async function claimSpineDispatch(db, options) {
82
82
  `);
83
83
  return asRows(result).map(spineRowFromSql);
84
84
  }
85
- export async function ackSpineDispatch(db, dispatchId) {
85
+ /**
86
+ * Extend one leased spine hint only while the same worker still owns it.
87
+ * A zero-row result is lease loss, not a transient database failure.
88
+ */
89
+ export async function extendSpineDispatchLease(db, options) {
90
+ const leaseDurationInterval = `${options.leaseDurationMs} milliseconds`;
91
+ const result = await db.execute(sql `
92
+ UPDATE opaque_dispatch
93
+ SET lease_expires_at = now() + ${leaseDurationInterval}::interval,
94
+ updated_at = now()
95
+ WHERE dispatch_id = ${options.dispatchId}
96
+ AND delivery_state = ${SpineDeliveryState.Leased}
97
+ AND lease_ref_id = ${options.workerId}
98
+ `);
99
+ return getRowsAffected(result) > 0;
100
+ }
101
+ /**
102
+ * The tenant route the spine last dispatched an execution for, whatever the hint's state.
103
+ * A request-side engine that never claimed the execution uses this to find the plane its row
104
+ * lives on before it reads, cancels or resumes it. Undefined when the spine holds no hint.
105
+ */
106
+ export async function findSpineDispatchTenantRoute(db, executionId) {
107
+ const result = await db.execute(sql `
108
+ SELECT tenant_route_id
109
+ FROM opaque_dispatch
110
+ WHERE execution_id = ${executionId}
111
+ ORDER BY created_at DESC
112
+ LIMIT 1
113
+ `);
114
+ const row = asRows(result)[0];
115
+ return row?.tenant_route_id == null ? undefined : String(row.tenant_route_id);
116
+ }
117
+ export async function ackSpineDispatch(db, dispatchId, workerId) {
86
118
  const result = await db.execute(sql `
87
119
  UPDATE opaque_dispatch
88
120
  SET delivery_state = ${SpineDeliveryState.Acknowledged},
@@ -91,6 +123,25 @@ export async function ackSpineDispatch(db, dispatchId) {
91
123
  updated_at = now()
92
124
  WHERE dispatch_id = ${dispatchId}
93
125
  AND delivery_state <> ${SpineDeliveryState.Acknowledged}
126
+ ${workerId === undefined ? sql `` : sql `AND lease_ref_id = ${workerId}`}
127
+ `);
128
+ return getRowsAffected(result) > 0;
129
+ }
130
+ /**
131
+ * Parks a hint no claim can act on — its tenant route cannot be resolved claim after claim —
132
+ * so it stops being re-leased on every poll. Left for an operator; never claimed again.
133
+ */
134
+ export async function deadLetterSpineDispatch(db, dispatchId, failureCategoryId) {
135
+ const result = await db.execute(sql `
136
+ UPDATE opaque_dispatch
137
+ SET delivery_state = ${SpineDeliveryState.DeadLettered},
138
+ lease_ref_id = NULL,
139
+ lease_expires_at = NULL,
140
+ privacy_safe_failure_category_id = ${failureCategoryId},
141
+ updated_at = now()
142
+ WHERE dispatch_id = ${dispatchId}
143
+ AND delivery_state <> ${SpineDeliveryState.Acknowledged}
144
+ AND delivery_state <> ${SpineDeliveryState.DeadLettered}
94
145
  `);
95
146
  return getRowsAffected(result) > 0;
96
147
  }
@@ -119,8 +170,8 @@ export async function upsertSpineDispatch(db, record) {
119
170
  tenant_epoch = EXCLUDED.tenant_epoch,
120
171
  not_before = EXCLUDED.not_before,
121
172
  updated_at = EXCLUDED.updated_at,
122
- lease_ref_id = NULL,
123
- lease_expires_at = NULL
173
+ lease_ref_id = EXCLUDED.lease_ref_id,
174
+ lease_expires_at = EXCLUDED.lease_expires_at
124
175
  RETURNING *
125
176
  `);
126
177
  const row = asRows(result)[0];
@@ -1 +1 @@
1
- {"version":3,"file":"spine-claim.js","sourceRoot":"","sources":["../../src/durable/spine-claim.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"spine-claim.js","sourceRoot":"","sources":["../../src/durable/spine-claim.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,kFAAkF;AAElF,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAElC,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAA6B,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAE3E,SAAS,eAAe,CAAC,MAAe;IACtC,MAAM,CAAC,GAAG,MAAsF,CAAC;IACjG,IAAI,OAAO,CAAC,EAAE,QAAQ,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC,QAAQ,CAAC;IACvD,IAAI,OAAO,CAAC,EAAE,KAAK,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC,KAAK,CAAC;IACjD,IAAI,OAAO,CAAC,EAAE,MAAM,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC,MAAM,CAAC;IACnD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,MAAM,CAAC,MAAe;IAC7B,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,MAAmC,CAAC;IACtE,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,KAAK,CAAC,KAAc;IAC3B,IAAI,KAAK,YAAY,IAAI;QAAE,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC;IACtD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,MAAM,IAAI,KAAK,CAAC,6BAA6B,OAAO,KAAK,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAA4B;IAC1D,OAAO,0BAA0B,CAAC;QAChC,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC;QACnC,aAAa,EAAE,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC;QAC1C,WAAW,EAAE,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC;QACrC,YAAY,EAAE,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC;QACvC,iBAAiB,EAAE,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC;QACjD,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;QAC3B,yBAAyB,EAAE,MAAM,CAAC,GAAG,CAAC,6BAA6B,CAAC;QACpE,gBAAgB,EAAE,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC;QAC/C,WAAW,EAAE,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC;QACrC,WAAW,EAAE,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC;QACtC,eAAe,EAAE,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC;QAC9C,aAAa,EAAE,GAAG,CAAC,cAAuD;QAC1E,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;QAC5B,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC;QAChC,UAAU,EAAE,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC;QAC3E,cAAc,EAAE,GAAG,CAAC,gBAAgB,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC;QACtF,4BAA4B,EAC1B,GAAG,CAAC,gCAAgC,IAAI,IAAI;YAC1C,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,gCAAgC,CAAC;QAClD,aAAa,EAAE,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC;QACzC,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC;QAChC,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC;KACjC,CAAC,CAAC;AACL,CAAC;AAcD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,EAAsB,EACtB,OAA0B;IAE1B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;IAClC,MAAM,qBAAqB,GAAG,GAAG,OAAO,CAAC,eAAe,eAAe,CAAC;IACxE,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA;;2BAEV,kBAAkB,CAAC,MAAM;yBAC3B,OAAO,CAAC,QAAQ;qCACJ,qBAAqB;;;;;;;;6BAQ7B,kBAAkB,CAAC,KAAK;gCACrB,kBAAkB,CAAC,cAAc;iCAChC,kBAAkB,CAAC,MAAM;;;;cAI5C,KAAK;;;GAGhB,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;AAC7C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,EAAsB,EACtB,OAA0B;IAE1B,MAAM,qBAAqB,GAAG,GAAG,OAAO,CAAC,eAAe,eAAe,CAAC;IACxE,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA;;qCAEA,qBAAqB;;0BAEhC,OAAO,CAAC,UAAU;6BACf,kBAAkB,CAAC,MAAM;2BAC3B,OAAO,CAAC,QAAQ;GACxC,CAAC,CAAC;IACH,OAAO,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AACrC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,EAAsB,EACtB,WAAmB;IAEnB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA;;;2BAGV,WAAW;;;GAGnC,CAAC,CAAC;IACH,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9B,OAAO,GAAG,EAAE,eAAe,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;AAChF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,EAAsB,EACtB,UAAkB,EAClB,QAAiB;IAEjB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA;;2BAEV,kBAAkB,CAAC,YAAY;;;;0BAIhC,UAAU;8BACN,kBAAkB,CAAC,YAAY;QACrD,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAA,EAAE,CAAC,CAAC,CAAC,GAAG,CAAA,sBAAsB,QAAQ,EAAE;GACzE,CAAC,CAAC;IACH,OAAO,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,EAAsB,EACtB,UAAkB,EAClB,iBAAyB;IAEzB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA;;2BAEV,kBAAkB,CAAC,YAAY;;;6CAGb,iBAAiB;;0BAEpC,UAAU;8BACN,kBAAkB,CAAC,YAAY;8BAC/B,kBAAkB,CAAC,YAAY;GAC1D,CAAC,CAAC;IACH,OAAO,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,EAAsB,EACtB,MAA4B;IAE5B,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA;;;;;;;;QAQ7B,MAAM,CAAC,UAAU,KAAK,MAAM,CAAC,eAAe,KAAK,MAAM,CAAC,aAAa;QACrE,MAAM,CAAC,WAAW,KAAK,MAAM,CAAC,YAAY,KAAK,MAAM,CAAC,iBAAiB;QACvE,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,yBAAyB;QAClD,MAAM,CAAC,gBAAgB,KAAK,MAAM,CAAC,WAAW,KAAK,MAAM,CAAC,WAAW;QACrE,MAAM,CAAC,eAAe,KAAK,MAAM,CAAC,aAAa,KAAK,MAAM,CAAC,OAAO;QAClE,MAAM,CAAC,SAAS,kBAAkB,MAAM,CAAC,UAAU,IAAI,IAAI;QAC3D,MAAM,CAAC,cAAc,IAAI,IAAI,KAAK,MAAM,CAAC,4BAA4B,IAAI,IAAI;QAC7E,MAAM,CAAC,aAAa,KAAK,MAAM,CAAC,SAAS,kBAAkB,MAAM,CAAC,SAAS;;;;;;;;;;;;GAYhF,CAAC,CAAC;IACH,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAC1D,OAAO,eAAe,CAAC,GAAG,CAAC,CAAC;AAC9B,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import type { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
2
2
  import type { DataPlaneResolver } from '../tenancy/types.js';
3
3
  import type { AuditService } from '../types/audit.js';
4
+ import type { LoggerService } from '../types/context.js';
4
5
  import type { PlumbusMetrics } from '../observability/metrics.js';
5
6
  import type { EventQueue } from './queue.js';
6
7
  export interface DispatcherConfig {
@@ -18,6 +19,14 @@ export interface DispatcherConfig {
18
19
  backoffBaseMs?: number;
19
20
  /** Max backoff delay in ms (default: 60000) */
20
21
  backoffMaxMs?: number;
22
+ /**
23
+ * How long a claimed (`processing`) row may stay unpublished before a later
24
+ * poll returns it to `pending` (default: 300000). Covers a dispatcher that
25
+ * stopped between claim and publish.
26
+ */
27
+ claimTimeoutMs?: number;
28
+ /** Receives audit write and poll failures (default: console) */
29
+ logger?: LoggerService;
21
30
  /**
22
31
  * When set with `listTenantRefs`, each poll resolves those tenants and
23
32
  * drains `event_outbox` (and `dispatch_outbox` when `spineDb` is set) on
@@ -32,6 +41,17 @@ export interface DispatcherConfig {
32
41
  * the dispatcher only drains `event_outbox` (historical behavior).
33
42
  */
34
43
  spineDb?: PostgresJsDatabase;
44
+ /**
45
+ * The schema every plane's durable `dispatch_outbox` lives in — the same one the flow
46
+ * engine writes it under (`spineDispatch.coreSchema`, else `PLUMBUS_FRAMEWORK_SCHEMA`,
47
+ * else the framework default). Defaults the same way, so a host that configures nothing
48
+ * reads where it wrote. This is deliberately *not* the plane handle's `coreSchema`: that
49
+ * names the tenant's own entity tables, which a host may keep in `public` while the
50
+ * durable tables sit in the framework schema — reading `dispatch_outbox` from the
51
+ * handle's schema answered `relation "dispatch_outbox" does not exist` for every tenant
52
+ * on every poll.
53
+ */
54
+ frameworkSchema?: string;
35
55
  }
36
56
  /**
37
57
  * Creates a dispatcher that polls the outbox table for pending events,
@@ -1 +1 @@
1
- {"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/events/dispatcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,kBAAkB,CAAC;IACvB,KAAK,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,oDAAoD;IACpD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,QAAQ,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IACpE;;;OAGG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAC;CAC9B;AAQD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB;IAmN3D,mDAAmD;gBAlB9B,OAAO,CAAC,MAAM,CAAC;IAqBpC,wCAAwC;aAC/B,IAAI;IASb,uCAAuC;YAC/B,IAAI;wBAQK,OAAO;EAI3B"}
1
+ {"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/events/dispatcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,kBAAkB,CAAC;IACvB,KAAK,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,oDAAoD;IACpD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gEAAgE;IAChE,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,QAAQ,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IACpE;;;OAGG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;;;;;;;;OASG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAOD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB;IA+P3D,mDAAmD;gBAzC9B,OAAO,CAAC,MAAM,CAAC;IA4CpC,wCAAwC;aAC/B,IAAI;IAOb,uCAAuC;YAC/B,IAAI;wBAQK,OAAO;EAI3B"}
@@ -1,5 +1,7 @@
1
- import { and, eq } from 'drizzle-orm';
1
+ import { and, eq, lt } from 'drizzle-orm';
2
+ import { FRAMEWORK_SCHEMA, resolveFrameworkSchema } from '../data/schema-generator.js';
2
3
  import { deadLetterTable, outboxTable } from './outbox.js';
4
+ import { recordPipelineAudit } from './pipeline-audit.js';
3
5
  /**
4
6
  * Creates a dispatcher that polls the outbox table for pending events,
5
7
  * publishes them to the queue, and marks them as dispatched.
@@ -10,7 +12,7 @@ import { deadLetterTable, outboxTable } from './outbox.js';
10
12
  * when `spineDb` is set — not a second bus.
11
13
  */
12
14
  export function createOutboxDispatcher(config) {
13
- const { db, queue, pollIntervalMs = 1000, batchSize = 100, maxRetries = 5, backoffBaseMs = 1000, backoffMaxMs = 60_000, metrics, audit, resolver, listTenantRefs, spineDb, } = config;
15
+ const { db, queue, pollIntervalMs = 1000, batchSize = 100, maxRetries = 5, backoffBaseMs = 1000, backoffMaxMs = 60_000, claimTimeoutMs = 300_000, metrics, audit, logger, resolver, listTenantRefs, spineDb, } = config;
14
16
  let timer = null;
15
17
  let running = false;
16
18
  let polling = false;
@@ -18,24 +20,34 @@ export function createOutboxDispatcher(config) {
18
20
  function computeBackoff(attempt) {
19
21
  return Math.min(backoffBaseMs * 2 ** attempt, backoffMaxMs);
20
22
  }
23
+ /** Logger messages are sentence case; the console fallback keeps the `[plumbus]` prefix. */
24
+ function logError(message, details) {
25
+ if (logger)
26
+ logger.error(message, details);
27
+ else
28
+ console.error(`[plumbus] ${message.charAt(0).toLowerCase()}${message.slice(1)}`, details);
29
+ }
30
+ // Where `dispatch_outbox` is, on every plane: the engine's own resolution, mirrored.
31
+ const durableSchema = config.frameworkSchema ?? resolveFrameworkSchema() ?? FRAMEWORK_SCHEMA;
21
32
  async function resolveTargets() {
22
33
  if (!resolver || !listTenantRefs) {
23
- return [{ db, tenantRef: 'default', coreSchema: 'public' }];
34
+ return [{ db, tenantRef: 'default' }];
24
35
  }
25
36
  const refs = [...(await listTenantRefs())];
26
37
  const targets = [];
27
38
  for (const tenantRef of refs) {
28
39
  const handle = await resolver.resolve(tenantRef);
29
- targets.push({
30
- db: handle.db,
31
- tenantRef: handle.tenantRef,
32
- coreSchema: handle.coreSchema,
33
- });
40
+ targets.push({ db: handle.db, tenantRef: handle.tenantRef });
34
41
  }
35
42
  return targets;
36
43
  }
37
44
  async function pollEventOutbox(targetDb) {
38
45
  const now = new Date();
46
+ // Release claims whose dispatcher stopped before publishing
47
+ await targetDb
48
+ .update(outboxTable)
49
+ .set({ status: 'pending' })
50
+ .where(and(eq(outboxTable.status, 'processing'), lt(outboxTable.dispatchedAt, new Date(now.getTime() - claimTimeoutMs))));
39
51
  const rows = await targetDb
40
52
  .select()
41
53
  .from(outboxTable)
@@ -84,13 +96,13 @@ export function createOutboxDispatcher(config) {
84
96
  causationId: row.causationId ?? undefined,
85
97
  payload: row.payload,
86
98
  };
99
+ // No outcome yet: audit outcomes are `success | failure | denied`
100
+ await recordPipelineAudit(audit, logger, 'event.dispatch.attempt', {
101
+ eventId: row.id,
102
+ eventType: row.eventType,
103
+ tenantId: row.tenantId,
104
+ });
87
105
  try {
88
- await audit?.record('event.dispatch.attempt', {
89
- eventId: row.id,
90
- eventType: row.eventType,
91
- tenantId: row.tenantId,
92
- outcome: 'pending',
93
- });
94
106
  await queue.publish(envelope);
95
107
  await targetDb
96
108
  .update(outboxTable)
@@ -98,7 +110,7 @@ export function createOutboxDispatcher(config) {
98
110
  .where(eq(outboxTable.id, row.id));
99
111
  dispatched++;
100
112
  metrics?.eventEmitted.inc({ eventType: row.eventType });
101
- await audit?.record('event.dispatch.dispatched', {
113
+ await recordPipelineAudit(audit, logger, 'event.dispatch.dispatched', {
102
114
  eventId: row.id,
103
115
  eventType: row.eventType,
104
116
  tenantId: row.tenantId,
@@ -108,13 +120,14 @@ export function createOutboxDispatcher(config) {
108
120
  catch (err) {
109
121
  const retryCount = parseInt(row.retryCount, 10) + 1;
110
122
  const errorMsg = err instanceof Error ? err.message : String(err);
111
- await audit?.record('event.dispatch.failed', {
123
+ await recordPipelineAudit(audit, logger, 'event.dispatch.failed', {
112
124
  eventId: row.id,
113
125
  eventType: row.eventType,
114
126
  tenantId: row.tenantId,
115
127
  retryCount,
116
128
  error: errorMsg,
117
- outcome: retryCount >= maxRetries ? 'dead_lettered' : 'retry',
129
+ outcome: 'failure',
130
+ disposition: retryCount >= maxRetries ? 'dead_lettered' : 'retry',
118
131
  });
119
132
  if (retryCount >= maxRetries) {
120
133
  await targetDb.insert(deadLetterTable).values({
@@ -155,16 +168,16 @@ export function createOutboxDispatcher(config) {
155
168
  if (!spineDb)
156
169
  return 0;
157
170
  const { listUnpublishedOutbox, publishOutboxToSpine } = await import('../durable/postgres-persist.js');
158
- const unpublished = await listUnpublishedOutbox(target.db, target.coreSchema);
171
+ const unpublished = await listUnpublishedOutbox(target.db, durableSchema);
159
172
  let published = 0;
160
173
  for (const row of unpublished) {
161
174
  try {
162
175
  const dispatchId = row.spineRowId ?? `disp:${row.executionId}:${row.expectedRevision}`;
163
- await publishOutboxToSpine(target.db, spineDb, row, dispatchId, new Date().toISOString(), target.coreSchema);
176
+ await publishOutboxToSpine(target.db, spineDb, row, dispatchId, new Date().toISOString(), durableSchema);
164
177
  published += 1;
165
178
  }
166
179
  catch (err) {
167
- console.error('[plumbus] dispatch_outbox pump failed', {
180
+ logError('dispatch_outbox pump failed', {
168
181
  tenantRef: target.tenantRef,
169
182
  outboxId: row.outboxId,
170
183
  error: err instanceof Error ? err.message : String(err),
@@ -181,15 +194,39 @@ export function createOutboxDispatcher(config) {
181
194
  const targets = await resolveTargets();
182
195
  let dispatched = 0;
183
196
  for (const target of targets) {
184
- dispatched += await pollEventOutbox(target.db);
185
- dispatched += await pumpDispatchOutbox(target);
197
+ // One plane's failure must neither stop the others nor escape the timer: an
198
+ // unhandled rejection here would take the worker process down.
199
+ try {
200
+ dispatched += await pollEventOutbox(target.db);
201
+ dispatched += await pumpDispatchOutbox(target);
202
+ }
203
+ catch (err) {
204
+ logError('Outbox poll failed for one plane', {
205
+ tenantRef: target.tenantRef,
206
+ error: err instanceof Error ? err.message : String(err),
207
+ });
208
+ }
186
209
  }
187
210
  return dispatched;
188
211
  }
212
+ catch (err) {
213
+ logError('Outbox poll could not resolve its planes', {
214
+ error: err instanceof Error ? err.message : String(err),
215
+ });
216
+ return 0;
217
+ }
189
218
  finally {
190
219
  polling = false;
191
220
  }
192
221
  }
222
+ /** Timer-driven poll; a failed cycle is logged and the next tick retries */
223
+ function tick() {
224
+ poll().catch((err) => {
225
+ logError('Outbox poll failed', {
226
+ error: err instanceof Error ? err.message : String(err),
227
+ });
228
+ });
229
+ }
193
230
  return {
194
231
  /** Run a single poll cycle (useful for testing) */
195
232
  poll,
@@ -198,10 +235,8 @@ export function createOutboxDispatcher(config) {
198
235
  if (running)
199
236
  return;
200
237
  running = true;
201
- timer = setInterval(() => {
202
- void poll();
203
- }, pollIntervalMs);
204
- void poll();
238
+ timer = setInterval(tick, pollIntervalMs);
239
+ tick();
205
240
  },
206
241
  /** Stop the background polling loop */
207
242
  stop() {