bunqueue 2.8.60 → 2.9.2

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 (427) hide show
  1. package/README.md +114 -78
  2. package/dist/application/background/dlq.js +2 -0
  3. package/dist/application/background/recovery/active.d.ts +1 -0
  4. package/dist/application/background/recovery/active.js +12 -0
  5. package/dist/application/background/recovery/index.js +3 -1
  6. package/dist/application/background/recovery/pending.js +1 -0
  7. package/dist/application/cleanupTasks.js +4 -16
  8. package/dist/application/contextFactory.js +8 -0
  9. package/dist/application/dlqManager.d.ts +10 -0
  10. package/dist/application/dlqManager.js +48 -9
  11. package/dist/application/dlqRetry.js +60 -38
  12. package/dist/application/eventsManager.d.ts +9 -2
  13. package/dist/application/eventsManager.js +106 -55
  14. package/dist/application/operations/ackHelpers.d.ts +1 -4
  15. package/dist/application/operations/ackHelpers.js +39 -14
  16. package/dist/application/operations/flowPush.js +1 -0
  17. package/dist/application/operations/flowValidation.js +4 -4
  18. package/dist/application/operations/jobManagement.d.ts +4 -0
  19. package/dist/application/operations/jobMoveOperations.js +9 -4
  20. package/dist/application/operations/pull.d.ts +7 -2
  21. package/dist/application/operations/pull.js +15 -57
  22. package/dist/application/operations/pullFinalization.d.ts +6 -0
  23. package/dist/application/operations/pullFinalization.js +69 -0
  24. package/dist/application/operations/pullStateTransition.d.ts +8 -7
  25. package/dist/application/operations/pullStateTransition.js +25 -18
  26. package/dist/application/operations/push.js +3 -0
  27. package/dist/application/operations/pushBatch.js +14 -7
  28. package/dist/application/operations/pushContext.d.ts +2 -1
  29. package/dist/application/postgres-queue-manager/batchSnapshot.d.ts +16 -0
  30. package/dist/application/postgres-queue-manager/batchSnapshot.js +17 -0
  31. package/dist/application/postgres-queue-manager/cloud.d.ts +30 -0
  32. package/dist/application/postgres-queue-manager/cloud.js +55 -0
  33. package/dist/application/postgres-queue-manager/config.d.ts +5 -0
  34. package/dist/application/postgres-queue-manager/config.js +1 -0
  35. package/dist/application/postgres-queue-manager/control.d.ts +30 -0
  36. package/dist/application/postgres-queue-manager/control.js +210 -0
  37. package/dist/application/postgres-queue-manager/deferredWrites.d.ts +13 -0
  38. package/dist/application/postgres-queue-manager/deferredWrites.js +60 -0
  39. package/dist/application/postgres-queue-manager/delivery.d.ts +20 -0
  40. package/dist/application/postgres-queue-manager/delivery.js +83 -0
  41. package/dist/application/postgres-queue-manager/groupQueries.d.ts +10 -0
  42. package/dist/application/postgres-queue-manager/groupQueries.js +40 -0
  43. package/dist/application/postgres-queue-manager/lease.d.ts +13 -0
  44. package/dist/application/postgres-queue-manager/lease.js +88 -0
  45. package/dist/application/postgres-queue-manager/lifetimeMetrics.d.ts +32 -0
  46. package/dist/application/postgres-queue-manager/lifetimeMetrics.js +53 -0
  47. package/dist/application/postgres-queue-manager/maintenance.d.ts +14 -0
  48. package/dist/application/postgres-queue-manager/maintenance.js +100 -0
  49. package/dist/application/postgres-queue-manager/operationGate.d.ts +26 -0
  50. package/dist/application/postgres-queue-manager/operationGate.js +96 -0
  51. package/dist/application/postgres-queue-manager/operations.d.ts +25 -0
  52. package/dist/application/postgres-queue-manager/operations.js +194 -0
  53. package/dist/application/postgres-queue-manager/projectionRefreshes.d.ts +43 -0
  54. package/dist/application/postgres-queue-manager/projectionRefreshes.js +170 -0
  55. package/dist/application/postgres-queue-manager/queries.d.ts +142 -0
  56. package/dist/application/postgres-queue-manager/queries.js +231 -0
  57. package/dist/application/postgres-queue-manager/relationships.d.ts +10 -0
  58. package/dist/application/postgres-queue-manager/relationships.js +45 -0
  59. package/dist/application/postgres-queue-manager/services.d.ts +31 -0
  60. package/dist/application/postgres-queue-manager/services.js +149 -0
  61. package/dist/application/postgres-queue-manager/snapshot.d.ts +51 -0
  62. package/dist/application/postgres-queue-manager/snapshot.js +236 -0
  63. package/dist/application/postgres-queue-manager/snapshotViews.d.ts +15 -0
  64. package/dist/application/postgres-queue-manager/snapshotViews.js +100 -0
  65. package/dist/application/postgres-queue-manager/startupEventBuffer.d.ts +12 -0
  66. package/dist/application/postgres-queue-manager/startupEventBuffer.js +36 -0
  67. package/dist/application/postgres-queue-manager/state.d.ts +47 -0
  68. package/dist/application/postgres-queue-manager/state.js +273 -0
  69. package/dist/application/postgres-queue-manager/terminalDelivery.d.ts +20 -0
  70. package/dist/application/postgres-queue-manager/terminalDelivery.js +100 -0
  71. package/dist/application/postgresQueueManager.d.ts +2 -0
  72. package/dist/application/postgresQueueManager.js +1 -0
  73. package/dist/application/queue-manager/control.js +1 -0
  74. package/dist/application/queue-manager/delivery.d.ts +5 -4
  75. package/dist/application/queue-manager/delivery.js +15 -8
  76. package/dist/application/queue-manager/flow-failures.js +4 -0
  77. package/dist/application/queue-manager/limits.d.ts +13 -0
  78. package/dist/application/queue-manager/limits.js +65 -0
  79. package/dist/application/queue-manager/observability.js +15 -3
  80. package/dist/application/queue-manager/queries.d.ts +7 -0
  81. package/dist/application/queue-manager/queries.js +9 -0
  82. package/dist/application/queue-manager/services.d.ts +1 -1
  83. package/dist/application/queue-manager/services.js +4 -2
  84. package/dist/application/queue-manager/state.js +17 -2
  85. package/dist/application/queueTelemetryJournal.d.ts +2 -0
  86. package/dist/application/queueTelemetryJournal.js +23 -0
  87. package/dist/application/types/ack.d.ts +3 -1
  88. package/dist/cli/commandRouter.d.ts +1 -1
  89. package/dist/cli/commands/server.js +1 -1
  90. package/dist/client/flowPush.js +6 -0
  91. package/dist/client/forwarder.d.ts +6 -4
  92. package/dist/client/forwarder.js +5 -3
  93. package/dist/client/groupId.d.ts +1 -0
  94. package/dist/client/groupId.js +1 -0
  95. package/dist/client/index.d.ts +1 -1
  96. package/dist/client/jobHelpers.js +1 -0
  97. package/dist/client/queue/dlq.d.ts +2 -0
  98. package/dist/client/queue/dlq.js +14 -0
  99. package/dist/client/queue/dlqOps.d.ts +2 -0
  100. package/dist/client/queue/dlqOps.js +4 -0
  101. package/dist/client/queue/helpers.js +2 -0
  102. package/dist/client/queue/operations/add/bulk.js +4 -4
  103. package/dist/client/queue/operations/add/payload.d.ts +1 -0
  104. package/dist/client/queue/operations/add/payload.js +7 -1
  105. package/dist/client/queue/operations/add/single.js +3 -3
  106. package/dist/client/queue/operations/groups.d.ts +21 -0
  107. package/dist/client/queue/operations/groups.js +88 -0
  108. package/dist/client/queue/runtime/configuration.d.ts +4 -0
  109. package/dist/client/queue/runtime/configuration.js +8 -0
  110. package/dist/client/queue/runtime/queries.d.ts +13 -0
  111. package/dist/client/queue/runtime/queries.js +31 -0
  112. package/dist/client/queue/runtime/state.d.ts +4 -0
  113. package/dist/client/queue/runtime/state.js +1 -0
  114. package/dist/client/types/index.d.ts +2 -2
  115. package/dist/client/types/options.d.ts +4 -0
  116. package/dist/client/types/worker.d.ts +8 -0
  117. package/dist/client/worker/runtime/execution.js +4 -8
  118. package/dist/client/worker/runtime/options.js +3 -0
  119. package/dist/client/worker/runtime/polling.d.ts +1 -0
  120. package/dist/client/worker/runtime/polling.js +9 -0
  121. package/dist/client/worker/types/options.d.ts +2 -1
  122. package/dist/client/worker/workerPull.d.ts +2 -0
  123. package/dist/client/worker/workerPull.js +6 -4
  124. package/dist/config/resolve.d.ts +14 -0
  125. package/dist/config/resolve.js +50 -5
  126. package/dist/config/types.d.ts +18 -0
  127. package/dist/domain/job/groupFifoOrder.d.ts +9 -0
  128. package/dist/domain/job/groupFifoOrder.js +26 -0
  129. package/dist/domain/queue/dlqShard.d.ts +2 -0
  130. package/dist/domain/queue/dlqShard.js +16 -0
  131. package/dist/domain/queue/groupLimiterManager.d.ts +23 -0
  132. package/dist/domain/queue/groupLimiterManager.js +107 -0
  133. package/dist/domain/queue/groupScheduler.d.ts +31 -0
  134. package/dist/domain/queue/groupScheduler.js +256 -0
  135. package/dist/domain/queue/groupSchedulerOrder.d.ts +6 -0
  136. package/dist/domain/queue/groupSchedulerOrder.js +30 -0
  137. package/dist/domain/queue/priorityQueue.d.ts +13 -23
  138. package/dist/domain/queue/priorityQueue.js +53 -42
  139. package/dist/domain/queue/shard/dlq.d.ts +1 -0
  140. package/dist/domain/queue/shard/dlq.js +3 -0
  141. package/dist/domain/queue/shard/keys.d.ts +1 -0
  142. package/dist/domain/queue/shard/keys.js +25 -2
  143. package/dist/domain/queue/shard/lifecycle.js +4 -0
  144. package/dist/domain/queue/shard/limits.d.ts +20 -1
  145. package/dist/domain/queue/shard/limits.js +56 -0
  146. package/dist/domain/queue/shard/state.d.ts +5 -0
  147. package/dist/domain/queue/shard/state.js +9 -1
  148. package/dist/domain/types/commands/core.d.ts +3 -0
  149. package/dist/domain/types/commands/dlq.d.ts +5 -0
  150. package/dist/domain/types/commands/limits.d.ts +41 -0
  151. package/dist/domain/types/commands/union.d.ts +1 -1
  152. package/dist/domain/types/cron.d.ts +5 -0
  153. package/dist/domain/types/cron.js +14 -3
  154. package/dist/domain/types/dlq.d.ts +1 -1
  155. package/dist/domain/types/dlq.js +1 -2
  156. package/dist/domain/types/group.d.ts +21 -0
  157. package/dist/domain/types/group.js +78 -0
  158. package/dist/domain/types/jobs/model.d.ts +1 -1
  159. package/dist/domain/types/priorityQueue.d.ts +1 -0
  160. package/dist/infrastructure/cloud/commandHandler.js +5 -3
  161. package/dist/infrastructure/cloud/commands/integrations.js +11 -11
  162. package/dist/infrastructure/cloud/commands/jobs.js +48 -40
  163. package/dist/infrastructure/cloud/commands/queues.js +61 -75
  164. package/dist/infrastructure/cloud/queueAdapter/local.d.ts +41 -0
  165. package/dist/infrastructure/cloud/queueAdapter/local.js +187 -0
  166. package/dist/infrastructure/cloud/queueAdapter/postgres.d.ts +42 -0
  167. package/dist/infrastructure/cloud/queueAdapter/postgres.js +188 -0
  168. package/dist/infrastructure/cloud/queueAdapter/registry.d.ts +4 -0
  169. package/dist/infrastructure/cloud/queueAdapter/registry.js +15 -0
  170. package/dist/infrastructure/cloud/queueAdapter/types.d.ts +87 -0
  171. package/dist/infrastructure/cloud/queueAdapter/types.js +1 -0
  172. package/dist/infrastructure/cloud/snapshot/analytics.d.ts +2 -0
  173. package/dist/infrastructure/cloud/snapshot/analytics.js +7 -0
  174. package/dist/infrastructure/cloud/snapshot/collector.d.ts +4 -0
  175. package/dist/infrastructure/cloud/snapshot/collector.js +39 -1
  176. package/dist/infrastructure/cloud/snapshot/config.d.ts +3 -0
  177. package/dist/infrastructure/cloud/snapshot/config.js +43 -0
  178. package/dist/infrastructure/cloud/snapshot/jobs.d.ts +3 -0
  179. package/dist/infrastructure/cloud/snapshot/jobs.js +32 -1
  180. package/dist/infrastructure/cloud/snapshotCollector.js +20 -35
  181. package/dist/infrastructure/cloud/snapshotHelpers.d.ts +3 -3
  182. package/dist/infrastructure/cloud/snapshotHelpers.js +3 -3
  183. package/dist/infrastructure/cloud/statsRefresh.js +2 -1
  184. package/dist/infrastructure/cloud/types/command.d.ts +2 -2
  185. package/dist/infrastructure/persistence/jobOptionsBlob.d.ts +1 -0
  186. package/dist/infrastructure/persistence/jobOptionsBlob.js +10 -2
  187. package/dist/infrastructure/persistence/migrations.js +11 -0
  188. package/dist/infrastructure/persistence/postgres/admission.d.ts +18 -0
  189. package/dist/infrastructure/persistence/postgres/admission.js +196 -0
  190. package/dist/infrastructure/persistence/postgres/admissionParent.d.ts +5 -0
  191. package/dist/infrastructure/persistence/postgres/admissionParent.js +35 -0
  192. package/dist/infrastructure/persistence/postgres/admissionResult.d.ts +9 -0
  193. package/dist/infrastructure/persistence/postgres/admissionResult.js +1 -0
  194. package/dist/infrastructure/persistence/postgres/admissionStore.d.ts +12 -0
  195. package/dist/infrastructure/persistence/postgres/admissionStore.js +101 -0
  196. package/dist/infrastructure/persistence/postgres/advisoryLocks.d.ts +2 -0
  197. package/dist/infrastructure/persistence/postgres/advisoryLocks.js +13 -0
  198. package/dist/infrastructure/persistence/postgres/batchAdmission.d.ts +11 -0
  199. package/dist/infrastructure/persistence/postgres/batchAdmission.js +128 -0
  200. package/dist/infrastructure/persistence/postgres/batchCompletion.d.ts +4 -0
  201. package/dist/infrastructure/persistence/postgres/batchCompletion.js +174 -0
  202. package/dist/infrastructure/persistence/postgres/batchEvents.d.ts +14 -0
  203. package/dist/infrastructure/persistence/postgres/batchEvents.js +72 -0
  204. package/dist/infrastructure/persistence/postgres/brokerSessions.d.ts +14 -0
  205. package/dist/infrastructure/persistence/postgres/brokerSessions.js +94 -0
  206. package/dist/infrastructure/persistence/postgres/claimBatch.d.ts +14 -0
  207. package/dist/infrastructure/persistence/postgres/claimBatch.js +69 -0
  208. package/dist/infrastructure/persistence/postgres/claimSelection.d.ts +11 -0
  209. package/dist/infrastructure/persistence/postgres/claimSelection.js +140 -0
  210. package/dist/infrastructure/persistence/postgres/claims.d.ts +10 -0
  211. package/dist/infrastructure/persistence/postgres/claims.js +153 -0
  212. package/dist/infrastructure/persistence/postgres/cloudReadModel.d.ts +26 -0
  213. package/dist/infrastructure/persistence/postgres/cloudReadModel.js +123 -0
  214. package/dist/infrastructure/persistence/postgres/codec.d.ts +30 -0
  215. package/dist/infrastructure/persistence/postgres/codec.js +82 -0
  216. package/dist/infrastructure/persistence/postgres/completionEvents.d.ts +11 -0
  217. package/dist/infrastructure/persistence/postgres/completionEvents.js +21 -0
  218. package/dist/infrastructure/persistence/postgres/completionLifecycle.d.ts +11 -0
  219. package/dist/infrastructure/persistence/postgres/completionLifecycle.js +145 -0
  220. package/dist/infrastructure/persistence/postgres/completionOutcome.d.ts +4 -0
  221. package/dist/infrastructure/persistence/postgres/completionOutcome.js +112 -0
  222. package/dist/infrastructure/persistence/postgres/completionQueries.d.ts +10 -0
  223. package/dist/infrastructure/persistence/postgres/completionQueries.js +87 -0
  224. package/dist/infrastructure/persistence/postgres/connection.d.ts +3 -0
  225. package/dist/infrastructure/persistence/postgres/connection.js +15 -0
  226. package/dist/infrastructure/persistence/postgres/context.d.ts +28 -0
  227. package/dist/infrastructure/persistence/postgres/context.js +74 -0
  228. package/dist/infrastructure/persistence/postgres/control.d.ts +23 -0
  229. package/dist/infrastructure/persistence/postgres/control.js +105 -0
  230. package/dist/infrastructure/persistence/postgres/crons.d.ts +18 -0
  231. package/dist/infrastructure/persistence/postgres/crons.js +205 -0
  232. package/dist/infrastructure/persistence/postgres/deduplication.d.ts +9 -0
  233. package/dist/infrastructure/persistence/postgres/deduplication.js +47 -0
  234. package/dist/infrastructure/persistence/postgres/dependencyDestruction.d.ts +14 -0
  235. package/dist/infrastructure/persistence/postgres/dependencyDestruction.js +74 -0
  236. package/dist/infrastructure/persistence/postgres/dependencyPromotion.d.ts +29 -0
  237. package/dist/infrastructure/persistence/postgres/dependencyPromotion.js +212 -0
  238. package/dist/infrastructure/persistence/postgres/destructiveMutations.d.ts +4 -0
  239. package/dist/infrastructure/persistence/postgres/destructiveMutations.js +111 -0
  240. package/dist/infrastructure/persistence/postgres/dlqLifecycle.d.ts +13 -0
  241. package/dist/infrastructure/persistence/postgres/dlqLifecycle.js +184 -0
  242. package/dist/infrastructure/persistence/postgres/dlqMaintenance.d.ts +6 -0
  243. package/dist/infrastructure/persistence/postgres/dlqMaintenance.js +36 -0
  244. package/dist/infrastructure/persistence/postgres/dlqRetryPlan.d.ts +21 -0
  245. package/dist/infrastructure/persistence/postgres/dlqRetryPlan.js +92 -0
  246. package/dist/infrastructure/persistence/postgres/eventCatchupCursors.d.ts +32 -0
  247. package/dist/infrastructure/persistence/postgres/eventCatchupCursors.js +66 -0
  248. package/dist/infrastructure/persistence/postgres/eventCommitGc.d.ts +27 -0
  249. package/dist/infrastructure/persistence/postgres/eventCommitGc.js +62 -0
  250. package/dist/infrastructure/persistence/postgres/eventJournal.d.ts +18 -0
  251. package/dist/infrastructure/persistence/postgres/eventJournal.js +76 -0
  252. package/dist/infrastructure/persistence/postgres/eventJournalSchema.d.ts +5 -0
  253. package/dist/infrastructure/persistence/postgres/eventJournalSchema.js +267 -0
  254. package/dist/infrastructure/persistence/postgres/eventPruneWatermarks.d.ts +26 -0
  255. package/dist/infrastructure/persistence/postgres/eventPruneWatermarks.js +129 -0
  256. package/dist/infrastructure/persistence/postgres/eventRetention.d.ts +18 -0
  257. package/dist/infrastructure/persistence/postgres/eventRetention.js +76 -0
  258. package/dist/infrastructure/persistence/postgres/events.d.ts +45 -0
  259. package/dist/infrastructure/persistence/postgres/events.js +276 -0
  260. package/dist/infrastructure/persistence/postgres/expiry.d.ts +3 -0
  261. package/dist/infrastructure/persistence/postgres/expiry.js +74 -0
  262. package/dist/infrastructure/persistence/postgres/flowFailures.d.ts +17 -0
  263. package/dist/infrastructure/persistence/postgres/flowFailures.js +199 -0
  264. package/dist/infrastructure/persistence/postgres/groupClaims.d.ts +15 -0
  265. package/dist/infrastructure/persistence/postgres/groupClaims.js +95 -0
  266. package/dist/infrastructure/persistence/postgres/groupSchema.d.ts +2 -0
  267. package/dist/infrastructure/persistence/postgres/groupSchema.js +155 -0
  268. package/dist/infrastructure/persistence/postgres/groupSchemaFingerprint.d.ts +3 -0
  269. package/dist/infrastructure/persistence/postgres/groupSchemaFingerprint.js +127 -0
  270. package/dist/infrastructure/persistence/postgres/groupStateRetention.d.ts +3 -0
  271. package/dist/infrastructure/persistence/postgres/groupStateRetention.js +93 -0
  272. package/dist/infrastructure/persistence/postgres/groups.d.ts +11 -0
  273. package/dist/infrastructure/persistence/postgres/groups.js +117 -0
  274. package/dist/infrastructure/persistence/postgres/jobData.d.ts +3 -0
  275. package/dist/infrastructure/persistence/postgres/jobData.js +32 -0
  276. package/dist/infrastructure/persistence/postgres/leaseRelease.d.ts +9 -0
  277. package/dist/infrastructure/persistence/postgres/leaseRelease.js +120 -0
  278. package/dist/infrastructure/persistence/postgres/leaseRenewal.d.ts +4 -0
  279. package/dist/infrastructure/persistence/postgres/leaseRenewal.js +35 -0
  280. package/dist/infrastructure/persistence/postgres/lifetimeMetrics.d.ts +15 -0
  281. package/dist/infrastructure/persistence/postgres/lifetimeMetrics.js +46 -0
  282. package/dist/infrastructure/persistence/postgres/lifetimeMetricsFinalizer.d.ts +4 -0
  283. package/dist/infrastructure/persistence/postgres/lifetimeMetricsFinalizer.js +13 -0
  284. package/dist/infrastructure/persistence/postgres/logs.d.ts +6 -0
  285. package/dist/infrastructure/persistence/postgres/logs.js +70 -0
  286. package/dist/infrastructure/persistence/postgres/maintenance.d.ts +6 -0
  287. package/dist/infrastructure/persistence/postgres/maintenance.js +138 -0
  288. package/dist/infrastructure/persistence/postgres/maintenanceFlights.d.ts +14 -0
  289. package/dist/infrastructure/persistence/postgres/maintenanceFlights.js +66 -0
  290. package/dist/infrastructure/persistence/postgres/metricWrites.d.ts +9 -0
  291. package/dist/infrastructure/persistence/postgres/metricWrites.js +94 -0
  292. package/dist/infrastructure/persistence/postgres/mutations.d.ts +9 -0
  293. package/dist/infrastructure/persistence/postgres/mutations.js +171 -0
  294. package/dist/infrastructure/persistence/postgres/outcomes.d.ts +4 -0
  295. package/dist/infrastructure/persistence/postgres/outcomes.js +194 -0
  296. package/dist/infrastructure/persistence/postgres/policies.d.ts +11 -0
  297. package/dist/infrastructure/persistence/postgres/policies.js +18 -0
  298. package/dist/infrastructure/persistence/postgres/postCommitMaintenance.d.ts +17 -0
  299. package/dist/infrastructure/persistence/postgres/postCommitMaintenance.js +117 -0
  300. package/dist/infrastructure/persistence/postgres/promotion.d.ts +3 -0
  301. package/dist/infrastructure/persistence/postgres/promotion.js +43 -0
  302. package/dist/infrastructure/persistence/postgres/queries.d.ts +22 -0
  303. package/dist/infrastructure/persistence/postgres/queries.js +152 -0
  304. package/dist/infrastructure/persistence/postgres/queueDestruction.d.ts +3 -0
  305. package/dist/infrastructure/persistence/postgres/queueDestruction.js +158 -0
  306. package/dist/infrastructure/persistence/postgres/queueLifecycle.d.ts +10 -0
  307. package/dist/infrastructure/persistence/postgres/queueLifecycle.js +60 -0
  308. package/dist/infrastructure/persistence/postgres/rateLimit.d.ts +6 -0
  309. package/dist/infrastructure/persistence/postgres/rateLimit.js +10 -0
  310. package/dist/infrastructure/persistence/postgres/readModels.d.ts +32 -0
  311. package/dist/infrastructure/persistence/postgres/readModels.js +72 -0
  312. package/dist/infrastructure/persistence/postgres/recovery.d.ts +3 -0
  313. package/dist/infrastructure/persistence/postgres/recovery.js +178 -0
  314. package/dist/infrastructure/persistence/postgres/relationships.d.ts +9 -0
  315. package/dist/infrastructure/persistence/postgres/relationships.js +201 -0
  316. package/dist/infrastructure/persistence/postgres/removeUnprocessedChildren.d.ts +4 -0
  317. package/dist/infrastructure/persistence/postgres/removeUnprocessedChildren.js +241 -0
  318. package/dist/infrastructure/persistence/postgres/repeatMutations.d.ts +5 -0
  319. package/dist/infrastructure/persistence/postgres/repeatMutations.js +37 -0
  320. package/dist/infrastructure/persistence/postgres/runtime.d.ts +45 -0
  321. package/dist/infrastructure/persistence/postgres/runtime.js +238 -0
  322. package/dist/infrastructure/persistence/postgres/runtimeConfig.d.ts +21 -0
  323. package/dist/infrastructure/persistence/postgres/runtimeConfig.js +39 -0
  324. package/dist/infrastructure/persistence/postgres/schema.d.ts +4 -0
  325. package/dist/infrastructure/persistence/postgres/schema.js +261 -0
  326. package/dist/infrastructure/persistence/postgres/schemaInitialization.d.ts +3 -0
  327. package/dist/infrastructure/persistence/postgres/schemaInitialization.js +226 -0
  328. package/dist/infrastructure/persistence/postgres/serialAdmission.d.ts +6 -0
  329. package/dist/infrastructure/persistence/postgres/serialAdmission.js +96 -0
  330. package/dist/infrastructure/persistence/postgres/snapshotBudget.d.ts +3 -0
  331. package/dist/infrastructure/persistence/postgres/snapshotBudget.js +83 -0
  332. package/dist/infrastructure/persistence/postgres/storageHealth.d.ts +10 -0
  333. package/dist/infrastructure/persistence/postgres/storageHealth.js +29 -0
  334. package/dist/infrastructure/persistence/postgres/store.d.ts +100 -0
  335. package/dist/infrastructure/persistence/postgres/store.js +180 -0
  336. package/dist/infrastructure/persistence/postgres/telemetry.d.ts +8 -0
  337. package/dist/infrastructure/persistence/postgres/telemetry.js +100 -0
  338. package/dist/infrastructure/persistence/postgres/terminal.d.ts +8 -0
  339. package/dist/infrastructure/persistence/postgres/terminal.js +137 -0
  340. package/dist/infrastructure/persistence/postgres/transactionRetry.d.ts +6 -0
  341. package/dist/infrastructure/persistence/postgres/transactionRetry.js +42 -0
  342. package/dist/infrastructure/persistence/postgres/types.d.ts +176 -0
  343. package/dist/infrastructure/persistence/postgres/types.js +1 -0
  344. package/dist/infrastructure/persistence/postgres/workers.d.ts +15 -0
  345. package/dist/infrastructure/persistence/postgres/workers.js +126 -0
  346. package/dist/infrastructure/persistence/postgres.d.ts +2 -0
  347. package/dist/infrastructure/persistence/postgres.js +1 -0
  348. package/dist/infrastructure/persistence/schema.d.ts +2 -2
  349. package/dist/infrastructure/persistence/schema.js +12 -1
  350. package/dist/infrastructure/persistence/sqlite/control.d.ts +14 -0
  351. package/dist/infrastructure/persistence/sqlite/control.js +69 -0
  352. package/dist/infrastructure/persistence/sqlite/jobs.d.ts +12 -0
  353. package/dist/infrastructure/persistence/sqlite/jobs.js +38 -0
  354. package/dist/infrastructure/persistence/sqlite/telemetry.d.ts +2 -1
  355. package/dist/infrastructure/persistence/sqlite/telemetry.js +5 -64
  356. package/dist/infrastructure/persistence/sqlite/telemetryWrites.d.ts +4 -0
  357. package/dist/infrastructure/persistence/sqlite/telemetryWrites.js +123 -0
  358. package/dist/infrastructure/persistence/sqliteSerializer.js +2 -0
  359. package/dist/infrastructure/scheduler/cron/persisted.d.ts +5 -0
  360. package/dist/infrastructure/scheduler/cron/persisted.js +27 -0
  361. package/dist/infrastructure/scheduler/cron/runtime.js +5 -10
  362. package/dist/infrastructure/scheduler/cron/validation.d.ts +3 -0
  363. package/dist/infrastructure/scheduler/cron/validation.js +11 -0
  364. package/dist/infrastructure/scheduler/cronParser.d.ts +1 -1
  365. package/dist/infrastructure/scheduler/cronParser.js +144 -11
  366. package/dist/infrastructure/server/bootstrap.d.ts +2 -3
  367. package/dist/infrastructure/server/bootstrap.js +33 -59
  368. package/dist/infrastructure/server/errors.d.ts +4 -0
  369. package/dist/infrastructure/server/errors.js +54 -0
  370. package/dist/infrastructure/server/handler-routes/control.d.ts +5 -5
  371. package/dist/infrastructure/server/handler-routes/control.js +16 -1
  372. package/dist/infrastructure/server/handler-routes/monitoring.d.ts +2 -2
  373. package/dist/infrastructure/server/handler.js +9 -11
  374. package/dist/infrastructure/server/handlers/advanced/dependencies.js +7 -6
  375. package/dist/infrastructure/server/handlers/advanced/jobs.js +19 -6
  376. package/dist/infrastructure/server/handlers/advanced/queue.d.ts +9 -9
  377. package/dist/infrastructure/server/handlers/advanced/queue.js +91 -27
  378. package/dist/infrastructure/server/handlers/core.d.ts +0 -5
  379. package/dist/infrastructure/server/handlers/core.js +47 -49
  380. package/dist/infrastructure/server/handlers/cron.d.ts +4 -4
  381. package/dist/infrastructure/server/handlers/cron.js +60 -59
  382. package/dist/infrastructure/server/handlers/dashboard.d.ts +1 -1
  383. package/dist/infrastructure/server/handlers/dashboard.js +21 -8
  384. package/dist/infrastructure/server/handlers/dlq.d.ts +6 -3
  385. package/dist/infrastructure/server/handlers/dlq.js +35 -9
  386. package/dist/infrastructure/server/handlers/flow.js +2 -1
  387. package/dist/infrastructure/server/handlers/groups.d.ts +11 -0
  388. package/dist/infrastructure/server/handlers/groups.js +55 -0
  389. package/dist/infrastructure/server/handlers/management.d.ts +5 -5
  390. package/dist/infrastructure/server/handlers/management.js +36 -9
  391. package/dist/infrastructure/server/handlers/monitoring/health.d.ts +5 -5
  392. package/dist/infrastructure/server/handlers/monitoring/health.js +45 -16
  393. package/dist/infrastructure/server/handlers/monitoring/operations.d.ts +1 -1
  394. package/dist/infrastructure/server/handlers/monitoring/operations.js +8 -1
  395. package/dist/infrastructure/server/handlers/monitoring/workers.d.ts +3 -3
  396. package/dist/infrastructure/server/handlers/monitoring/workers.js +31 -7
  397. package/dist/infrastructure/server/handlers/pushBatchValidation.d.ts +3 -1
  398. package/dist/infrastructure/server/handlers/pushBatchValidation.js +56 -8
  399. package/dist/infrastructure/server/handlers/query.d.ts +1 -1
  400. package/dist/infrastructure/server/handlers/query.js +5 -4
  401. package/dist/infrastructure/server/http.js +2 -2
  402. package/dist/infrastructure/server/httpDashboardEndpoints.d.ts +1 -1
  403. package/dist/infrastructure/server/httpDashboardEndpoints.js +19 -6
  404. package/dist/infrastructure/server/httpEndpoints.js +18 -7
  405. package/dist/infrastructure/server/httpRouteQueues.js +11 -1
  406. package/dist/infrastructure/server/protocol/validation.d.ts +1 -0
  407. package/dist/infrastructure/server/protocol/validation.js +1 -0
  408. package/dist/infrastructure/server/protocol.d.ts +1 -1
  409. package/dist/infrastructure/server/protocol.js +1 -1
  410. package/dist/infrastructure/server/shutdownCoordinator.d.ts +24 -0
  411. package/dist/infrastructure/server/shutdownCoordinator.js +106 -0
  412. package/dist/infrastructure/server/sseHandler.js +8 -3
  413. package/dist/infrastructure/server/storageAdapter.d.ts +29 -0
  414. package/dist/infrastructure/server/storageAdapter.js +61 -0
  415. package/dist/infrastructure/server/storageManager.d.ts +12 -0
  416. package/dist/infrastructure/server/storageManager.js +102 -0
  417. package/dist/infrastructure/server/tcp.js +2 -3
  418. package/dist/infrastructure/server/ws/snapshots.d.ts +1 -1
  419. package/dist/infrastructure/server/ws/snapshots.js +19 -4
  420. package/dist/infrastructure/server/wsHandler.js +10 -5
  421. package/dist/main.js +1 -1
  422. package/dist/mcp/backend/embedded/services.js +2 -1
  423. package/dist/mcp/index.d.ts +2 -2
  424. package/dist/mcp/index.js +2 -2
  425. package/dist/shared/storageHealth.d.ts +9 -0
  426. package/dist/shared/storageHealth.js +12 -0
  427. package/package.json +75 -65
