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
@@ -0,0 +1,273 @@
1
+ import { PostgresQueueStore, } from '../../infrastructure/persistence/postgres';
2
+ import { QueueManager } from '../queueManager';
3
+ import { stopBackgroundTasks } from '../backgroundTasks';
4
+ import { PostgresDeferredWriteQueue, throwDeferredWriteErrors } from './deferredWrites';
5
+ import { applyPostgresEventMetrics, hydratePostgresLifetimeMetrics, postgresEventType, } from './lifetimeMetrics';
6
+ import { PostgresQueueSnapshot } from './snapshot';
7
+ import { PostgresStartupEventBuffer } from './startupEventBuffer';
8
+ import { PostgresOperationGate } from './operationGate';
9
+ import { applyPostgresJobProjection, PostgresProjectionRefreshes } from './projectionRefreshes';
10
+ export class PostgresQueueManagerState extends QueueManager {
11
+ postgresStore;
12
+ postgresSnapshot;
13
+ activeTokens = new Map();
14
+ postgresReady;
15
+ refreshes = new Map();
16
+ dirtyQueues = new Set();
17
+ queueEventVersions = new Map();
18
+ snapshotEventBuffer = new PostgresStartupEventBuffer();
19
+ terminalMetricBaselineCommitSeq = 0;
20
+ unsubscribeEvent;
21
+ unsubscribeInvalidation;
22
+ writes = new PostgresDeferredWriteQueue();
23
+ operations;
24
+ projectionRefreshes;
25
+ shutdownPromise = null;
26
+ shutdownComplete = false;
27
+ baseStopped = false;
28
+ stopQueueRefreshes = false;
29
+ constructor(config) {
30
+ const { postgres, ...baseConfig } = config;
31
+ super(baseConfig);
32
+ if (this.backgroundTaskHandles)
33
+ stopBackgroundTasks(this.backgroundTaskHandles);
34
+ this.postgresSnapshot = new PostgresQueueSnapshot(this.config.maxCompletedJobs, this.config.maxJobResults);
35
+ this.postgresStore = new PostgresQueueStore({
36
+ ...postgres,
37
+ maxQueueEvents: this.config.maxQueueEvents,
38
+ maxMetricDataPoints: this.config.maxMetricDataPoints,
39
+ maxCompletedJobs: this.config.maxCompletedJobs,
40
+ maxJobResults: this.config.maxJobResults,
41
+ });
42
+ this.operations = new PostgresOperationGate(this.postgresStore.config.maxConcurrentOperations, this.postgresStore.config.maxQueuedOperations);
43
+ this.projectionRefreshes = new PostgresProjectionRefreshes((requests) => this.postgresStore.loadJobProjections(requests), (id, projection) => applyPostgresJobProjection(this.postgresSnapshot, this.activeTokens, id, projection), (queue, id, error) => this.postgresStore.reportProjectionRefresh(queue, id, error), this.postgresStore.config.pollIntervalMs);
44
+ this.unsubscribeEvent = this.postgresStore.onEvent((event) => this.onStoreEvent(event));
45
+ this.unsubscribeInvalidation = this.postgresStore.onInvalidation((queue) => {
46
+ this.scheduleQueueRefresh(queue);
47
+ });
48
+ this.postgresReady = this.initializePostgres();
49
+ }
50
+ async waitUntilReady() {
51
+ await this.postgresReady;
52
+ }
53
+ async flushPostgresWrites() {
54
+ await this.postgresReady;
55
+ await this.writes.flush();
56
+ }
57
+ async shutdownPostgres() {
58
+ if (this.shutdownComplete)
59
+ return;
60
+ if (!this.shutdownPromise) {
61
+ const attempt = this.performPostgresShutdown()
62
+ .then(() => {
63
+ this.shutdownComplete = true;
64
+ })
65
+ .finally(() => {
66
+ if (this.shutdownPromise === attempt && !this.shutdownComplete) {
67
+ this.shutdownPromise = null;
68
+ }
69
+ });
70
+ this.shutdownPromise = attempt;
71
+ }
72
+ await this.shutdownPromise;
73
+ }
74
+ shutdown() {
75
+ void this.shutdownPostgres().catch(() => undefined);
76
+ }
77
+ async performPostgresShutdown() {
78
+ this.stopQueueRefreshes = true;
79
+ this.dirtyQueues.clear();
80
+ this.projectionRefreshes.close();
81
+ const operationDrain = this.operations.closeAndDrain();
82
+ await operationDrain;
83
+ this.stopBaseRuntime();
84
+ this.unsubscribeEvent();
85
+ this.unsubscribeInvalidation();
86
+ const errors = await this.writes.closeAndDrain();
87
+ try {
88
+ await this.postgresReady;
89
+ }
90
+ catch (error) {
91
+ errors.push(error);
92
+ }
93
+ await Promise.allSettled([...this.refreshes.values(), this.projectionRefreshes.drain()]);
94
+ try {
95
+ await this.postgresStore.close();
96
+ }
97
+ catch (error) {
98
+ errors.push(error);
99
+ }
100
+ throwDeferredWriteErrors(errors, 'PostgreSQL shutdown failed');
101
+ }
102
+ tokenFor(id, token) {
103
+ return token ?? this.activeTokens.get(id) ?? this.postgresSnapshot.get(id)?.token ?? null;
104
+ }
105
+ forgetToken(id) {
106
+ this.activeTokens.delete(id);
107
+ }
108
+ runPostgresOperation(operation) {
109
+ return this.operations.run(operation);
110
+ }
111
+ async refreshJob(id, queue) {
112
+ const targetQueue = queue ?? this.postgresSnapshot.get(id)?.job.queue ?? '';
113
+ try {
114
+ await this.projectionRefreshes.refreshNow(id, targetQueue);
115
+ }
116
+ catch {
117
+ this.projectionRefreshes.request(id, targetQueue);
118
+ }
119
+ }
120
+ async fetchPostgresJob(id) {
121
+ const queue = this.postgresSnapshot.get(id)?.job.queue ?? '';
122
+ return (await this.projectionRefreshes.refreshNow(id, queue)).row;
123
+ }
124
+ async refreshJobs(ids, queue) {
125
+ const requests = [...new Set(ids)].map((id) => ({
126
+ id,
127
+ queue: queue ?? this.postgresSnapshot.get(id)?.job.queue ?? '',
128
+ }));
129
+ try {
130
+ await this.projectionRefreshes.refreshManyNow(requests);
131
+ }
132
+ catch {
133
+ for (const request of requests)
134
+ this.projectionRefreshes.request(request.id, request.queue);
135
+ }
136
+ }
137
+ async refreshQueue(queue) {
138
+ const eventVersion = this.queueEventVersions.get(queue) ?? 0;
139
+ const { rows, state, exists, results } = await this.postgresStore.loadQueueReadModel(queue);
140
+ if (eventVersion !== (this.queueEventVersions.get(queue) ?? 0)) {
141
+ this.dirtyQueues.add(queue);
142
+ return false;
143
+ }
144
+ this.projectionRefreshes.supersedeQueue(queue);
145
+ if (!exists) {
146
+ for (const id of this.postgresSnapshot.removeQueue(queue))
147
+ this.activeTokens.delete(id);
148
+ return true;
149
+ }
150
+ this.postgresSnapshot.replaceQueue(queue, rows, state, results);
151
+ return true;
152
+ }
153
+ async refreshQueueAfterCommit(queue) {
154
+ try {
155
+ if (!(await this.refreshQueue(queue)))
156
+ this.scheduleQueueRefresh(queue);
157
+ else
158
+ this.postgresStore.reportQueueRefresh(queue, null);
159
+ }
160
+ catch (error) {
161
+ this.postgresStore.reportQueueRefresh(queue, error);
162
+ this.scheduleQueueRefresh(queue);
163
+ }
164
+ }
165
+ enqueueWrite(operation) {
166
+ this.writes.enqueue(operation);
167
+ }
168
+ async initializePostgres() {
169
+ await this.postgresStore.initialize();
170
+ for (let attempt = 0; attempt < 2; attempt++) {
171
+ const buffer = this.snapshotEventBuffer;
172
+ if (!buffer)
173
+ return;
174
+ buffer.reset();
175
+ const { rows, results, crons, states } = await this.postgresStore.loadManagerSnapshot();
176
+ const events = buffer.take();
177
+ if (!events && attempt === 0)
178
+ continue;
179
+ this.postgresSnapshot.hydrate(rows);
180
+ this.postgresSnapshot.hydrateResults(results);
181
+ this.cronScheduler.load([...crons]);
182
+ for (const state of states)
183
+ this.postgresSnapshot.setQueueState(state);
184
+ for (const event of events ?? []) {
185
+ this.postgresSnapshot.apply(event);
186
+ applyPostgresEventMetrics(this.metrics, this.perQueueMetrics, event, false);
187
+ }
188
+ await this.postgresStore.finalizeLifetimeMetrics((lifetimeMetrics) => {
189
+ hydratePostgresLifetimeMetrics(this.metrics, this.perQueueMetrics, lifetimeMetrics);
190
+ this.terminalMetricBaselineCommitSeq = lifetimeMetrics.baselineCommitSeq;
191
+ this.snapshotEventBuffer = null;
192
+ this.projectionRefreshes.start();
193
+ });
194
+ return;
195
+ }
196
+ }
197
+ scheduleQueueRefresh(queue) {
198
+ if (this.stopQueueRefreshes)
199
+ return;
200
+ this.dirtyQueues.add(queue);
201
+ if (this.refreshes.has(queue))
202
+ return;
203
+ const refresh = this.postgresReady
204
+ .then(() => this.refreshDirtyQueue(queue))
205
+ .catch(() => {
206
+ this.dirtyQueues.delete(queue);
207
+ })
208
+ .finally(() => {
209
+ this.refreshes.delete(queue);
210
+ if (this.dirtyQueues.has(queue))
211
+ this.scheduleQueueRefresh(queue);
212
+ });
213
+ this.refreshes.set(queue, refresh);
214
+ }
215
+ async refreshDirtyQueue(queue) {
216
+ let retryDelay = this.postgresStore.config.pollIntervalMs;
217
+ while (!this.stopQueueRefreshes && this.dirtyQueues.delete(queue)) {
218
+ try {
219
+ const applied = await this.refreshQueue(queue);
220
+ if (!applied && !this.stopQueueRefreshes) {
221
+ await Bun.sleep(this.postgresStore.config.pollIntervalMs);
222
+ }
223
+ this.postgresStore.reportQueueRefresh(queue, null);
224
+ retryDelay = this.postgresStore.config.pollIntervalMs;
225
+ }
226
+ catch (error) {
227
+ this.postgresStore.reportQueueRefresh(queue, error);
228
+ if (this.stopQueueRefreshes)
229
+ return;
230
+ this.dirtyQueues.add(queue);
231
+ await Bun.sleep(retryDelay);
232
+ retryDelay = Math.min(retryDelay * 2, 1_000);
233
+ }
234
+ }
235
+ }
236
+ onStoreEvent(event) {
237
+ this.queueEventVersions.set(event.queue, (this.queueEventVersions.get(event.queue) ?? 0) + 1);
238
+ const startupBuffer = this.snapshotEventBuffer;
239
+ startupBuffer?.capture(event);
240
+ if (startupBuffer)
241
+ this.postgresSnapshot.apply(event);
242
+ if (startupBuffer?.overflowed)
243
+ this.scheduleQueueRefresh(event.queue);
244
+ else
245
+ this.projectionRefreshes.request(event.jobId, event.queue);
246
+ const mapped = postgresEventType(event.type);
247
+ if (!mapped)
248
+ return;
249
+ if (!startupBuffer) {
250
+ applyPostgresEventMetrics(this.metrics, this.perQueueMetrics, event, event.commitSeq > this.terminalMetricBaselineCommitSeq);
251
+ }
252
+ this.eventsManager.broadcast({
253
+ eventType: mapped,
254
+ queue: event.queue,
255
+ jobId: event.jobId,
256
+ timestamp: event.occurredAt,
257
+ ...(Object.hasOwn(event, 'result') && { data: event.result }),
258
+ ...(event.error !== undefined && { error: event.error }),
259
+ ...(mapped === 'failed' && { terminal: event.state === 'failed' }),
260
+ });
261
+ }
262
+ applyPostgresClaim(claim) {
263
+ this.projectionRefreshes.supersede(claim.job.id);
264
+ this.activeTokens.set(claim.job.id, claim.token);
265
+ this.postgresSnapshot.claim(claim);
266
+ }
267
+ stopBaseRuntime() {
268
+ if (this.baseStopped)
269
+ return;
270
+ this.baseStopped = true;
271
+ super.shutdown();
272
+ }
273
+ }
@@ -0,0 +1,20 @@
1
+ import { FailureReason } from '../../domain/types/dlq';
2
+ import type { JobId } from '../../domain/types/job';
3
+ import type { AckBatchOutcome, AckOutcome, CompletionOptions } from '../types/ack';
4
+ import { PostgresQueueManagerQueries } from './queries';
5
+ /** Terminal delivery transitions drained before the PostgreSQL pool closes. */
6
+ export declare class PostgresQueueManagerTerminalDelivery extends PostgresQueueManagerQueries {
7
+ ack(id: JobId, result?: unknown, token?: string, options?: CompletionOptions): Promise<AckOutcome>;
8
+ ackBatch(ids: JobId[], tokens?: string[]): Promise<AckBatchOutcome>;
9
+ ackBatchWithResults(items: Array<{
10
+ id: JobId;
11
+ result: unknown;
12
+ token?: string;
13
+ } & CompletionOptions>): Promise<AckBatchOutcome>;
14
+ fail(id: JobId, error?: string, token?: string, unrecoverable?: boolean, stack?: string[], removeOnFail?: boolean): Promise<AckOutcome>;
15
+ failWithReason(id: JobId, error: string | undefined, reason: FailureReason): Promise<AckOutcome>;
16
+ private requireToken;
17
+ private ackPostgres;
18
+ private completeBatch;
19
+ private failPostgres;
20
+ }
@@ -0,0 +1,100 @@
1
+ import { applyPostgresBatchCompletion } from './batchSnapshot';
2
+ import { PostgresQueueManagerQueries } from './queries';
3
+ /** Terminal delivery transitions drained before the PostgreSQL pool closes. */
4
+ export class PostgresQueueManagerTerminalDelivery extends PostgresQueueManagerQueries {
5
+ async ack(id, result, token, options = {}) {
6
+ return await this.runPostgresOperation(() => this.ackPostgres(id, result, token, options));
7
+ }
8
+ async ackBatch(ids, tokens) {
9
+ return await this.runPostgresOperation(() => this.completeBatch(ids.map((id, index) => ({ id, token: tokens?.[index] }))));
10
+ }
11
+ async ackBatchWithResults(items) {
12
+ return await this.runPostgresOperation(() => this.completeBatch(items));
13
+ }
14
+ // oxlint-disable-next-line max-params -- public compatibility signature carries failure policy
15
+ async fail(id, error, token, unrecoverable = false, stack, removeOnFail) {
16
+ return await this.runPostgresOperation(() => this.failPostgres(id, error, token, { unrecoverable, stack, removeOnFail }));
17
+ }
18
+ async failWithReason(id, error, reason) {
19
+ return await this.runPostgresOperation(() => this.failPostgres(id, error, undefined, {
20
+ unrecoverable: reason === "timeout" /* FailureReason.Timeout */,
21
+ failureReason: reason,
22
+ }));
23
+ }
24
+ requireToken(id, supplied) {
25
+ const token = this.tokenFor(id, supplied);
26
+ if (!token)
27
+ throw new Error(`Lock token required for job ${String(id)}`);
28
+ return token;
29
+ }
30
+ async ackPostgres(id, result, token, options) {
31
+ await this.postgresReady;
32
+ const transition = await this.postgresStore.complete(id, this.requireToken(id, token), result, options.removeOnComplete);
33
+ this.forgetToken(id);
34
+ await this.refreshJob(id);
35
+ if (transition.applied)
36
+ return;
37
+ if (transition.alreadyFinalized)
38
+ return { applied: false, reason: 'already-finalized' };
39
+ throw new Error(`Invalid or expired lock token for job ${String(id)}`);
40
+ }
41
+ async completeBatch(items) {
42
+ if (items.length === 0)
43
+ return;
44
+ if (new Set(items.map((item) => String(item.id))).size === items.length) {
45
+ await this.postgresReady;
46
+ const transitions = await this.postgresStore.completeMany(items.map((item) => ({
47
+ id: item.id,
48
+ token: this.requireToken(item.id, item.token),
49
+ result: item.result,
50
+ removeOnComplete: item.removeOnComplete,
51
+ })));
52
+ const repeatQueues = new Set();
53
+ const ignoredIds = [];
54
+ const ignoredIndices = [];
55
+ for (let index = 0; index < transitions.length; index++) {
56
+ const transition = transitions[index];
57
+ this.forgetToken(items[index].id);
58
+ const repeatQueue = applyPostgresBatchCompletion(this.postgresSnapshot, items[index], transition);
59
+ if (repeatQueue)
60
+ repeatQueues.add(repeatQueue);
61
+ if (!transition.applied) {
62
+ ignoredIndices.push(index);
63
+ ignoredIds.push(items[index].id);
64
+ }
65
+ }
66
+ await Promise.all([
67
+ ...ignoredIds.map((id) => this.refreshJob(id)),
68
+ ...[...repeatQueues].map((queue) => this.refreshQueueAfterCommit(queue)),
69
+ ]);
70
+ return ignoredIndices.length === 0
71
+ ? undefined
72
+ : { ignoredIndices, ignoredIds: ignoredIndices.map((index) => items[index].id) };
73
+ }
74
+ const ignoredIndices = [];
75
+ for (let index = 0; index < items.length; index++) {
76
+ const outcome = await this.ackPostgres(items[index].id, items[index].result, items[index].token, items[index]);
77
+ if (outcome)
78
+ ignoredIndices.push(index);
79
+ }
80
+ return ignoredIndices.length === 0
81
+ ? undefined
82
+ : { ignoredIndices, ignoredIds: ignoredIndices.map((index) => items[index].id) };
83
+ }
84
+ async failPostgres(id, error, token, options) {
85
+ await this.postgresReady;
86
+ const transition = await this.postgresStore.fail({
87
+ id,
88
+ token: this.requireToken(id, token),
89
+ error,
90
+ ...options,
91
+ });
92
+ this.forgetToken(id);
93
+ await this.refreshJob(id);
94
+ if (transition.applied)
95
+ return;
96
+ if (transition.alreadyFinalized)
97
+ return { applied: false, reason: 'already-finalized' };
98
+ throw new Error(`Invalid or expired lock token for job ${String(id)}`);
99
+ }
100
+ }
@@ -0,0 +1,2 @@
1
+ export { PostgresQueueManagerOperations as PostgresQueueManager } from './postgres-queue-manager/operations';
2
+ export type { PostgresQueueManagerConfig } from './postgres-queue-manager/config';
@@ -0,0 +1 @@
1
+ export { PostgresQueueManagerOperations as PostgresQueueManager } from './postgres-queue-manager/operations';
@@ -126,7 +126,7 @@ export class QueueManagerAck extends QueueManagerDelivery {
126
126
  this.syncJobTimeout(item.id);
127
127
  }
