bunqueue 2.8.59 → 2.9.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 (380) hide show
  1. package/README.md +109 -77
  2. package/dist/application/background/dlq.js +2 -0
  3. package/dist/application/contextFactory.js +5 -0
  4. package/dist/application/dlqManager.d.ts +11 -1
  5. package/dist/application/dlqManager.js +48 -10
  6. package/dist/application/dlqRetry.js +59 -38
  7. package/dist/application/eventsManager.d.ts +1 -1
  8. package/dist/application/eventsManager.js +30 -26
  9. package/dist/application/lockManager.js +1 -1
  10. package/dist/application/operations/jobManagement.d.ts +4 -0
  11. package/dist/application/operations/jobMoveOperations.js +9 -4
  12. package/dist/application/postgres-queue-manager/batchSnapshot.d.ts +16 -0
  13. package/dist/application/postgres-queue-manager/batchSnapshot.js +17 -0
  14. package/dist/application/postgres-queue-manager/cloud.d.ts +30 -0
  15. package/dist/application/postgres-queue-manager/cloud.js +55 -0
  16. package/dist/application/postgres-queue-manager/config.d.ts +5 -0
  17. package/dist/application/postgres-queue-manager/config.js +1 -0
  18. package/dist/application/postgres-queue-manager/control.d.ts +26 -0
  19. package/dist/application/postgres-queue-manager/control.js +186 -0
  20. package/dist/application/postgres-queue-manager/deferredWrites.d.ts +13 -0
  21. package/dist/application/postgres-queue-manager/deferredWrites.js +60 -0
  22. package/dist/application/postgres-queue-manager/delivery.d.ts +19 -0
  23. package/dist/application/postgres-queue-manager/delivery.js +80 -0
  24. package/dist/application/postgres-queue-manager/lease.d.ts +13 -0
  25. package/dist/application/postgres-queue-manager/lease.js +88 -0
  26. package/dist/application/postgres-queue-manager/lifetimeMetrics.d.ts +32 -0
  27. package/dist/application/postgres-queue-manager/lifetimeMetrics.js +53 -0
  28. package/dist/application/postgres-queue-manager/maintenance.d.ts +14 -0
  29. package/dist/application/postgres-queue-manager/maintenance.js +100 -0
  30. package/dist/application/postgres-queue-manager/operationGate.d.ts +26 -0
  31. package/dist/application/postgres-queue-manager/operationGate.js +96 -0
  32. package/dist/application/postgres-queue-manager/operations.d.ts +25 -0
  33. package/dist/application/postgres-queue-manager/operations.js +194 -0
  34. package/dist/application/postgres-queue-manager/projectionRefreshes.d.ts +43 -0
  35. package/dist/application/postgres-queue-manager/projectionRefreshes.js +170 -0
  36. package/dist/application/postgres-queue-manager/queries.d.ts +142 -0
  37. package/dist/application/postgres-queue-manager/queries.js +231 -0
  38. package/dist/application/postgres-queue-manager/relationships.d.ts +10 -0
  39. package/dist/application/postgres-queue-manager/relationships.js +45 -0
  40. package/dist/application/postgres-queue-manager/services.d.ts +31 -0
  41. package/dist/application/postgres-queue-manager/services.js +149 -0
  42. package/dist/application/postgres-queue-manager/snapshot.d.ts +51 -0
  43. package/dist/application/postgres-queue-manager/snapshot.js +236 -0
  44. package/dist/application/postgres-queue-manager/snapshotViews.d.ts +15 -0
  45. package/dist/application/postgres-queue-manager/snapshotViews.js +100 -0
  46. package/dist/application/postgres-queue-manager/startupEventBuffer.d.ts +12 -0
  47. package/dist/application/postgres-queue-manager/startupEventBuffer.js +36 -0
  48. package/dist/application/postgres-queue-manager/state.d.ts +47 -0
  49. package/dist/application/postgres-queue-manager/state.js +273 -0
  50. package/dist/application/postgres-queue-manager/terminalDelivery.d.ts +20 -0
  51. package/dist/application/postgres-queue-manager/terminalDelivery.js +100 -0
  52. package/dist/application/postgresQueueManager.d.ts +2 -0
  53. package/dist/application/postgresQueueManager.js +1 -0
  54. package/dist/application/queue-manager/ack.js +1 -1
  55. package/dist/application/queue-manager/delivery.js +1 -1
  56. package/dist/application/queue-manager/flow-failures.js +4 -0
  57. package/dist/application/queue-manager/limits.d.ts +2 -0
  58. package/dist/application/queue-manager/limits.js +4 -0
  59. package/dist/application/queue-manager/observability.js +15 -3
  60. package/dist/application/queue-manager/queries.d.ts +7 -0
  61. package/dist/application/queue-manager/queries.js +9 -0
  62. package/dist/application/queue-manager/services.d.ts +1 -1
  63. package/dist/application/queue-manager/services.js +4 -2
  64. package/dist/application/queue-manager/state.js +16 -1
  65. package/dist/application/statsManager.d.ts +1 -1
  66. package/dist/application/statsManager.js +1 -1
  67. package/dist/cli/commands/server.js +1 -1
  68. package/dist/client/events.js +2 -2
  69. package/dist/client/flow.js +0 -1
  70. package/dist/client/forwarder.d.ts +6 -4
  71. package/dist/client/forwarder.js +5 -3
  72. package/dist/client/queue/dlq.d.ts +2 -0
  73. package/dist/client/queue/dlq.js +14 -0
  74. package/dist/client/queue/dlqOps.d.ts +2 -0
  75. package/dist/client/queue/dlqOps.js +4 -0
  76. package/dist/client/queue/helpers.js +2 -0
  77. package/dist/client/queue/operations/add/single.js +1 -1
  78. package/dist/client/queue/runtime/configuration.d.ts +4 -0
  79. package/dist/client/queue/runtime/configuration.js +8 -0
  80. package/dist/client/sandboxed/runtime/state.js +2 -2
  81. package/dist/client/tcp/connection.d.ts +1 -1
  82. package/dist/client/tcp/connection.js +1 -1
  83. package/dist/client/tcp/runtime/state.js +2 -2
  84. package/dist/client/types/metrics.d.ts +1 -1
  85. package/dist/client/worker/runtime/control.js +0 -1
  86. package/dist/client/worker/runtime/execution.js +3 -8
  87. package/dist/client/worker/runtime/lifecycle.js +0 -1
  88. package/dist/client/worker/runtime/polling.d.ts +1 -0
  89. package/dist/client/worker/runtime/polling.js +9 -0
  90. package/dist/client/worker/runtime/state.js +3 -3
  91. package/dist/client/workflow/compensationChild.d.ts +2 -0
  92. package/dist/client/workflow/compensationChild.js +3 -1
  93. package/dist/client/workflow/compensationPass.d.ts +1 -0
  94. package/dist/client/workflow/compensationPass.js +18 -2
  95. package/dist/client/workflow/compensator.d.ts +2 -1
  96. package/dist/client/workflow/compensator.js +11 -3
  97. package/dist/client/workflow/engine.js +1 -1
  98. package/dist/client/workflow/executionFence.d.ts +15 -0
  99. package/dist/client/workflow/executionFence.js +29 -0
  100. package/dist/client/workflow/executor.d.ts +5 -11
  101. package/dist/client/workflow/executor.js +48 -47
  102. package/dist/client/workflow/executorLifecycle.d.ts +1 -0
  103. package/dist/client/workflow/executorLifecycle.js +41 -10
  104. package/dist/client/workflow/executorNodes.d.ts +1 -0
  105. package/dist/client/workflow/executorNodes.js +45 -16
  106. package/dist/client/workflow/executorQueue.d.ts +9 -0
  107. package/dist/client/workflow/executorQueue.js +15 -0
  108. package/dist/client/workflow/forEachRunner.d.ts +4 -0
  109. package/dist/client/workflow/forEachRunner.js +70 -0
  110. package/dist/client/workflow/loops.d.ts +4 -5
  111. package/dist/client/workflow/loops.js +27 -93
  112. package/dist/client/workflow/mapRunner.d.ts +1 -1
  113. package/dist/client/workflow/mapRunner.js +11 -2
  114. package/dist/client/workflow/recovery.d.ts +1 -0
  115. package/dist/client/workflow/recovery.js +24 -18
  116. package/dist/client/workflow/rollbackControl.d.ts +1 -0
  117. package/dist/client/workflow/rollbackControl.js +5 -2
  118. package/dist/client/workflow/runner.d.ts +3 -1
  119. package/dist/client/workflow/runner.js +26 -3
  120. package/dist/client/workflow/stepTypes.js +1 -1
  121. package/dist/client/workflow/subWorkflowRunner.d.ts +1 -0
  122. package/dist/client/workflow/subWorkflowRunner.js +7 -0
  123. package/dist/client/workflow/waitFor.d.ts +4 -0
  124. package/dist/client/workflow/waitFor.js +23 -11
  125. package/dist/client/workflow/workflowDecisions.d.ts +1 -1
  126. package/dist/client/workflow/workflowDecisions.js +3 -1
  127. package/dist/config/resolve.d.ts +14 -0
  128. package/dist/config/resolve.js +50 -5
  129. package/dist/config/types.d.ts +18 -0
  130. package/dist/domain/queue/dlqShard.d.ts +2 -0
  131. package/dist/domain/queue/dlqShard.js +16 -0
  132. package/dist/domain/queue/shard/dlq.d.ts +1 -0
  133. package/dist/domain/queue/shard/dlq.js +3 -0
  134. package/dist/domain/types/commands/dlq.d.ts +5 -0
  135. package/dist/domain/types/commands/union.d.ts +1 -1
  136. package/dist/domain/types/cron.d.ts +5 -0
  137. package/dist/domain/types/cron.js +14 -3
  138. package/dist/domain/types/dlq.d.ts +1 -1
  139. package/dist/domain/types/dlq.js +1 -2
  140. package/dist/domain/types/jobs/model.d.ts +1 -1
  141. package/dist/infrastructure/cloud/commandHandler.js +5 -3
  142. package/dist/infrastructure/cloud/commands/integrations.js +11 -11
  143. package/dist/infrastructure/cloud/commands/jobs.js +48 -40
  144. package/dist/infrastructure/cloud/commands/queues.js +61 -75
  145. package/dist/infrastructure/cloud/queueAdapter/local.d.ts +41 -0
  146. package/dist/infrastructure/cloud/queueAdapter/local.js +187 -0
  147. package/dist/infrastructure/cloud/queueAdapter/postgres.d.ts +42 -0
  148. package/dist/infrastructure/cloud/queueAdapter/postgres.js +188 -0
  149. package/dist/infrastructure/cloud/queueAdapter/registry.d.ts +4 -0
  150. package/dist/infrastructure/cloud/queueAdapter/registry.js +15 -0
  151. package/dist/infrastructure/cloud/queueAdapter/types.d.ts +87 -0
  152. package/dist/infrastructure/cloud/queueAdapter/types.js +1 -0
  153. package/dist/infrastructure/cloud/snapshot/analytics.d.ts +2 -0
  154. package/dist/infrastructure/cloud/snapshot/analytics.js +7 -0
  155. package/dist/infrastructure/cloud/snapshot/collector.d.ts +4 -0
  156. package/dist/infrastructure/cloud/snapshot/collector.js +39 -1
  157. package/dist/infrastructure/cloud/snapshot/config.d.ts +3 -0
  158. package/dist/infrastructure/cloud/snapshot/config.js +43 -0
  159. package/dist/infrastructure/cloud/snapshot/jobs.d.ts +3 -0
  160. package/dist/infrastructure/cloud/snapshot/jobs.js +32 -1
  161. package/dist/infrastructure/cloud/snapshotCollector.js +20 -35
  162. package/dist/infrastructure/cloud/snapshotHelpers.d.ts +3 -3
  163. package/dist/infrastructure/cloud/snapshotHelpers.js +3 -3
  164. package/dist/infrastructure/cloud/statsRefresh.js +2 -1
  165. package/dist/infrastructure/cloud/types/command.d.ts +2 -2
  166. package/dist/infrastructure/persistence/postgres/admission.d.ts +18 -0
  167. package/dist/infrastructure/persistence/postgres/admission.js +193 -0
  168. package/dist/infrastructure/persistence/postgres/admissionParent.d.ts +5 -0
  169. package/dist/infrastructure/persistence/postgres/admissionParent.js +35 -0
  170. package/dist/infrastructure/persistence/postgres/admissionResult.d.ts +9 -0
  171. package/dist/infrastructure/persistence/postgres/admissionResult.js +1 -0
  172. package/dist/infrastructure/persistence/postgres/admissionStore.d.ts +12 -0
  173. package/dist/infrastructure/persistence/postgres/admissionStore.js +101 -0
  174. package/dist/infrastructure/persistence/postgres/advisoryLocks.d.ts +2 -0
  175. package/dist/infrastructure/persistence/postgres/advisoryLocks.js +13 -0
  176. package/dist/infrastructure/persistence/postgres/batchAdmission.d.ts +11 -0
  177. package/dist/infrastructure/persistence/postgres/batchAdmission.js +110 -0
  178. package/dist/infrastructure/persistence/postgres/batchCompletion.d.ts +4 -0
  179. package/dist/infrastructure/persistence/postgres/batchCompletion.js +174 -0
  180. package/dist/infrastructure/persistence/postgres/batchEvents.d.ts +14 -0
  181. package/dist/infrastructure/persistence/postgres/batchEvents.js +72 -0
  182. package/dist/infrastructure/persistence/postgres/brokerSessions.d.ts +14 -0
  183. package/dist/infrastructure/persistence/postgres/brokerSessions.js +94 -0
  184. package/dist/infrastructure/persistence/postgres/claimBatch.d.ts +11 -0
  185. package/dist/infrastructure/persistence/postgres/claimBatch.js +56 -0
  186. package/dist/infrastructure/persistence/postgres/claimSelection.d.ts +4 -0
  187. package/dist/infrastructure/persistence/postgres/claimSelection.js +198 -0
  188. package/dist/infrastructure/persistence/postgres/claims.d.ts +3 -0
  189. package/dist/infrastructure/persistence/postgres/claims.js +137 -0
  190. package/dist/infrastructure/persistence/postgres/cloudReadModel.d.ts +26 -0
  191. package/dist/infrastructure/persistence/postgres/cloudReadModel.js +123 -0
  192. package/dist/infrastructure/persistence/postgres/codec.d.ts +30 -0
  193. package/dist/infrastructure/persistence/postgres/codec.js +82 -0
  194. package/dist/infrastructure/persistence/postgres/completionEvents.d.ts +11 -0
  195. package/dist/infrastructure/persistence/postgres/completionEvents.js +21 -0
  196. package/dist/infrastructure/persistence/postgres/completionLifecycle.d.ts +11 -0
  197. package/dist/infrastructure/persistence/postgres/completionLifecycle.js +145 -0
  198. package/dist/infrastructure/persistence/postgres/completionOutcome.d.ts +4 -0
  199. package/dist/infrastructure/persistence/postgres/completionOutcome.js +112 -0
  200. package/dist/infrastructure/persistence/postgres/completionQueries.d.ts +10 -0
  201. package/dist/infrastructure/persistence/postgres/completionQueries.js +87 -0
  202. package/dist/infrastructure/persistence/postgres/connection.d.ts +3 -0
  203. package/dist/infrastructure/persistence/postgres/connection.js +15 -0
  204. package/dist/infrastructure/persistence/postgres/context.d.ts +28 -0
  205. package/dist/infrastructure/persistence/postgres/context.js +74 -0
  206. package/dist/infrastructure/persistence/postgres/control.d.ts +23 -0
  207. package/dist/infrastructure/persistence/postgres/control.js +105 -0
  208. package/dist/infrastructure/persistence/postgres/crons.d.ts +18 -0
  209. package/dist/infrastructure/persistence/postgres/crons.js +205 -0
  210. package/dist/infrastructure/persistence/postgres/deduplication.d.ts +9 -0
  211. package/dist/infrastructure/persistence/postgres/deduplication.js +47 -0
  212. package/dist/infrastructure/persistence/postgres/dependencyDestruction.d.ts +14 -0
  213. package/dist/infrastructure/persistence/postgres/dependencyDestruction.js +74 -0
  214. package/dist/infrastructure/persistence/postgres/dependencyPromotion.d.ts +29 -0
  215. package/dist/infrastructure/persistence/postgres/dependencyPromotion.js +212 -0
  216. package/dist/infrastructure/persistence/postgres/destructiveMutations.d.ts +4 -0
  217. package/dist/infrastructure/persistence/postgres/destructiveMutations.js +111 -0
  218. package/dist/infrastructure/persistence/postgres/dlqLifecycle.d.ts +13 -0
  219. package/dist/infrastructure/persistence/postgres/dlqLifecycle.js +184 -0
  220. package/dist/infrastructure/persistence/postgres/dlqMaintenance.d.ts +6 -0
  221. package/dist/infrastructure/persistence/postgres/dlqMaintenance.js +36 -0
  222. package/dist/infrastructure/persistence/postgres/dlqRetryPlan.d.ts +21 -0
  223. package/dist/infrastructure/persistence/postgres/dlqRetryPlan.js +92 -0
  224. package/dist/infrastructure/persistence/postgres/eventCommitGc.d.ts +27 -0
  225. package/dist/infrastructure/persistence/postgres/eventCommitGc.js +62 -0
  226. package/dist/infrastructure/persistence/postgres/eventJournal.d.ts +18 -0
  227. package/dist/infrastructure/persistence/postgres/eventJournal.js +76 -0
  228. package/dist/infrastructure/persistence/postgres/eventJournalSchema.d.ts +5 -0
  229. package/dist/infrastructure/persistence/postgres/eventJournalSchema.js +253 -0
  230. package/dist/infrastructure/persistence/postgres/eventPruneWatermarks.d.ts +24 -0
  231. package/dist/infrastructure/persistence/postgres/eventPruneWatermarks.js +111 -0
  232. package/dist/infrastructure/persistence/postgres/eventRetention.d.ts +18 -0
  233. package/dist/infrastructure/persistence/postgres/eventRetention.js +76 -0
  234. package/dist/infrastructure/persistence/postgres/events.d.ts +45 -0
  235. package/dist/infrastructure/persistence/postgres/events.js +249 -0
  236. package/dist/infrastructure/persistence/postgres/expiry.d.ts +3 -0
  237. package/dist/infrastructure/persistence/postgres/expiry.js +74 -0
  238. package/dist/infrastructure/persistence/postgres/flowFailures.d.ts +17 -0
  239. package/dist/infrastructure/persistence/postgres/flowFailures.js +199 -0
  240. package/dist/infrastructure/persistence/postgres/jobData.d.ts +3 -0
  241. package/dist/infrastructure/persistence/postgres/jobData.js +32 -0
  242. package/dist/infrastructure/persistence/postgres/leaseRelease.d.ts +9 -0
  243. package/dist/infrastructure/persistence/postgres/leaseRelease.js +120 -0
  244. package/dist/infrastructure/persistence/postgres/leaseRenewal.d.ts +4 -0
  245. package/dist/infrastructure/persistence/postgres/leaseRenewal.js +35 -0
  246. package/dist/infrastructure/persistence/postgres/lifetimeMetrics.d.ts +15 -0
  247. package/dist/infrastructure/persistence/postgres/lifetimeMetrics.js +46 -0
  248. package/dist/infrastructure/persistence/postgres/lifetimeMetricsFinalizer.d.ts +4 -0
  249. package/dist/infrastructure/persistence/postgres/lifetimeMetricsFinalizer.js +13 -0
  250. package/dist/infrastructure/persistence/postgres/logs.d.ts +6 -0
  251. package/dist/infrastructure/persistence/postgres/logs.js +70 -0
  252. package/dist/infrastructure/persistence/postgres/maintenance.d.ts +6 -0
  253. package/dist/infrastructure/persistence/postgres/maintenance.js +138 -0
  254. package/dist/infrastructure/persistence/postgres/maintenanceFlights.d.ts +14 -0
  255. package/dist/infrastructure/persistence/postgres/maintenanceFlights.js +66 -0
  256. package/dist/infrastructure/persistence/postgres/metricWrites.d.ts +9 -0
  257. package/dist/infrastructure/persistence/postgres/metricWrites.js +94 -0
  258. package/dist/infrastructure/persistence/postgres/mutations.d.ts +9 -0
  259. package/dist/infrastructure/persistence/postgres/mutations.js +171 -0
  260. package/dist/infrastructure/persistence/postgres/outcomes.d.ts +4 -0
  261. package/dist/infrastructure/persistence/postgres/outcomes.js +194 -0
  262. package/dist/infrastructure/persistence/postgres/policies.d.ts +11 -0
  263. package/dist/infrastructure/persistence/postgres/policies.js +18 -0
  264. package/dist/infrastructure/persistence/postgres/postCommitMaintenance.d.ts +17 -0
  265. package/dist/infrastructure/persistence/postgres/postCommitMaintenance.js +117 -0
  266. package/dist/infrastructure/persistence/postgres/promotion.d.ts +3 -0
  267. package/dist/infrastructure/persistence/postgres/promotion.js +43 -0
  268. package/dist/infrastructure/persistence/postgres/queries.d.ts +22 -0
  269. package/dist/infrastructure/persistence/postgres/queries.js +152 -0
  270. package/dist/infrastructure/persistence/postgres/queueDestruction.d.ts +3 -0
  271. package/dist/infrastructure/persistence/postgres/queueDestruction.js +154 -0
  272. package/dist/infrastructure/persistence/postgres/queueLifecycle.d.ts +10 -0
  273. package/dist/infrastructure/persistence/postgres/queueLifecycle.js +60 -0
  274. package/dist/infrastructure/persistence/postgres/rateLimit.d.ts +6 -0
  275. package/dist/infrastructure/persistence/postgres/rateLimit.js +10 -0
  276. package/dist/infrastructure/persistence/postgres/readModels.d.ts +32 -0
  277. package/dist/infrastructure/persistence/postgres/readModels.js +72 -0
  278. package/dist/infrastructure/persistence/postgres/recovery.d.ts +3 -0
  279. package/dist/infrastructure/persistence/postgres/recovery.js +178 -0
  280. package/dist/infrastructure/persistence/postgres/relationships.d.ts +9 -0
  281. package/dist/infrastructure/persistence/postgres/relationships.js +201 -0
  282. package/dist/infrastructure/persistence/postgres/removeUnprocessedChildren.d.ts +4 -0
  283. package/dist/infrastructure/persistence/postgres/removeUnprocessedChildren.js +241 -0
  284. package/dist/infrastructure/persistence/postgres/repeatMutations.d.ts +5 -0
  285. package/dist/infrastructure/persistence/postgres/repeatMutations.js +37 -0
  286. package/dist/infrastructure/persistence/postgres/runtime.d.ts +46 -0
  287. package/dist/infrastructure/persistence/postgres/runtime.js +236 -0
  288. package/dist/infrastructure/persistence/postgres/runtimeConfig.d.ts +21 -0
  289. package/dist/infrastructure/persistence/postgres/runtimeConfig.js +39 -0
  290. package/dist/infrastructure/persistence/postgres/schema.d.ts +4 -0
  291. package/dist/infrastructure/persistence/postgres/schema.js +257 -0
  292. package/dist/infrastructure/persistence/postgres/schemaInitialization.d.ts +3 -0
  293. package/dist/infrastructure/persistence/postgres/schemaInitialization.js +221 -0
  294. package/dist/infrastructure/persistence/postgres/serialAdmission.d.ts +6 -0
  295. package/dist/infrastructure/persistence/postgres/serialAdmission.js +96 -0
  296. package/dist/infrastructure/persistence/postgres/snapshotBudget.d.ts +3 -0
  297. package/dist/infrastructure/persistence/postgres/snapshotBudget.js +83 -0
  298. package/dist/infrastructure/persistence/postgres/storageHealth.d.ts +10 -0
  299. package/dist/infrastructure/persistence/postgres/storageHealth.js +29 -0
  300. package/dist/infrastructure/persistence/postgres/store.d.ts +90 -0
  301. package/dist/infrastructure/persistence/postgres/store.js +136 -0
  302. package/dist/infrastructure/persistence/postgres/telemetry.d.ts +6 -0
  303. package/dist/infrastructure/persistence/postgres/telemetry.js +88 -0
  304. package/dist/infrastructure/persistence/postgres/terminal.d.ts +8 -0
  305. package/dist/infrastructure/persistence/postgres/terminal.js +137 -0
  306. package/dist/infrastructure/persistence/postgres/transactionRetry.d.ts +6 -0
  307. package/dist/infrastructure/persistence/postgres/transactionRetry.js +42 -0
  308. package/dist/infrastructure/persistence/postgres/types.d.ts +175 -0
  309. package/dist/infrastructure/persistence/postgres/types.js +1 -0
  310. package/dist/infrastructure/persistence/postgres/workers.d.ts +15 -0
  311. package/dist/infrastructure/persistence/postgres/workers.js +126 -0
  312. package/dist/infrastructure/persistence/postgres.d.ts +2 -0
  313. package/dist/infrastructure/persistence/postgres.js +1 -0
  314. package/dist/infrastructure/persistence/sqlite/jobs.js +2 -0
  315. package/dist/infrastructure/persistence/sqlite.d.ts +1 -1
  316. package/dist/infrastructure/scheduler/cron/persisted.d.ts +5 -0
  317. package/dist/infrastructure/scheduler/cron/persisted.js +27 -0
  318. package/dist/infrastructure/scheduler/cron/runtime.js +5 -10
  319. package/dist/infrastructure/scheduler/cron/validation.d.ts +3 -0
  320. package/dist/infrastructure/scheduler/cron/validation.js +11 -0
  321. package/dist/infrastructure/scheduler/cronParser.d.ts +1 -1
  322. package/dist/infrastructure/scheduler/cronParser.js +144 -11
  323. package/dist/infrastructure/server/bootstrap.d.ts +2 -3
  324. package/dist/infrastructure/server/bootstrap.js +33 -59
  325. package/dist/infrastructure/server/errors.d.ts +4 -0
  326. package/dist/infrastructure/server/errors.js +54 -0
  327. package/dist/infrastructure/server/handler-routes/control.d.ts +5 -5
  328. package/dist/infrastructure/server/handler-routes/control.js +3 -1
  329. package/dist/infrastructure/server/handler-routes/jobs.js +0 -3
  330. package/dist/infrastructure/server/handler-routes/monitoring.d.ts +2 -2
  331. package/dist/infrastructure/server/handler.js +9 -11
  332. package/dist/infrastructure/server/handlerRoutes.d.ts +2 -2
  333. package/dist/infrastructure/server/handlerRoutes.js +2 -2
  334. package/dist/infrastructure/server/handlers/advanced/dependencies.js +7 -6
  335. package/dist/infrastructure/server/handlers/advanced/jobs.js +19 -6
  336. package/dist/infrastructure/server/handlers/advanced/queue.d.ts +9 -9
  337. package/dist/infrastructure/server/handlers/advanced/queue.js +91 -27
  338. package/dist/infrastructure/server/handlers/core.js +32 -31
  339. package/dist/infrastructure/server/handlers/cron.d.ts +4 -4
  340. package/dist/infrastructure/server/handlers/cron.js +60 -59
  341. package/dist/infrastructure/server/handlers/dashboard.d.ts +1 -1
  342. package/dist/infrastructure/server/handlers/dashboard.js +21 -8
  343. package/dist/infrastructure/server/handlers/dlq.d.ts +6 -3
  344. package/dist/infrastructure/server/handlers/dlq.js +35 -9
  345. package/dist/infrastructure/server/handlers/flow.js +2 -1
  346. package/dist/infrastructure/server/handlers/management.d.ts +5 -5
  347. package/dist/infrastructure/server/handlers/management.js +36 -9
  348. package/dist/infrastructure/server/handlers/monitoring/health.d.ts +5 -5
  349. package/dist/infrastructure/server/handlers/monitoring/health.js +45 -16
  350. package/dist/infrastructure/server/handlers/monitoring/operations.d.ts +1 -1
  351. package/dist/infrastructure/server/handlers/monitoring/operations.js +8 -1
  352. package/dist/infrastructure/server/handlers/monitoring/workers.d.ts +3 -3
  353. package/dist/infrastructure/server/handlers/monitoring/workers.js +31 -7
  354. package/dist/infrastructure/server/handlers/pushBatchValidation.d.ts +3 -1
  355. package/dist/infrastructure/server/handlers/pushBatchValidation.js +52 -7
  356. package/dist/infrastructure/server/handlers/query.d.ts +1 -1
  357. package/dist/infrastructure/server/handlers/query.js +5 -4
  358. package/dist/infrastructure/server/http.js +2 -2
  359. package/dist/infrastructure/server/httpDashboardEndpoints.d.ts +1 -1
  360. package/dist/infrastructure/server/httpDashboardEndpoints.js +19 -6
  361. package/dist/infrastructure/server/httpEndpoints.js +20 -7
  362. package/dist/infrastructure/server/httpRouteQueues.js +11 -1
  363. package/dist/infrastructure/server/shutdownCoordinator.d.ts +24 -0
  364. package/dist/infrastructure/server/shutdownCoordinator.js +106 -0
  365. package/dist/infrastructure/server/sseHandler.js +8 -3
  366. package/dist/infrastructure/server/storageAdapter.d.ts +29 -0
  367. package/dist/infrastructure/server/storageAdapter.js +61 -0
  368. package/dist/infrastructure/server/storageManager.d.ts +12 -0
  369. package/dist/infrastructure/server/storageManager.js +102 -0
  370. package/dist/infrastructure/server/tcp.js +2 -3
  371. package/dist/infrastructure/server/ws/snapshots.d.ts +1 -1
  372. package/dist/infrastructure/server/ws/snapshots.js +19 -4
  373. package/dist/infrastructure/server/wsHandler.js +10 -5
  374. package/dist/main.js +1 -1
  375. package/dist/mcp/backend/embedded/services.js +2 -1
  376. package/dist/mcp/index.d.ts +2 -2
  377. package/dist/mcp/index.js +2 -2
  378. package/dist/shared/storageHealth.d.ts +9 -0
  379. package/dist/shared/storageHealth.js +12 -0
  380. package/package.json +85 -74