@@ -2,10 +2,11 @@
2
2
  * Pull Operations
3
3
  * Job pull logic with timeout support
4
4
  */
5
+ import { assertGroupPullOptions } from '../../domain/types/group';
5
6
  import { withWriteLock } from '../../shared/lock';
6
- import { shardIndex, processingShardIndex } from '../../shared/hash';
7
+ import { shardIndex } from '../../shared/hash';
7
8
  import { latencyTracker } from '../latencyTracker';
8
- import { throughputTracker } from '../throughputTracker';
9
+ import { finalizeProcessing, finalizeProcessingBatch } from './pullFinalization';
9
10
  import { createDequeueScan, requeueJob, restoreParkedJobs, tryDequeueNextJob, } from './pullStateTransition';
10
11
  /** Wait until either a notification arrives, the next delay matures, or the pull deadline. */
11
12
  async function waitForNextCandidate(options) {
@@ -14,64 +15,18 @@ async function waitForNextCandidate(options) {
14
15
  const untilNextRun = nextRunAt === null ? remaining : Math.max(1, nextRunAt - now);
15
16
  await shard.waitForJob(queue, Math.min(remaining, untilNextRun), signal);
16
17
  }
17
- /**
18
- * Finish the handoff of a dequeued job: persist active state and broadcast.
19
- *
20
- * The job was ALREADY inserted into processingShards and jobIndex was flipped
21
- * to 'processing' inside the dequeue critical section (tryDequeueNextJob),
22
- * atomically with the queue pop, so readers never see a stale 'queue'
23
- * location. Only the bookkeeping that may follow an await happens here.
24
- *
25
- * Returns false when the job is no longer in processingShards: a management
26
- * op (discardJob, moveJobToDelayed, obliterate) claimed it between the
27
- * dequeue and this call. The claimer owns the job now; the pull must NOT
28
- * deliver it to a worker nor mark it active.
29
- */
30
- function finalizeProcessing(job, queue, ctx) {
31
- const procIdx = processingShardIndex(job.id);
32
- if (!ctx.processingShards[procIdx].has(job.id))
33
- return false;
34
- const now = Date.now();
35
- try {
36
- ctx.storage?.markActive(job.id, job.startedAt ?? now, job.timeline);
37
- }
38
- catch {
39
- // Non-fatal: job is already in processingShards (in-memory source of truth).
40
- // On crash, SQLite recovery will handle the stale state.
41
- }
42
- ctx.totalPulled.value++;
43
- throughputTracker.pullRate.increment();
44
- ctx.broadcast({
45
- eventType: 'pulled',
46
- queue,
47
- jobId: job.id,
48
- timestamp: now,
49
- });
50
- return true;
51
- }
52
- /**
53
- * Finish the handoff for a batch of dequeued jobs.
54
- * Returns the jobs actually delivered (claimed jobs are skipped, see above).
55
- */
56
- function finalizeProcessingBatch(jobs, queue, ctx) {
57
- const delivered = [];
58
- for (const job of jobs) {
59
- if (finalizeProcessing(job, queue, ctx))
60
- delivered.push(job);
61
- }
62
- return delivered;
63
- }
64
18
  /**
65
19
  * Pull next job from queue
66
20
  */
67
- export async function pullJob(queue, timeoutMs, ctx, signal) {
21
+ export async function pullJob(queue, timeoutMs, ctx, signal, groupOptions) {
22
+ assertGroupPullOptions(groupOptions);
68
23
  const startNs = Bun.nanoseconds();
69
24
  const deadline = timeoutMs > 0 ? Date.now() + timeoutMs : 0;
70
25
  const idx = shardIndex(queue);
71
26
  while (true) {
72
27
  if (signal?.aborted)
73
28
  return null;
74
- const attempt = await tryPullFromShard(queue, idx, ctx, signal);
29
+ const attempt = await tryPullFromShard(queue, idx, ctx, signal, groupOptions);
75
30
  const job = attempt.job;
76
31
  if (job) {
77
32
  if (signal?.aborted) {
@@ -112,7 +67,7 @@ export async function pullJob(queue, timeoutMs, ctx, signal) {
112
67
  /**
113
68
  * Try to pull a job from a specific shard
114
69
  */
115
- async function tryPullFromShard(queue, idx, ctx, signal) {
70
+ async function tryPullFromShard(queue, idx, ctx, signal, groupOptions) {
116
71
  return await withWriteLock(ctx.shardLocks[idx], () => {
117
72
  if (signal?.aborted)
118
73
  return { job: null, nextRunAt: null };
@@ -122,7 +77,7 @@ async function tryPullFromShard(queue, idx, ctx, signal) {
122
77
  return { job: null, nextRunAt: null };
123
78
  }
124
79
  const now = Date.now();
125
- const scan = createDequeueScan();
80
+ const scan = createDequeueScan(groupOptions);
126
81
  try {
127
82
  const result = tryDequeueNextJob(shard, queue, now, ctx, scan);
128
83
  return result.status === 'job'
@@ -137,14 +92,16 @@ async function tryPullFromShard(queue, idx, ctx, signal) {
137
92
  /**
138
93
  * Pull multiple jobs from queue
139
94
  */
140
- export async function pullJobBatch(queue, count, timeoutMs, ctx, signal) {
95
+ export async function pullJobBatch(queue, count, timeoutMs, ctx, options = {}) {
96
+ assertGroupPullOptions(options.group);
97
+ const { signal } = options;
141
98
  const startNs = Bun.nanoseconds();
142
99
  const deadline = timeoutMs > 0 ? Date.now() + timeoutMs : 0;
143
100
  const idx = shardIndex(queue);
144
101
  while (true) {
145
102
  if (signal?.aborted)
146
103
  return [];
147
- const attempt = await tryPullBatchFromShard(queue, idx, count, ctx, signal);
104
+ const attempt = await tryPullBatchFromShard(queue, idx, count, ctx, options);
148
105
  const jobs = attempt.jobs;
149
106
  if (jobs.length > 0) {
150
107
  if (signal?.aborted) {
@@ -194,7 +151,8 @@ export async function pullJobBatch(queue, count, timeoutMs, ctx, signal) {
194
151
  /**
195
152
  * Try to pull multiple jobs from a shard
196
153
  */
197
- async function tryPullBatchFromShard(queue, idx, count, ctx, signal) {
154
+ async function tryPullBatchFromShard(queue, idx, count, ctx, options) {
155
+ const { signal, group: groupOptions } = options;
198
156
  return await withWriteLock(ctx.shardLocks[idx], () => {
199
157
  if (signal?.aborted)
200
158
  return { jobs: [], nextRunAt: null };
@@ -204,7 +162,7 @@ async function tryPullBatchFromShard(queue, idx, count, ctx, signal) {
204
162
  if (state.paused)
205
163
  return { jobs, nextRunAt: null };
206
164
  const now = Date.now();
207
- const scan = createDequeueScan();
165
+ const scan = createDequeueScan(groupOptions);
208
166
  try {
209
167
  while (jobs.length < count) {
210
168
  const result = tryDequeueNextJob(shard, queue, now, ctx, scan);
@@ -0,0 +1,6 @@
1
+ import type { Job } from '../../domain/types/job';
2
+ import type { PullContext } from './pullStateTransition';
3
+ /** Persist and publish a single processing handoff. */
4
+ export declare function finalizeProcessing(job: Job, queue: string, ctx: PullContext): boolean;
5
+ /** Persist and publish all processing handoffs with one durable state transaction. */
6
+ export declare function finalizeProcessingBatch(jobs: Job[], queue: string, ctx: PullContext): Job[];
@@ -0,0 +1,69 @@
1
+ import { processingShardIndex } from '../../shared/hash';
2
+ import { throughputTracker } from '../throughputTracker';
3
+ function createPulledEvent(job, queue, ctx) {
4
+ if (!ctx.processingShards[processingShardIndex(job.id)].has(job.id))
5
+ return null;
6
+ return {
7
+ eventType: 'pulled',
8
+ queue,
9
+ jobId: job.id,
10
+ timestamp: Date.now(),
11
+ };
12
+ }
13
+ function persistActive(job, fallbackStartedAt, ctx) {
14
+ try {
15
+ ctx.storage?.markActive(job.id, job.startedAt ?? fallbackStartedAt, job.timeline);
16
+ }
17
+ catch {
18
+ // Non-fatal: the in-memory processing map remains authoritative.
19
+ }
20
+ }
21
+ function persistActiveBatch(jobs, events, ctx) {
22
+ const storage = ctx.storage;
23
+ if (!storage || jobs.length === 0)
24
+ return;
25
+ try {
26
+ storage.markActiveBatch(jobs.map((job, index) => ({
27
+ jobId: job.id,
28
+ startedAt: job.startedAt ?? events[index].timestamp,
29
+ timeline: job.timeline,
30
+ })));
31
+ }
32
+ catch {
33
+ for (let index = 0; index < jobs.length; index++) {
34
+ persistActive(jobs[index], events[index].timestamp, ctx);
35
+ }
36
+ }
37
+ }
38
+ /** Persist and publish a single processing handoff. */
39
+ export function finalizeProcessing(job, queue, ctx) {
40
+ const event = createPulledEvent(job, queue, ctx);
41
+ if (!event)
42
+ return false;
43
+ persistActive(job, event.timestamp, ctx);
44
+ ctx.totalPulled.value++;
45
+ throughputTracker.pullRate.increment();
46
+ ctx.broadcast(event);
47
+ return true;
48
+ }
49
+ /** Persist and publish all processing handoffs with one durable state transaction. */
50
+ export function finalizeProcessingBatch(jobs, queue, ctx) {
51
+ const delivered = [];
52
+ const events = [];
53
+ for (const job of jobs) {
54
+ const event = createPulledEvent(job, queue, ctx);
55
+ if (!event)
56
+ continue;
57
+ delivered.push(job);
58
+ events.push(event);
59
+ }
60
+ persistActiveBatch(delivered, events, ctx);
61
+ ctx.totalPulled.value += BigInt(delivered.length);
62
+ throughputTracker.pullRate.increment(delivered.length);
63
+ if (ctx.broadcastBatch)
64
+ ctx.broadcastBatch(events);
65
+ else
66
+ for (const event of events)
67
+ ctx.broadcast(event);
68
+ return delivered;
69
+ }
@@ -3,7 +3,8 @@
3
3
  */
4
4
  import type { Shard } from '../../domain/queue/shard';
5
5
  import { type Job, type JobId } from '../../domain/types/job';
6
- import type { EventType, JobLocation } from '../../domain/types/queue';
6
+ import type { GroupPullOptions } from '../../domain/types/group';
7
+ import type { EventType, JobEvent, JobLocation } from '../../domain/types/queue';
7
8
  import type { SqliteStorage } from '../../infrastructure/persistence/sqlite';
8
9
  import type { RWLock } from '../../shared/lock';
9
10
  /** Dependencies shared by the single and batch pull paths. */
@@ -23,11 +24,13 @@ export interface PullContext {
23
24
  jobId: JobId;
24
25
  timestamp: number;
25
26
  }) => void;
27
+ broadcastBatch?: (events: readonly JobEvent[]) => void;
26
28
  dashboardEmit?: (event: string, data: Record<string, unknown>) => void;
27
29
  }
28
30
  export interface DequeueScan {
29
31
  parked: Job[];
30
32
  nextRunAt: number | null;
33
+ groupOptions?: GroupPullOptions;
31
34
  }
32
35
  export type DequeueResult = {
33
36
  status: 'job';
@@ -35,15 +38,13 @@ export type DequeueResult = {
35
38
  } | {
36
39
  status: 'stop';
37
40
  };
38
- export declare function createDequeueScan(): DequeueScan;
41
+ export declare function createDequeueScan(groupOptions?: GroupPullOptions): DequeueScan;
39
42
  /** Restore physical heap membership without changing logical queue state. */
40
43
  export declare function restoreParkedJobs(shard: Shard, queue: string, scan: DequeueScan): void;
41
44
  /**
42
- * Remove the best eligible job while retaining ineligible roots in `scan`.
43
- *
44
- * A batch reuses one scan, because readiness cannot change while the synchronous
45
- * shard critical section is held: time is fixed and active FIFO groups only
46
- * grow. Its parked jobs therefore need to be restored only once after the batch.
45
+ * Remove the best eligible job from the shard's secondary group indexes.
46
+ * A batch reuses the same fixed timestamp and group defaults while its
47
+ * synchronous shard critical section is held.
47
48
  */
48
49
  export declare function tryDequeueNextJob(shard: Shard, queue: string, now: number, ctx: PullContext, scan: DequeueScan): DequeueResult;
49
50
  /** Restore a dequeued job when its handoff to the worker cannot complete. */
@@ -4,8 +4,8 @@
4
4
  import { isExpired, isReady, MAX_TIMELINE_ENTRIES, } from '../../domain/types/job';
5
5
  import { processingShardIndex } from '../../shared/hash';
6
6
  import { withWriteLock } from '../../shared/lock';
7
- export function createDequeueScan() {
8
- return { parked: [], nextRunAt: null };
7
+ export function createDequeueScan(groupOptions) {
8
+ return { parked: [], nextRunAt: null, groupOptions };
9
9
  }
10
10
  /** Restore physical heap membership without changing logical queue state. */
11
11
  export function restoreParkedJobs(shard, queue, scan) {
@@ -15,23 +15,30 @@ export function restoreParkedJobs(shard, queue, scan) {
15
15
  scan.parked.length = 0;
16
16
  }
17
17
  /**
18
- * Remove the best eligible job while retaining ineligible roots in `scan`.
19
- *
20
- * A batch reuses one scan, because readiness cannot change while the synchronous
21
- * shard critical section is held: time is fixed and active FIFO groups only
22
- * grow. Its parked jobs therefore need to be restored only once after the batch.
18
+ * Remove the best eligible job from the shard's secondary group indexes.
19
+ * A batch reuses the same fixed timestamp and group defaults while its
20
+ * synchronous shard critical section is held.
23
21
  */
24
22
  export function tryDequeueNextJob(shard, queue, now, ctx, scan) {
25
23
  const priorityQueue = shard.getQueue(queue);
26
24
  while (true) {
27
- const job = priorityQueue.peek();
25
+ const grouped = shard.hasGroupScheduler(queue);
26
+ const candidate = grouped
27
+ ? shard.peekGroupCandidate(queue, now, scan.groupOptions)
28
+ : { job: priorityQueue.peek(), nextRunAt: null };
29
+ if (grouped)
30
+ scan.nextRunAt = candidate.nextRunAt;
31
+ const job = candidate.job;
28
32
  if (!job)
29
33
  return { status: 'stop' };
30
34
  if (isExpired(job, now)) {
31
35
  // Persistence is removed first so a failed durable delete leaves the
32
36
  // in-memory job available for a later attempt.
33
37
  ctx.storage?.deleteJob(job.id);
34
- priorityQueue.pop();
38
+ if (grouped)
39
+ priorityQueue.remove(job.id);
40
+ else
41
+ priorityQueue.pop();
35
42
  shard.decrementQueued(job.id);
36
43
  ctx.jobIndex.delete(job.id);
37
44
  ctx.dashboardEmit?.('job:expired', {
@@ -42,19 +49,13 @@ export function tryDequeueNextJob(shard, queue, now, ctx, scan) {
42
49
  });
43
50
  continue;
44
51
  }
45
- if (!isReady(job, now)) {
52
+ if (!grouped && !isReady(job, now)) {
46
53
  const delayed = priorityQueue.pop();
47
54
  if (delayed)
48
55
  scan.parked.push(delayed);
49
56
  scan.nextRunAt = scan.nextRunAt === null ? job.runAt : Math.min(scan.nextRunAt, job.runAt);
50
57
  continue;
51
58
  }
52
- if (job.groupId && shard.isGroupActive(queue, job.groupId)) {
53
- const blocked = priorityQueue.pop();
54
- if (blocked)
55
- scan.parked.push(blocked);
56
- continue;
57
- }
58
59
  // Capacity is consumed only after an eligible job has been found.
59
60
  if (!shard.tryAcquireConcurrency(queue)) {
60
61
  ctx.dashboardEmit?.('concurrency:rejected', { queue });
@@ -65,14 +66,20 @@ export function tryDequeueNextJob(shard, queue, now, ctx, scan) {
65
66
  ctx.dashboardEmit?.('ratelimit:rejected', { queue });
66
67
  return { status: 'stop' };
67
68
  }
68
- const dequeued = priorityQueue.pop();
69
+ if (job.groupId && !shard.acquireGroup(queue, job.groupId, scan.groupOptions, now)) {
70
+ shard.releaseConcurrency(queue);
71
+ return { status: 'stop' };
72
+ }
73
+ const dequeued = grouped ? priorityQueue.remove(job.id) : priorityQueue.pop();
69
74
  if (!dequeued) {
75
+ if (job.groupId)
76
+ shard.releaseGroup(queue, job.groupId);
70
77
  shard.releaseConcurrency(queue);
71
78
  return { status: 'stop' };
72
79
  }
73
80
  shard.decrementQueued(dequeued.id);
74
81
  if (dequeued.groupId)
75
- shard.activateGroup(queue, dequeued.groupId);
82
+ shard.advanceGroup(queue, dequeued.groupId);
76
83
  dequeued.startedAt = now;
77
84
  dequeued.lastHeartbeat = now;
78
85
  if (dequeued.timeline.length < MAX_TIMELINE_ENTRIES) {
@@ -3,6 +3,7 @@
3
3
  * Single-job push logic and stable batch re-export
4
4
  */
5
5
  import { createJob } from '../../domain/types/job';
6
+ import { assertOptionalGroupId } from '../../domain/types/group';
6
7
  import { shardIndex } from '../../shared/hash';
7
8
  import { latencyTracker } from '../latencyTracker';
8
9
  import { throughputTracker } from '../throughputTracker';
@@ -20,6 +21,7 @@ export { pushJobBatch } from './pushBatch';
20
21
  * NOTE: customId check happens INSIDE lock to prevent race conditions
21
22
  */
22
23
  export async function pushJob(queue, input, ctx) {
24
+ assertOptionalGroupId(input.groupId);
23
25
  validateRepeatJobInput(input);
24
26
  const startNs = Bun.nanoseconds();
25
27
  const idx = shardIndex(queue);
@@ -58,6 +60,7 @@ export async function pushJob(queue, input, ctx) {
58
60
  };
59
61
  return;
60
62
  }
63
+ shard.assignGroupFifoOrder(job);
61
64
  const target = { queue, shard, shardIdx: idx };
62
65
  let storageHandled = false;
63
66
  if (linkParent) {
@@ -1,4 +1,5 @@
1
1
  import { createJob, normalizeJobPayload, } from '../../domain/types/job';
2
+ import { assertOptionalGroupId } from '../../domain/types/group';
2
3
  import { shardIndex } from '../../shared/hash';
3
4
  import { releaseDependencyCompletionPins } from '../dependencyCompletions';
4
5
  import { latencyTracker } from '../latencyTracker';
@@ -13,6 +14,7 @@ import { withPushWriteLocks } from './pushLocks';
13
14
  /** Push an ordered batch while preserving its accepted-prefix contract. */
14
15
  export async function pushJobBatch(queue, inputs, ctx) {
15
16
  for (const input of inputs) {
17
+ assertOptionalGroupId(input.groupId);
16
18
  validateRepeatJobInput(input);
17
19
  normalizeJobPayload(input);
18
20
  }
@@ -43,6 +45,7 @@ export async function pushJobBatch(queue, inputs, ctx) {
43
45
  resultIds.push(dedupResult.existingId);
44
46
  continue;
45
47
  }
48
+ shard.assignGroupFifoOrder(job);
46
49
  const target = { queue, shard, shardIdx: idx };
47
50
  let storageHandled = false;
48
51
  if (linkParent) {
@@ -111,13 +114,17 @@ export async function pushJobBatch(queue, inputs, ctx) {
111
114
  }
112
115
  ctx.totalPushed.value += BigInt(acceptedJobs.length);
113
116
  throughputTracker.pushRate.increment(acceptedJobs.length);
114
- for (const job of acceptedJobs) {
115
- ctx.broadcast({
116
- eventType: 'pushed',
117
- queue: job.queue,
118
- jobId: job.id,
119
- timestamp: now,
120
- });
117
+ const events = acceptedJobs.map((job) => ({
118
+ eventType: 'pushed',
119
+ queue: job.queue,
120
+ jobId: job.id,
121
+ timestamp: now,
122
+ }));
123
+ if (ctx.broadcastBatch)
124
+ ctx.broadcastBatch(events);
125
+ else {
126
+ for (const event of events)
127
+ ctx.broadcast(event);
121
128
  }
122
129
  }
123
130
  if (jobsToInsert.length > 0)
@@ -1,7 +1,7 @@
1
1
  import type { Shard } from '../../domain/queue/shard';
2
2
  import type { Job, JobId } from '../../domain/types/job';
3
3
  import type { JobLocation } from '../../domain/types/queue';
4
- import { type EventType } from '../../domain/types/queue';
4
+ import { type EventType, type JobEvent } from '../../domain/types/queue';
5
5
  import type { SqliteStorage } from '../../infrastructure/persistence/sqlite';
6
6
  import type { RWLock } from '../../shared/lock';
7
7
  import type { MapLike, SetLike } from '../../shared/lru';
@@ -34,6 +34,7 @@ export interface PushContext {
34
34
  jobId: JobId;
35
35
  timestamp: number;
36
36
  }) => void;
37
+ broadcastBatch?: (events: readonly JobEvent[]) => void;
37
38
  dashboardEmit?: (event: string, data: Record<string, unknown>) => void;
38
39
  registerQueueName?: (queue: string) => void;
39
40
  }
@@ -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,30 @@
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
+ setGroupRateLimit(queue: string, groupId: string, max: number, duration: number): Promise<void>;
7
+ removeGroupRateLimit(queue: string, groupId: string): Promise<number>;
8
+ setGroupConcurrency(queue: string, groupId: string, concurrency: number): Promise<void>;
9
+ removeGroupConcurrency(queue: string, groupId: string): Promise<number>;
10
+ pause(queue: string): void;
11
+ resume(queue: string): void;
12
+ pauseDurable(queue: string, paused: boolean): Promise<void>;
13
+ drain(queue: string): number;
14
+ drainDurable(queue: string): Promise<number>;
15
+ obliterate(queue: string): void;
16
+ obliterateDurable(queue: string): Promise<void>;
17
+ setRateLimit(queue: string, limit: number, durationMs?: number, ttlMs?: number): void;
18
+ clearRateLimit(queue: string): void;
19
+ setConcurrency(queue: string, limit: number): void;
20
+ clearConcurrency(queue: string): void;
21
+ setRateLimitDurable(queue: string, limit: number | null, durationMs: number | null, ttlMs?: number | null): Promise<void>;
22
+ setConcurrencyDurable(queue: string, limit: number | null): Promise<void>;
23
+ setStallConfig(queue: string, patch: Record<string, unknown>): void;
24
+ getStallConfig(queue: string): StallConfig;
25
+ setStallConfigDurable(queue: string, patch: Record<string, unknown>): Promise<void>;
26
+ setDlqConfig(queue: string, patch: Record<string, unknown>): void;
27
+ getDlqConfig(queue: string): DlqConfig;
28
+ setDlqConfigDurable(queue: string, patch: Record<string, unknown>): Promise<void>;
29
+ private setLocalQueueState;
30
+ }