128
128
  }
129
- // biome-ignore lint/complexity/useMaxParams: public compatibility signature carries removal policy.
129
+ // oxlint-disable-next-line max-params -- public compatibility signature carries removal policy
130
130
  async fail(jobId, error, token, unrecoverable = false, stack, removeOnFail) {
131
131
  return this.failWithOptions(jobId, error, token, { unrecoverable, stack, removeOnFail });
132
132
  }
@@ -40,7 +40,7 @@ export class QueueManagerDelivery extends QueueManagerState {
40
40
  this.scheduleJobTimeout(job);
41
41
  return jobs;
42
42
  }
43
- // biome-ignore lint/complexity/useMaxParams: public API includes cancellation and lock policy
43
+ // oxlint-disable-next-line max-params -- public API includes cancellation and lock policy
44
44
  async pullBatchWithLock(queue, count, owner, timeoutMs = 0, lockTtl = DEFAULT_LOCK_TTL, signal) {
45
45
  const jobs = await pullJobBatch(queue, count, timeoutMs, this.contextFactory.getPullContext(), signal);
46
46
  const tokens = jobs.map((job) => lockMgr.createLock(job.id, owner, this.contextFactory.getLockContext(), lockTtl) ?? '');
@@ -9,6 +9,10 @@ export class QueueManagerFlowFailures extends QueueManagerDependencyRuntime {
9
9
  this.jobIndex.delete(entry.job.id);
10
10
  this.jobResults.delete(entry.job.id);
11
11
  this.jobLogs.delete(entry.job.id);
12
+ this.dependencyResults.releaseConsumer(entry.job.id);
13
+ if (entry.job.customId && this.customIdMap.get(entry.job.customId) === entry.job.id) {
14
+ this.customIdMap.delete(entry.job.customId);
15
+ }
12
16
  }
13
17
  this.storage?.purgeDlqEntries(entry.job.queue, [entry.job.id], ownsTerminal ? [entry.job.id] : [], false);
14
18
  }