@@ -34,9 +34,8 @@ export class EventsManager {
34
34
  // Clear all waiters
35
35
  for (const waiters of this.completionWaiters.values()) {
36
36
  for (const waiter of waiters) {
37
- if (!waiter.cancelled) {
37
+ if (!waiter.cancelled)
38
38
  waiter.resolve();
39
- }
40
39
  }
41
40
  }
42
41
  this.completionWaiters.clear();
@@ -45,40 +44,45 @@ export class EventsManager {
45
44
  * Wait for a specific job to complete - event-driven, no polling
46
45
  * Returns true if job completed, false if timeout
47
46
  */
48
- waitForJobCompletion(jobId, timeoutMs) {
47
+ waitForJobCompletion(jobId, timeoutMs, signal) {
49
48
  const jobKey = String(jobId);
49
+ if (signal?.aborted)
50
+ return Promise.resolve(false);
50
51
  return new Promise((resolve) => {
52
+ let settled = false;
53
+ const cleanup = () => {
54
+ clearTimeout(timer);
55
+ signal?.removeEventListener('abort', onAbort);
56
+ const waiters = this.completionWaiters.get(jobKey);
57
+ waiters?.delete(waiter);
58
+ if (waiters?.size === 0)
59
+ this.completionWaiters.delete(jobKey);
60
+ };
61
+ const finish = (completed) => {
62
+ if (settled)
63
+ return;
64
+ settled = true;
65
+ waiter.cancelled = !completed;
66
+ cleanup();
67
+ resolve(completed);
68
+ };
69
+ const onAbort = () => finish(false);
51
70
  const waiter = {
52
- resolve: () => {
53
- clearTimeout(timer);
54
- resolve(true);
55
- },
71
+ resolve: () => finish(true),
72
+ cancel: () => finish(false),
56
73
  cancelled: false,
57
74
  };
58
- const timer = setTimeout(() => {
59
- // Timeout - mark as cancelled and remove from map to prevent memory leak
60
- waiter.cancelled = true;
61
- // Remove the waiter from the array
62
- const waiters = this.completionWaiters.get(jobKey);
63
- if (waiters) {
64
- const index = waiters.indexOf(waiter);
65
- if (index !== -1) {
66
- waiters.splice(index, 1);
67
- }
68
- // Clean up empty arrays to free memory
69
- if (waiters.length === 0) {
70
- this.completionWaiters.delete(jobKey);
71
- }
72
- }
73
- resolve(false);
74
- }, timeoutMs);
75
75
  // Add to waiters
76
76
  let waiters = this.completionWaiters.get(jobKey);
77
77
  if (!waiters) {
78
- waiters = [];
78
+ waiters = new Set();
79
79
  this.completionWaiters.set(jobKey, waiters);
80
80
  }
81
- waiters.push(waiter);
81
+ waiters.add(waiter);
82
+ const timer = setTimeout(() => finish(false), timeoutMs);
83
+ signal?.addEventListener('abort', onAbort, { once: true });
84
+ if (signal?.aborted)
85
+ onAbort();
82
86
  });
83
87
  }
84
88
  /** Check if broadcast has any listeners - for batch optimizations */
@@ -78,7 +78,7 @@ export async function checkExpiredLocks(ctx) {
78
78
  * Process a single expired lock (called with both locks already held)
79
79
  * Lock hierarchy already satisfied: shardLock -> processingLock held by caller
80
80
  */
81
- // biome-ignore lint/complexity/useMaxParams: lock-processing inner fn needs the full lock context (7 params)
81
+ // oxlint-disable-next-line max-params -- lock-processing inner fn needs the full lock context (7 params)
82
82
  function processExpiredLockInner(jobId, lock, job, shardIdx, procIdx, ctx, now) {
83
83
  const shard = ctx.shards[shardIdx];
84
84
  const queue = shard.getQueue(job.queue);
@@ -26,6 +26,10 @@ export interface JobManagementContext {
26
26
  eventsManager: EventsManager;
27
27
  repeatChain?: Map<JobId, JobId>;
28
28
  dependencyResults: DependencyResultTracker;
29
+ customIdMap: {
30
+ get(id: string): JobId | undefined;
31
+ delete(id: string): boolean;
32
+ };
29
33
  depCompletions?: DependencyCompletionTracker;
30
34
  maxDependencyCompletions: number;
31
35
  }
@@ -75,7 +75,7 @@ export async function discardJob(jobId, ctx) {
75
75
  const validJob = job;
76
76
  const idx = shardIndex(validJob.queue);
77
77
  const fromProcessing = location.type === 'processing';
78
- const entry = await withWriteLock(ctx.shardLocks[idx], () => {
78
+ await withWriteLock(ctx.shardLocks[idx], () => {
79
79
  const shard = ctx.shards[idx];
80
80
  if (fromProcessing) {
81
81
  shard.releaseJobResources(validJob.queue, validJob.uniqueKey, validJob.groupId, validJob.id);
@@ -86,9 +86,14 @@ export async function discardJob(jobId, ctx) {
86
86
  }
87
87
  const dlqEntry = shard.addToDlq(validJob);
88
88
  ctx.jobIndex.set(jobId, { type: 'dlq', queueName: validJob.queue });
89
- return dlqEntry;
89
+ // SQLite writes are synchronous. Keeping them in this critical section
90
+ // prevents a concurrent permanent removal from racing a late DLQ insert.
91
+ ctx.storage?.saveDlqEntry(dlqEntry);
92
+ ctx.storage?.deleteJob(jobId);
93
+ ctx.dependencyResults.releaseConsumer(jobId);
94
+ if (validJob.customId && ctx.customIdMap.get(validJob.customId) === jobId) {
95
+ ctx.customIdMap.delete(validJob.customId);
96
+ }
90
97
  });
91
- ctx.storage?.saveDlqEntry(entry);
92
- ctx.storage?.deleteJob(jobId);
93
98
  return true;
94
99
  }
@@ -0,0 +1,16 @@
1
+ import type { Job, JobId } from '../../domain/types/job';
2
+ import type { PostgresJobState } from '../../infrastructure/persistence/postgres';
3
+ import type { PostgresQueueSnapshot } from './snapshot';
4
+ interface BatchCompletionItem {
5
+ readonly id: JobId;
6
+ readonly result?: unknown;
7
+ }
8
+ interface BatchCompletionTransition {
9
+ readonly applied: boolean;
10
+ readonly job: Job | null;
11
+ readonly state: PostgresJobState | null;
12
+ readonly removed: boolean;
13
+ }
14
+ /** Apply an authoritative batch result without reloading every job in its queue. */
15
+ export declare function applyPostgresBatchCompletion(snapshot: PostgresQueueSnapshot, item: BatchCompletionItem, transition: BatchCompletionTransition): string | null;
16
+ export {};
@@ -0,0 +1,17 @@
1
+ /** Apply an authoritative batch result without reloading every job in its queue. */
2
+ export function applyPostgresBatchCompletion(snapshot, item, transition) {
3
+ if (!transition.applied || !transition.job || transition.state !== 'completed')
4
+ return null;
5
+ snapshot.apply({
6
+ id: 0,
7
+ queue: transition.job.queue,
8
+ type: 'completed',
9
+ jobId: item.id,
10
+ occurredAt: transition.job.completedAt ?? Date.now(),
11
+ job: transition.job,
12
+ state: 'completed',
13
+ result: item.result,
14
+ removed: transition.removed,
15
+ });
16
+ return transition.job.repeat === null ? null : transition.job.queue;
17
+ }
@@ -0,0 +1,30 @@
1
+ import type { JobId } from '../../domain/types/job';
2
+ import type { PostgresCloudReadModel } from '../../infrastructure/persistence/postgres/cloudReadModel';
3
+ import { PostgresQueueManagerServices } from './services';
4
+ /** PostgreSQL-specific Cloud read port with no eventually-consistent fallback. */
5
+ export declare class PostgresQueueManagerCloud extends PostgresQueueManagerServices {
6
+ getCloudProcessStats(): {
7
+ waiting: number;
8
+ prioritized: number;
9
+ delayed: number;
10
+ active: number;
11
+ dlq: number;
12
+ completed: number;
13
+ 'waiting-children': number;
14
+ totalPushed: bigint;
15
+ totalPulled: bigint;
16
+ totalCompleted: bigint;
17
+ totalFailed: bigint;
18
+ uptime: number;
19
+ cronJobs: number;
20
+ cronPending: number;
21
+ };
22
+ readCloudSnapshotDurable(): Promise<PostgresCloudReadModel>;
23
+ listCloudJobsDurable(queue: string, options?: {
24
+ state?: string | string[];
25
+ start?: number;
26
+ end?: number;
27
+ asc?: boolean;
28
+ }): Promise<import("../../domain/types").Job[]>;
29
+ getCloudResultDurable(id: JobId): Promise<unknown>;
30
+ }
@@ -0,0 +1,55 @@
1
+ import { PostgresQueueManagerServices } from './services';
2
+ const POSTGRES_STATES = new Set([
3
+ 'waiting',
4
+ 'prioritized',
5
+ 'delayed',
6
+ 'waiting-children',
7
+ 'active',
8
+ 'completed',
9
+ 'failed',
10
+ ]);
11
+ function pageIndex(value, fallback) {
12
+ if (value === undefined || !Number.isFinite(value))
13
+ return fallback;
14
+ return Math.min(Number.MAX_SAFE_INTEGER, Math.max(0, Math.floor(value)));
15
+ }
16
+ function durableStates(value) {
17
+ if (value === undefined)
18
+ return undefined;
19
+ const requested = Array.isArray(value) ? value : [value];
20
+ const normalized = requested.flatMap((state) => state === 'paused' ? ['waiting', 'prioritized'] : [state]);
21
+ return [...new Set(normalized)].filter((state) => POSTGRES_STATES.has(state));
22
+ }
23
+ /** PostgreSQL-specific Cloud read port with no eventually-consistent fallback. */
24
+ export class PostgresQueueManagerCloud extends PostgresQueueManagerServices {
25
+ getCloudProcessStats() {
26
+ return super.getStats();
27
+ }
28
+ async readCloudSnapshotDurable() {
29
+ return await this.runPostgresOperation(async () => {
30
+ await this.postgresReady;
31
+ return await this.postgresStore.loadCloudReadModel();
32
+ });
33
+ }
34
+ async listCloudJobsDurable(queue, options = {}) {
35
+ return await this.runPostgresOperation(async () => {
36
+ await this.postgresReady;
37
+ const start = pageIndex(options.start, 0);
38
+ const end = Math.max(start, pageIndex(options.end, 100));
39
+ const rows = await this.postgresStore.list(queue, {
40
+ states: durableStates(options.state),
41
+ offset: start,
42
+ limit: end - start,
43
+ asc: options.asc ?? true,
44
+ });
45
+ return rows.map((row) => row.job);
46
+ });
47
+ }
48
+ async getCloudResultDurable(id) {
49
+ return await this.runPostgresOperation(async () => {
50
+ await this.postgresReady;
51
+ const result = await this.postgresStore.getResult(id);
52
+ return result.found ? result.result : null;
53
+ });
54
+ }
55
+ }
@@ -0,0 +1,5 @@
1
+ import type { PostgresStorageConfig } from '../../infrastructure/persistence/postgres';
2
+ import type { QueueManagerConfig } from '../types';
3
+ export interface PostgresQueueManagerConfig extends Omit<QueueManagerConfig, 'dataPath'> {
4
+ readonly postgres: PostgresStorageConfig;
5
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,26 @@
1
+ import { type DlqConfig } from '../../domain/types/dlq';
2
+ import { type StallConfig } from '../../domain/types/stall';
3
+ import { PostgresQueueManagerMaintenance } from './maintenance';
4
+ /** Durable queue controls and policies shared by every PostgreSQL broker. */
5
+ export declare class PostgresQueueManagerControl extends PostgresQueueManagerMaintenance {
6
+ pause(queue: string): void;
7
+ resume(queue: string): void;
8
+ pauseDurable(queue: string, paused: boolean): Promise<void>;
9
+ drain(queue: string): number;
10
+ drainDurable(queue: string): Promise<number>;
11
+ obliterate(queue: string): void;
12
+ obliterateDurable(queue: string): Promise<void>;
13
+ setRateLimit(queue: string, limit: number, durationMs?: number, ttlMs?: number): void;
14
+ clearRateLimit(queue: string): void;
15
+ setConcurrency(queue: string, limit: number): void;
16
+ clearConcurrency(queue: string): void;
17
+ setRateLimitDurable(queue: string, limit: number | null, durationMs: number | null, ttlMs?: number | null): Promise<void>;
18
+ setConcurrencyDurable(queue: string, limit: number | null): Promise<void>;
19
+ setStallConfig(queue: string, patch: Record<string, unknown>): void;
20
+ getStallConfig(queue: string): StallConfig;
21
+ setStallConfigDurable(queue: string, patch: Record<string, unknown>): Promise<void>;
22
+ setDlqConfig(queue: string, patch: Record<string, unknown>): void;
23
+ getDlqConfig(queue: string): DlqConfig;
24
+ setDlqConfigDurable(queue: string, patch: Record<string, unknown>): Promise<void>;
25
+ private setLocalQueueState;
26
+ }
@@ -0,0 +1,186 @@
1
+ import { DEFAULT_DLQ_CONFIG } from '../../domain/types/dlq';
2
+ import { DEFAULT_STALL_CONFIG } from '../../domain/types/stall';
3
+ import { normalizePostgresRateLimit } from '../../infrastructure/persistence/postgres/rateLimit';
4
+ import { PostgresQueueManagerMaintenance } from './maintenance';
5
+ const PENDING_STATES = ['waiting', 'prioritized', 'delayed', 'waiting-children'];
6
+ function normalizeDlq(current, patch) {
7
+ const next = { ...current };
8
+ if (typeof patch.autoRetry === 'boolean')
9
+ next.autoRetry = patch.autoRetry;
10
+ if (Number.isFinite(patch.autoRetryInterval)) {
11
+ next.autoRetryInterval = Math.max(0, Math.floor(patch.autoRetryInterval));
12
+ }
13
+ if (Number.isFinite(patch.maxAutoRetries)) {
14
+ next.maxAutoRetries = Math.max(0, Math.floor(patch.maxAutoRetries));
15
+ }
16
+ if (patch.maxAge === null)
17
+ next.maxAge = null;
18
+ else if (Number.isFinite(patch.maxAge)) {
19
+ next.maxAge = Math.max(0, Math.floor(patch.maxAge));
20
+ }
21
+ if (Number.isFinite(patch.maxEntries)) {
22
+ next.maxEntries = Math.max(1, Math.floor(patch.maxEntries));
23
+ }
24
+ return next;
25
+ }
26
+ /** Durable queue controls and policies shared by every PostgreSQL broker. */
27
+ export class PostgresQueueManagerControl extends PostgresQueueManagerMaintenance {
28
+ pause(queue) {
29
+ this.operations.runSync(() => {
30
+ this.setLocalQueueState(queue, { paused: true });
31
+ this.enqueueWrite(() => this.postgresStore.pause(queue, true));
32
+ });
33
+ }
34
+ resume(queue) {
35
+ this.operations.runSync(() => {
36
+ this.setLocalQueueState(queue, { paused: false });
37
+ this.enqueueWrite(() => this.postgresStore.pause(queue, false));
38
+ });
39
+ }
40
+ async pauseDurable(queue, paused) {
41
+ return await this.runPostgresOperation(async () => {
42
+ await this.postgresReady;
43
+ await this.postgresStore.pause(queue, paused);
44
+ await this.refreshQueueAfterCommit(queue);
45
+ });
46
+ }
47
+ drain(queue) {
48
+ return this.operations.runSync(() => {
49
+ const count = this.postgresSnapshot.removeStates(queue, PENDING_STATES);
50
+ this.enqueueWrite(async () => {
51
+ await this.postgresStore.drain(queue);
52
+ await this.refreshQueueAfterCommit(queue);
53
+ });
54
+ return count;
55
+ });
56
+ }
57
+ async drainDurable(queue) {
58
+ return await this.runPostgresOperation(async () => {
59
+ await this.postgresReady;
60
+ const count = await this.postgresStore.drain(queue);
61
+ await this.refreshQueueAfterCommit(queue);
62
+ return count;
63
+ });
64
+ }
65
+ obliterate(queue) {
66
+ this.operations.runSync(() => {
67
+ this.postgresSnapshot.removeStates(queue, [
68
+ ...PENDING_STATES,
69
+ 'active',
70
+ 'completed',
71
+ 'failed',
72
+ ]);
73
+ this.enqueueWrite(async () => {
74
+ await this.postgresStore.obliterate(queue);
75
+ await this.refreshQueueAfterCommit(queue);
76
+ });
77
+ });
78
+ }
79
+ async obliterateDurable(queue) {
80
+ return await this.runPostgresOperation(async () => {
81
+ await this.postgresReady;
82
+ await this.postgresStore.obliterate(queue);
83
+ await this.refreshQueueAfterCommit(queue);
84
+ });
85
+ }
86
+ setRateLimit(queue, limit, durationMs, ttlMs) {
87
+ this.operations.runSync(() => {
88
+ const normalized = normalizePostgresRateLimit(durationMs, ttlMs);
89
+ this.setLocalQueueState(queue, {
90
+ rateLimit: limit,
91
+ rateDurationMs: normalized.durationMs,
92
+ rateExpiresAt: normalized.ttlMs === null ? null : Date.now() + normalized.ttlMs,
93
+ });
94
+ this.enqueueWrite(() => this.postgresStore.setRateLimit(queue, limit, normalized.durationMs, normalized.ttlMs));
95
+ });
96
+ }
97
+ clearRateLimit(queue) {
98
+ this.operations.runSync(() => {
99
+ this.setLocalQueueState(queue, {
100
+ rateLimit: null,
101
+ rateDurationMs: null,
102
+ rateExpiresAt: null,
103
+ });
104
+ this.enqueueWrite(() => this.postgresStore.setRateLimit(queue, null, null));
105
+ });
106
+ }
107
+ setConcurrency(queue, limit) {
108
+ this.operations.runSync(() => {
109
+ this.setLocalQueueState(queue, { concurrencyLimit: limit });
110
+ this.enqueueWrite(() => this.postgresStore.setConcurrency(queue, limit));
111
+ });
112
+ }
113
+ clearConcurrency(queue) {
114
+ this.operations.runSync(() => {
115
+ this.setLocalQueueState(queue, { concurrencyLimit: null });
116
+ this.enqueueWrite(() => this.postgresStore.setConcurrency(queue, null));
117
+ });
118
+ }
119
+ async setRateLimitDurable(queue, limit, durationMs, ttlMs) {
120
+ return await this.runPostgresOperation(async () => {
121
+ await this.postgresReady;
122
+ const normalized = normalizePostgresRateLimit(durationMs, ttlMs);
123
+ await this.postgresStore.setRateLimit(queue, limit, normalized.durationMs, normalized.ttlMs);
124
+ await this.refreshQueueAfterCommit(queue);
125
+ });
126
+ }
127
+ async setConcurrencyDurable(queue, limit) {
128
+ return await this.runPostgresOperation(async () => {
129
+ await this.postgresReady;
130
+ await this.postgresStore.setConcurrency(queue, limit);
131
+ await this.refreshQueueAfterCommit(queue);
132
+ });
133
+ }
134
+ setStallConfig(queue, patch) {
135
+ this.operations.runSync(() => {
136
+ const config = { ...this.getStallConfig(queue), ...patch };
137
+ this.setLocalQueueState(queue, { stallConfig: config });
138
+ this.enqueueWrite(() => this.postgresStore.setStallConfig(queue, config));
139
+ });
140
+ }
141
+ getStallConfig(queue) {
142
+ return this.postgresSnapshot.queueState(queue)?.stallConfig ?? DEFAULT_STALL_CONFIG;
143
+ }
144
+ async setStallConfigDurable(queue, patch) {
145
+ return await this.runPostgresOperation(async () => {
146
+ await this.postgresReady;
147
+ const state = await this.postgresStore.getQueueState(queue);
148
+ const config = { ...state.stallConfig, ...patch };
149
+ await this.postgresStore.setStallConfig(queue, config);
150
+ await this.refreshQueueAfterCommit(queue);
151
+ });
152
+ }
153
+ setDlqConfig(queue, patch) {
154
+ this.operations.runSync(() => {
155
+ const config = normalizeDlq(this.getDlqConfig(queue), patch);
156
+ this.setLocalQueueState(queue, { dlqConfig: config });
157
+ this.enqueueWrite(() => this.postgresStore.setDlqConfig(queue, config));
158
+ });
159
+ }
160
+ getDlqConfig(queue) {
161
+ return this.postgresSnapshot.queueState(queue)?.dlqConfig ?? DEFAULT_DLQ_CONFIG;
162
+ }
163
+ async setDlqConfigDurable(queue, patch) {
164
+ return await this.runPostgresOperation(async () => {
165
+ await this.postgresReady;
166
+ const state = await this.postgresStore.getQueueState(queue);
167
+ await this.postgresStore.setDlqConfig(queue, normalizeDlq(state.dlqConfig, patch));
168
+ await this.refreshQueueAfterCommit(queue);
169
+ });
170
+ }
171
+ setLocalQueueState(queue, patch) {
172
+ const current = this.postgresSnapshot.queueState(queue) ?? {
173
+ queue,
174
+ paused: false,
175
+ rateLimit: null,
176
+ rateDurationMs: null,
177
+ rateWindowStartedAt: null,
178
+ rateExpiresAt: null,
179
+ rateCount: 0,
180
+ concurrencyLimit: null,
181
+ stallConfig: DEFAULT_STALL_CONFIG,
182
+ dlqConfig: DEFAULT_DLQ_CONFIG,
183
+ };
184
+ this.postgresSnapshot.setQueueState({ ...current, ...patch });
185
+ }
186
+ }
@@ -0,0 +1,13 @@
1
+ export declare function throwDeferredWriteErrors(errors: readonly unknown[], message?: string): void;
2
+ /** Serializes fire-and-forget writes while retaining failures until an observed drain. */
3
+ export declare class PostgresDeferredWriteQueue {
4
+ private accepting;
5
+ private tail;
6
+ private nextSequence;
7
+ private readonly failures;
8
+ private checkpoint;
9
+ enqueue(operation: () => Promise<void>): void;
10
+ closeAndDrain(): Promise<unknown[]>;
11
+ drain(): Promise<unknown[]>;
12
+ flush(): Promise<void>;
13
+ }
@@ -0,0 +1,60 @@
1
+ export function throwDeferredWriteErrors(errors, message = 'Multiple deferred PostgreSQL writes failed') {
2
+ if (errors.length === 0)
3
+ return;
4
+ if (errors.length === 1)
5
+ throw errors[0];
6
+ throw new AggregateError(errors, message);
7
+ }
8
+ /** Serializes fire-and-forget writes while retaining failures until an observed drain. */
9
+ export class PostgresDeferredWriteQueue {
10
+ accepting = true;
11
+ tail = Promise.resolve();
12
+ nextSequence = 0;
13
+ failures = [];
14
+ checkpoint = null;
15
+ enqueue(operation) {
16
+ if (!this.accepting)
17
+ throw new Error('PostgreSQL queue manager is shutting down');
18
+ const sequence = ++this.nextSequence;
19
+ this.tail = this.tail.then(async () => {
20
+ try {
21
+ await operation();
22
+ }
23
+ catch (error) {
24
+ this.failures.push({ sequence, error });
25
+ }
26
+ });
27
+ }
28
+ closeAndDrain() {
29
+ this.accepting = false;
30
+ return this.drain();
31
+ }
32
+ async drain() {
33
+ const throughSequence = this.nextSequence;
34
+ const pending = this.checkpoint;
35
+ if (pending?.sequence === throughSequence)
36
+ return [...(await pending.result)];
37
+ const throughTail = this.tail;
38
+ const checkpoint = {
39
+ sequence: throughSequence,
40
+ result: throughTail.then(() => {
41
+ const firstLaterFailure = this.failures.findIndex(({ sequence }) => sequence > throughSequence);
42
+ const observed = firstLaterFailure === -1
43
+ ? this.failures.splice(0)
44
+ : this.failures.splice(0, firstLaterFailure);
45
+ return observed.map(({ error }) => error);
46
+ }),
47
+ };
48
+ this.checkpoint = checkpoint;
49
+ try {
50
+ return [...(await checkpoint.result)];
51
+ }
52
+ finally {
53
+ if (this.checkpoint === checkpoint)
54
+ this.checkpoint = null;
55
+ }
56
+ }
57
+ async flush() {
58
+ throwDeferredWriteErrors(await this.drain());
59
+ }
60
+ }
@@ -0,0 +1,19 @@
1
+ import type { AtomicFlowBatchInput, AtomicFlowBatchResult } from '../../domain/types/flow';
2
+ import { type Job, type JobId, type JobInput } from '../../domain/types/job';
3
+ import { PostgresQueueManagerTerminalDelivery } from './terminalDelivery';
4
+ export declare class PostgresQueueManagerDelivery extends PostgresQueueManagerTerminalDelivery {
5
+ push(queue: string, input: JobInput): Promise<Job>;
6
+ pushBatch(queue: string, inputs: JobInput[]): Promise<JobId[]>;
7
+ pushFlow(batch: AtomicFlowBatchInput): Promise<AtomicFlowBatchResult>;
8
+ pull(queue: string, timeoutMs?: number, signal?: AbortSignal): Promise<Job | null>;
9
+ pullWithLock(queue: string, owner: string, timeoutMs?: number, lockTtl?: number, signal?: AbortSignal): Promise<{
10
+ job: Job | null;
11
+ token: string | null;
12
+ }>;
13
+ pullBatch(queue: string, count: number, timeoutMs?: number, signal?: AbortSignal): Promise<Job[]>;
14
+ pullBatchWithLock(queue: string, count: number, owner: string, timeoutMs?: number, lockTtl?: number, signal?: AbortSignal): Promise<{
15
+ jobs: Job[];
16
+ tokens: string[];
17
+ }>;
18
+ private claimUntil;
19
+ }
@@ -0,0 +1,80 @@
1
+ import { createJob, DEFAULT_LOCK_TTL, generateJobId, jobId, } from '../../domain/types/job';
2
+ import { validateRepeatJobInput } from '../repeatJobs';
3
+ import { PostgresQueueManagerTerminalDelivery } from './terminalDelivery';
4
+ export class PostgresQueueManagerDelivery extends PostgresQueueManagerTerminalDelivery {
5
+ async push(queue, input) {
6
+ return await this.runPostgresOperation(async () => {
7
+ await this.postgresReady;
8
+ validateRepeatJobInput(input);
9
+ const id = input.customId ? jobId(input.customId) : generateJobId();
10
+ const admitted = await this.postgresStore.insert(createJob(id, queue, input, await this.postgresStore.now()));
11
+ await this.refreshJob(admitted.job.id, queue);
12
+ return admitted.job;
13
+ });
14
+ }
15
+ async pushBatch(queue, inputs) {
16
+ return await this.runPostgresOperation(async () => {
17
+ await this.postgresReady;
18
+ for (const input of inputs)
19
+ validateRepeatJobInput(input);
20
+ const now = await this.postgresStore.now();
21
+ const jobs = inputs.map((input) => createJob(input.customId ? jobId(input.customId) : generateJobId(), queue, input, now));
22
+ const stored = await this.postgresStore.insertMany(jobs);
23
+ await this.refreshJobs(stored.map((job) => job.id), queue);
24
+ return stored.map((job) => job.id);
25
+ });
26
+ }
27
+ async pushFlow(batch) {
28
+ return await this.runPostgresOperation(async () => {
29
+ await this.postgresReady;
30
+ const jobs = await this.postgresStore.insertFlow(batch);
31
+ await Promise.all(new Set(jobs.map((job) => job.queue))
32
+ .values()
33
+ .map((queue) => this.refreshQueueAfterCommit(queue)));
34
+ return { jobs };
35
+ });
36
+ }
37
+ async pull(queue, timeoutMs = 0, signal) {
38
+ const claims = await this.claimUntil(queue, 1, this.postgresStore.config.brokerId, timeoutMs, undefined, signal);
39
+ return claims[0]?.job ?? null;
40
+ }
41
+ async pullWithLock(queue, owner, timeoutMs = 0, lockTtl = DEFAULT_LOCK_TTL, signal) {
42
+ const claims = await this.claimUntil(queue, 1, owner, timeoutMs, lockTtl, signal);
43
+ const claim = claims[0];
44
+ return claim ? { job: claim.job, token: claim.token } : { job: null, token: null };
45
+ }
46
+ async pullBatch(queue, count, timeoutMs = 0, signal) {
47
+ const claims = await this.claimUntil(queue, count, this.postgresStore.config.brokerId, timeoutMs, undefined, signal);
48
+ return claims.map((claim) => claim.job);
49
+ }
50
+ // oxlint-disable-next-line max-params -- public API includes cancellation and lease policy
51
+ async pullBatchWithLock(queue, count, owner, timeoutMs = 0, lockTtl = DEFAULT_LOCK_TTL, signal) {
52
+ const claims = await this.claimUntil(queue, count, owner, timeoutMs, lockTtl, signal);
53
+ return {
54
+ jobs: claims.map((claim) => claim.job),
55
+ tokens: claims.map((claim) => claim.token),
56
+ };
57
+ }
58
+ // oxlint-disable-next-line max-params -- internal bridge mirrors the public pull contract
59
+ async claimUntil(queue, count, owner, timeoutMs, leaseDurationMs, signal) {
60
+ await this.postgresReady;
61
+ await this.flushPostgresWrites();
62
+ const deadline = Date.now() + Math.max(0, timeoutMs);
63
+ do {
64
+ const claims = await this.runPostgresOperation(async () => {
65
+ const admitted = await this.postgresStore.claim(queue, count, owner, leaseDurationMs);
66
+ for (const claim of admitted) {
67
+ this.applyPostgresClaim(claim);
68
+ }
69
+ return admitted;
70
+ });
71
+ if (claims.length > 0 || timeoutMs <= 0 || signal?.aborted)
72
+ return claims;
73
+ const remaining = deadline - Date.now();
74
+ if (remaining <= 0)
75
+ return [];
76
+ await this.postgresStore.waitForWork(queue, Math.min(remaining, this.postgresStore.config.pollIntervalMs), signal);
77
+ } while (!signal?.aborted);
78
+ return [];
79
+ }
80
+ }
@@ -0,0 +1,13 @@
1
+ import { type JobId, type JobLock, type LockToken } from '../../domain/types/job';
2
+ import { PostgresQueueManagerDelivery } from './delivery';
3
+ export declare class PostgresQueueManagerLease extends PostgresQueueManagerDelivery {
4
+ extendLock(id: JobId | string, token: string | null, duration: number): Promise<boolean>;
5
+ heartbeatDurable(id: JobId, token?: string, duration?: number): Promise<boolean>;
6
+ heartbeatBatchDurable(ids: JobId[], tokens?: string[]): Promise<number>;
7
+ jobHeartbeat(id: JobId, token?: string): boolean;
8
+ jobHeartbeatBatch(ids: JobId[], tokens?: string[]): number;
9
+ verifyLock(id: JobId, token: string): boolean;
10
+ renewJobLock(id: JobId, token: string, ttl?: number): boolean;
11
+ getLockInfo(id: JobId): JobLock | null;
12
+ createLock(id: JobId, _owner: string, _ttl?: number): LockToken | null;
13
+ }