@@ -16,6 +16,8 @@ export declare class QueueManagerLimits extends QueueManagerControl {
16
16
  retryDlq(queue: string, jobId?: JobId, limit?: number): number;
17
17
  retryDlqByFilter(queue: string, filter: DlqFilter): number;
18
18
  purgeDlq(queue: string): number;
19
+ /** Remove one terminal DLQ job without re-enqueuing it. */
20
+ removeDlqJob(queue: string, jobId: JobId): boolean;
19
21
  retryCompleted(queue: string, jobId?: JobId, options?: {
20
22
  limit?: number;
21
23
  timestamp?: number;
@@ -37,6 +37,10 @@ export class QueueManagerLimits extends QueueManagerControl {
37
37
  purgeDlq(queue) {
38
38
  return dlqOps.purgeDlqJobs(queue, this.contextFactory.getDlqContext());
39
39
  }
40
+ /** Remove one terminal DLQ job without re-enqueuing it. */
41
+ removeDlqJob(queue, jobId) {
42
+ return dlqOps.removeDlqJob(queue, jobId, this.contextFactory.getDlqContext());
43
+ }
40
44
  retryCompleted(queue, jobId, options) {
41
45
  return dlqOps.retryCompletedJobs(queue, this.contextFactory.getRetryCompletedContext(), jobId, options);
42
46
  }
@@ -2,6 +2,7 @@ import * as logsOps from '../jobLogsManager';
2
2
  import { generatePrometheusMetrics } from '../metricsExporter';
3
3
  import { selectPrometheusQueues } from '../prometheusOperationalMetrics';
4
4
  import * as statsMgr from '../statsManager';
5
+ import { isStorageDegraded } from '../../shared/storageHealth';
5
6
  import { QueueManagerStats } from './stats';
6
7
  export class QueueManagerObservability extends QueueManagerStats {
7
8
  getQueueMetrics(queue, type, start = 0, end = -1) {
@@ -25,9 +26,20 @@ export class QueueManagerObservability extends QueueManagerStats {
25
26
  getPrometheusMetrics() {
26
27
  const storageStatus = this.getStorageStatus();
27
28
  const memory = process.memoryUsage();
28
- const queueSelection = selectPrometheusQueues(this.queueNamesCache, this.config.maxPrometheusQueues);
29
- return generatePrometheusMetrics(this.getStats(), this.workerManager, this.webhookManager, statsMgr.getPerQueueStats(this.contextFactory.getStatsContext(), queueSelection.selected), {
30
- storageDegraded: storageStatus.diskFull,
29
+ const queueSelection = selectPrometheusQueues(this.listQueues(), this.config.maxPrometheusQueues);
30
+ const countsByQueue = this.getQueueJobCountsBatch(queueSelection.selected);
31
+ const perQueueStats = new Map([...countsByQueue].map(([queue, counts]) => [
32
+ queue,
33
+ {
34
+ waiting: counts.waiting,
35
+ prioritized: counts.prioritized,
36
+ delayed: counts.delayed,
37
+ active: counts.active,
38
+ dlq: counts.failed,
39
+ },
40
+ ]));
41
+ return generatePrometheusMetrics(this.getStats(), this.workerManager, this.webhookManager, perQueueStats, {
42
+ storageDegraded: isStorageDegraded(storageStatus),
31
43
  storageDiskFull: storageStatus.diskFull,
32
44
  ...(this.storage && { sqliteDatabaseSizeBytes: this.storage.getSize() }),
33
45
  processHeapUsedBytes: memory.heapUsed,
@@ -4,6 +4,13 @@ export declare class QueueManagerQueries extends QueueManagerLocks {
4
4
  getJob(jobId: JobId): Promise<Job | null>;
5
5
  getJobState(jobId: JobId): Promise<string>;
6
6
  getResult(jobId: JobId): unknown;
7
+ /** Distinguish a completed generation from a valid undefined result. */
8
+ getCompletionAsync(jobId: JobId): Promise<{
9
+ found: boolean;
10
+ result: unknown;
11
+ }>;
12
+ /** Async result port used by transports; memory and SQLite remain synchronous internally. */
13
+ getResultAsync(jobId: JobId): Promise<unknown>;
7
14
  getChildrenValues(parentJobId: JobId): Promise<Record<string, unknown>>;
8
15
  updateJobParent(childJobId: JobId, parentJobId: JobId): Promise<void>;
9
16
  getJobByCustomId(customId: string): Job | null;
@@ -14,6 +14,15 @@ export class QueueManagerQueries extends QueueManagerLocks {
14
14
  getResult(jobId) {
15
15
  return queryOps.getJobResult(jobId, this.contextFactory.getQueryContext());
16
16
  }
17
+ /** Distinguish a completed generation from a valid undefined result. */
18
+ async getCompletionAsync(jobId) {
19
+ const found = this.completedJobs.has(jobId);
20
+ return { found, result: found ? this.getResult(jobId) : undefined };
21
+ }
22
+ /** Async result port used by transports; memory and SQLite remain synchronous internally. */
23
+ async getResultAsync(jobId) {
24
+ return (await this.getCompletionAsync(jobId)).result;
25
+ }
17
26
  async getChildrenValues(parentJobId) {
18
27
  const job = await this.getJob(parentJobId);
19
28
  if (!job?.childrenIds || job.childrenIds.length === 0)
@@ -12,7 +12,7 @@ export declare class QueueManagerServices extends QueueManagerObservability {
12
12
  setDashboardEmit(fn: (event: string, data: Record<string, unknown>) => void): void;
13
13
  emitDashboardEvent(event: string, data: Record<string, unknown>): void;
14
14
  subscribe(callback: (event: JobEvent) => void): () => void;
15
- waitForJobCompletion(jobId: JobId, timeoutMs: number): Promise<boolean>;
15
+ waitForJobCompletion(jobId: JobId, timeoutMs: number, signal?: AbortSignal): Promise<boolean>;
16
16
  registerWorker(name: string, queues: string[], concurrency?: number, options?: CreateWorkerOptions): import("../../domain/types/worker").Worker;
17
17
  unregisterWorker(workerId: string): boolean;
18
18
  unregisterWorkersByClientId(clientId: string): number;
@@ -1,7 +1,9 @@
1
+ import { assertValidCronInput } from '../../infrastructure/scheduler/cron/validation';
1
2
  import { shardIndex } from '../../shared/hash';
2
3
  import { QueueManagerObservability } from './observability';
3
4
  export class QueueManagerServices extends QueueManagerObservability {
4
5
  addCron(input) {
6
+ assertValidCronInput(input);
5
7
  if (input.preventOverlap) {
6
8
  this.removeOrphanedCronJob(input.queue, input.uniqueKey ?? `cron:${input.name}`);
7
9
  }
@@ -54,8 +56,8 @@ export class QueueManagerServices extends QueueManagerObservability {
54
56
  subscribe(callback) {
55
57
  return this.eventsManager.subscribe(callback);
56
58
  }
57
- waitForJobCompletion(jobId, timeoutMs) {
58
- return this.eventsManager.waitForJobCompletion(jobId, timeoutMs);
59
+ waitForJobCompletion(jobId, timeoutMs, signal) {
60
+ return this.eventsManager.waitForJobCompletion(jobId, timeoutMs, signal);
59
61
  }
60
62
  registerWorker(name, queues, concurrency, options) {
61
63
  const worker = this.workerManager.register(name, queues, concurrency, options);
@@ -1,6 +1,7 @@
1
1
  import { Shard } from '../../domain/queue/shard';
2
2
  import { SqliteStorage } from '../../infrastructure/persistence/sqlite';
3
3
  import { CronScheduler } from '../../infrastructure/scheduler/cronScheduler';
4
+ import { assertPersistedCronsSupported } from '../../infrastructure/scheduler/cron/persisted';
4
5
  import { RWLock } from '../../shared/lock';
5
6
  import { SHARD_COUNT } from '../../shared/hash';
6
7
  import { BoundedMap, BoundedSet, LRUMap } from '../../shared/lru';
@@ -83,6 +84,20 @@ export class QueueManagerState {
83
84
  constructor(config = {}) {
84
85
  this.config = { ...DEFAULT_CONFIG, ...config };
85
86
  this.storage = config.dataPath ? new SqliteStorage({ path: config.dataPath }) : null;
87
+ let persistedCrons;
88
+ try {
89
+ persistedCrons = this.storage?.loadCronJobs() ?? [];
90
+ assertPersistedCronsSupported(persistedCrons);
91
+ }
92
+ catch (error) {
93
+ try {
94
+ this.storage?.close();
95
+ }
96
+ catch {
97
+ // Preserve the read/validation error that made construction fail.
98
+ }
99
+ throw error;
100
+ }
86
101
  this.telemetryJournal = new QueueTelemetryJournal(this.storage, this.config.maxQueueEvents, this.config.maxMetricDataPoints);
87
102
  this.completedJobsData = new BoundedMap(this.config.maxCompletedJobs);
88
103
  this.completedJobs = new BoundedSet(this.config.maxCompletedJobs, (id) => {
@@ -138,7 +153,7 @@ export class QueueManagerState {
138
153
  }
139
154
  this.recoveryStats = { queues: this.queueNamesCache.size, jobs: this.jobIndex.size };
140
155
  if (this.storage)
141
- this.cronScheduler.load(this.storage.loadCronJobs());
156
+ this.cronScheduler.load(persistedCrons);
142
157
  this.backgroundTaskHandles = bgTasks.startBackgroundTasks(this.contextFactory.getBackgroundContext(), this.cronScheduler);
143
158
  }
144
159
  }
@@ -3,7 +3,7 @@
3
3
  * Provides system metrics and memory compaction utilities
4
4
  */
5
5
  import type { StatsContext } from './types';
6
- export { getAllQueueJobCounts, getPerQueueStats, getQueueJobCounts, } from './queueStatsAggregator';
6
+ export { getAllQueueJobCounts, getPerQueueStats, getQueueJobCounts } from './queueStatsAggregator';
7
7
  export type { PerQueueStats, QueueJobCounts } from './queueStatsAggregator';
8
8
  export interface QueueStats {
9
9
  waiting: number;
@@ -3,7 +3,7 @@
3
3
  * Provides system metrics and memory compaction utilities
4
4
  */
5
5
  import { SHARD_COUNT } from '../shared/hash';
6
- export { getAllQueueJobCounts, getPerQueueStats, getQueueJobCounts, } from './queueStatsAggregator';
6
+ export { getAllQueueJobCounts, getPerQueueStats, getQueueJobCounts } from './queueStatsAggregator';
7
7
  /**
8
8
  * Get queue statistics - uses running counters + priority scan
9
9
  */
@@ -106,5 +106,5 @@ export async function runServer(args, showHelp) {
106
106
  const mergedConfig = applyCliFlags(fileConfig, flags);
107
107
  const config = resolveServerConfig(mergedConfig);
108
108
  // Same full server as the bare `bunqueue` entry (shared bootstrap)
109
- bootServer(mergedConfig, config);
109
+ await bootServer(mergedConfig, config);
110
110
  }
@@ -41,11 +41,11 @@ export class QueueEvents extends EventEmitter {
41
41
  this.queueKey = (options.prefixKey ?? '') + name;
42
42
  this.start();
43
43
  }
44
- // biome-ignore lint/suspicious/noExplicitAny: EventEmitter's fallback overload requires any[].
44
+ // oxlint-disable-next-line typescript/no-explicit-any -- EventEmitter's fallback overload requires any[]
45
45
  on(event, listener) {
46
46
  return super.on(event, listener);
47
47
  }
48
- // biome-ignore lint/suspicious/noExplicitAny: EventEmitter's fallback overload requires any[].
48
+ // oxlint-disable-next-line typescript/no-explicit-any -- EventEmitter's fallback overload requires any[]
49
49
  once(event, listener) {
50
50
  return super.once(event, listener);
51
51
  }
@@ -129,7 +129,6 @@ export class FlowProducer extends EventEmitter {
129
129
  return plan.roots.map((root) => this.buildPlannedNode(root, snapshotsById));
130
130
  }
131
131
  /** Get a flow tree starting from a job (BullMQ v5 compatible). */
132
- // biome-ignore lint/suspicious/useAwait: preserves the public Promise return contract.
133
132
  async getFlow(opts) {
134
133
  return readFlow({
135
134
  embedded: this.embedded,