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
@@ -0,0 +1,226 @@
1
+ import { postgresAdvisoryLockName } from './advisoryLocks';
2
+ import { databaseNow } from './context';
3
+ import { POSTGRES_ASSIGN_EVENT_COMMIT_BODY, POSTGRES_REGISTER_EVENT_ROWS_BODY, POSTGRES_REGISTER_WATERMARK_ROWS_BODY, } from './eventJournalSchema';
4
+ import { POSTGRES_SCHEMA, POSTGRES_SCHEMA_VERSION } from './schema';
5
+ import { hasCurrentPostgresGroupSchema } from './groupSchemaFingerprint';
6
+ const EXPECTED_FUNCTION_BODIES = new Map([
7
+ ['bunqueue_register_event_rows', POSTGRES_REGISTER_EVENT_ROWS_BODY],
8
+ ['bunqueue_register_watermark_rows', POSTGRES_REGISTER_WATERMARK_ROWS_BODY],
9
+ ['bunqueue_assign_event_commit', POSTGRES_ASSIGN_EVENT_COMMIT_BODY],
10
+ ]);
11
+ function normalizeFunctionBody(value) {
12
+ return value.replaceAll(/\s+/g, ' ').trim();
13
+ }
14
+ async function hasCurrentSchema(tx) {
15
+ const [table] = await tx `
16
+ SELECT to_regclass('bunqueue_schema_migrations') IS NOT NULL AS exists
17
+ `;
18
+ if (!table.exists)
19
+ return false;
20
+ const [migration] = await tx `
21
+ SELECT
22
+ EXISTS (
23
+ SELECT 1 FROM bunqueue_schema_migrations
24
+ WHERE version = ${POSTGRES_SCHEMA_VERSION}
25
+ ) AS current,
26
+ MAX(version) AS latest
27
+ FROM bunqueue_schema_migrations
28
+ `;
29
+ const latest = Number(migration.latest ?? 0);
30
+ if (latest > POSTGRES_SCHEMA_VERSION) {
31
+ throw new Error(`PostgreSQL schema version ${latest} is newer than supported version ${POSTGRES_SCHEMA_VERSION}`);
32
+ }
33
+ if (!migration.current)
34
+ return false;
35
+ const [objects] = await tx `
36
+ WITH expected_columns(table_name, column_name, type_name, not_null, default_kind) AS (
37
+ VALUES
38
+ ('bunqueue_events', 'transaction_id', 'bigint', TRUE, 'transaction'),
39
+ ('bunqueue_event_commits', 'namespace', 'text', TRUE, 'none'),
40
+ ('bunqueue_event_commits', 'transaction_id', 'bigint', TRUE, 'none'),
41
+ ('bunqueue_event_commits', 'commit_seq', 'bigint', FALSE, 'none'),
42
+ ('bunqueue_event_prune_watermarks', 'transaction_id', 'bigint', TRUE, 'transaction'),
43
+ ('bunqueue_event_prune_watermarks', 'commit_seq', 'bigint', FALSE, 'none'),
44
+ ('bunqueue_event_prune_watermarks', 'pruned_commit_seq', 'bigint', TRUE, 'zero'),
45
+ ('bunqueue_event_prune_watermarks', 'self_pruned_commit_seq', 'bigint', TRUE, 'zero'),
46
+ ('bunqueue_event_prune_watermarks', 'prunes_current_transaction', 'boolean', TRUE, 'false'),
47
+ ('bunqueue_brokers', 'session_id', 'text', FALSE, 'none'),
48
+ ('bunqueue_jobs', 'lease_broker_session_id', 'text', FALSE, 'none'),
49
+ ('bunqueue_workers', 'broker_session_id', 'text', FALSE, 'none'),
50
+ ('bunqueue_queue_state', 'group_sequence', 'bigint', TRUE, 'zero')
51
+ ), expected_indexes(
52
+ index_name, table_name, columns, descending, predicate, is_unique
53
+ ) AS (
54
+ VALUES
55
+ ('bunqueue_events_transaction_idx', 'bunqueue_events',
56
+ ARRAY['namespace', 'transaction_id', 'id'], ARRAY[FALSE, FALSE, FALSE], '', FALSE),
57
+ ('bunqueue_event_commits_replay_idx', 'bunqueue_event_commits',
58
+ ARRAY['namespace', 'commit_seq', 'transaction_id'], ARRAY[FALSE, FALSE, FALSE],
59
+ 'commit_seqisnotnull', FALSE),
60
+ ('bunqueue_event_prune_watermarks_commit_idx', 'bunqueue_event_prune_watermarks',
61
+ ARRAY['namespace', 'queue', 'commit_seq'], ARRAY[FALSE, FALSE, TRUE],
62
+ 'commit_seqisnotnull', FALSE),
63
+ ('bunqueue_event_prune_watermarks_pending_commit_idx',
64
+ 'bunqueue_event_prune_watermarks', ARRAY['namespace', 'transaction_id'],
65
+ ARRAY[FALSE, FALSE], 'commit_seqisnull', FALSE),
66
+ ('bunqueue_event_prune_watermarks_transaction_idx',
67
+ 'bunqueue_event_prune_watermarks', ARRAY['namespace', 'transaction_id'],
68
+ ARRAY[FALSE, FALSE], '', FALSE),
69
+ ('bunqueue_jobs_broker_session_lease_idx', 'bunqueue_jobs',
70
+ ARRAY['namespace', 'lease_broker_id', 'lease_broker_session_id', 'id'],
71
+ ARRAY[FALSE, FALSE, FALSE, FALSE], 'state=''active''::text', FALSE),
72
+ ('bunqueue_workers_broker_session_idx', 'bunqueue_workers',
73
+ ARRAY['namespace', 'broker_id', 'broker_session_id', 'client_id'],
74
+ ARRAY[FALSE, FALSE, FALSE, FALSE], '', FALSE),
75
+ ('bunqueue_jobs_live_unique_key_idx', 'bunqueue_jobs',
76
+ ARRAY['namespace', 'queue', 'unique_key'], ARRAY[FALSE, FALSE, FALSE],
77
+ 'unique_keyisnotnullandstate=anyarray[''waiting''::text,''prioritized''::text,' ||
78
+ '''delayed''::text,''waiting-children''::text,''active''::text]', TRUE)
79
+ ), expected_triggers(
80
+ trigger_name, table_name, function_name, trigger_type, new_table,
81
+ is_constraint, is_deferrable
82
+ ) AS (
83
+ VALUES
84
+ ('bunqueue_events_register_commit', 'bunqueue_events',
85
+ 'bunqueue_register_event_rows', 4, 'new_event_rows', FALSE, FALSE),
86
+ ('bunqueue_watermarks_insert_register_commit', 'bunqueue_event_prune_watermarks',
87
+ 'bunqueue_register_watermark_rows', 4, 'new_watermark_rows', FALSE, FALSE),
88
+ ('bunqueue_watermarks_update_register_commit', 'bunqueue_event_prune_watermarks',
89
+ 'bunqueue_register_watermark_rows', 16, 'new_watermark_rows', FALSE, FALSE),
90
+ ('bunqueue_assign_event_commit', 'bunqueue_event_commits',
91
+ 'bunqueue_assign_event_commit', 5, NULL, TRUE, TRUE)
92
+ )
93
+ SELECT
94
+ EXISTS (
95
+ SELECT 1 FROM pg_sequence
96
+ WHERE seqrelid = to_regclass('bunqueue_event_commit_seq')
97
+ AND seqtypid = to_regtype('bigint')
98
+ AND seqincrement = 1 AND seqmin = 1
99
+ AND seqmax = 9223372036854775807
100
+ AND NOT seqcycle
101
+ AND seqcache = 1
102
+ )
103
+ AND to_regclass('bunqueue_event_commits') IS NOT NULL
104
+ AND (
105
+ SELECT COALESCE(bool_and(COALESCE(
106
+ attribute.atttypid = to_regtype(expected.type_name)
107
+ AND attribute.attnotnull = expected.not_null
108
+ AND CASE expected.default_kind
109
+ WHEN 'transaction' THEN regexp_replace(
110
+ lower(COALESCE(pg_get_expr(defaults.adbin, defaults.adrelid), '')),
111
+ '[()[:space:]]', '', 'g'
112
+ ) = 'pg_current_xact_id::text::bigint'
113
+ WHEN 'zero' THEN regexp_replace(
114
+ lower(COALESCE(pg_get_expr(defaults.adbin, defaults.adrelid), '')),
115
+ '[()[:space:]]', '', 'g'
116
+ ) IN ('0', '0::bigint')
117
+ WHEN 'false' THEN regexp_replace(
118
+ lower(COALESCE(pg_get_expr(defaults.adbin, defaults.adrelid), '')),
119
+ '[()[:space:]]', '', 'g'
120
+ ) IN ('false', 'false::boolean')
121
+ ELSE defaults.oid IS NULL
122
+ END,
123
+ FALSE
124
+ )), FALSE)
125
+ FROM expected_columns AS expected
126
+ LEFT JOIN pg_attribute AS attribute
127
+ ON attribute.attrelid = to_regclass(expected.table_name)
128
+ AND attribute.attname = expected.column_name AND NOT attribute.attisdropped
129
+ LEFT JOIN pg_attrdef AS defaults
130
+ ON defaults.adrelid = attribute.attrelid AND defaults.adnum = attribute.attnum
131
+ )
132
+ AND (
133
+ SELECT COALESCE(bool_and(COALESCE(
134
+ indexes.indrelid = to_regclass(expected.table_name)
135
+ AND indexes.indisvalid AND indexes.indisready
136
+ AND indexes.indisunique = expected.is_unique
137
+ AND NOT indexes.indisexclusion
138
+ AND indexes.indnkeyatts = cardinality(expected.columns)
139
+ AND indexes.indnatts = indexes.indnkeyatts
140
+ AND indexes.indexprs IS NULL
141
+ AND access_method.amname = 'btree'
142
+ AND ARRAY(
143
+ SELECT attribute.attname::text
144
+ FROM unnest(indexes.indkey::smallint[]) WITH ORDINALITY AS key(attnum, position)
145
+ JOIN pg_attribute AS attribute
146
+ ON attribute.attrelid = indexes.indrelid AND attribute.attnum = key.attnum
147
+ ORDER BY key.position
148
+ ) = expected.columns
149
+ AND ARRAY(
150
+ SELECT (option & 1) = 1
151
+ FROM unnest(indexes.indoption::smallint[]) WITH ORDINALITY AS ordering(option, position)
152
+ ORDER BY ordering.position
153
+ ) = expected.descending
154
+ AND regexp_replace(
155
+ lower(COALESCE(pg_get_expr(indexes.indpred, indexes.indrelid), '')),
156
+ '[()[:space:]]', '', 'g'
157
+ ) = expected.predicate,
158
+ FALSE
159
+ )), FALSE)
160
+ FROM expected_indexes AS expected
161
+ LEFT JOIN pg_class AS index_class ON index_class.oid = to_regclass(expected.index_name)
162
+ LEFT JOIN pg_index AS indexes ON indexes.indexrelid = index_class.oid
163
+ LEFT JOIN pg_am AS access_method ON access_method.oid = index_class.relam
164
+ )
165
+ AND (
166
+ SELECT COALESCE(bool_and(EXISTS (
167
+ SELECT 1 FROM pg_trigger AS trigger
168
+ WHERE trigger.tgrelid = to_regclass(expected.table_name)
169
+ AND trigger.tgname = expected.trigger_name
170
+ AND trigger.tgfoid = to_regprocedure(expected.function_name || '()')
171
+ AND NOT trigger.tgisinternal AND trigger.tgenabled = 'O'
172
+ AND trigger.tgtype = expected.trigger_type
173
+ AND trigger.tgnewtable IS NOT DISTINCT FROM expected.new_table
174
+ AND trigger.tgoldtable IS NULL
175
+ AND trigger.tgqual IS NULL AND trigger.tgnargs = 0
176
+ AND (trigger.tgconstraint <> 0) = expected.is_constraint
177
+ AND trigger.tgdeferrable = expected.is_deferrable
178
+ AND trigger.tginitdeferred = expected.is_deferrable
179
+ )), FALSE)
180
+ FROM expected_triggers AS expected
181
+ ) AS valid
182
+ `;
183
+ if (!objects.valid)
184
+ return false;
185
+ if (!(await hasCurrentPostgresGroupSchema(tx)))
186
+ return false;
187
+ const functions = await tx `
188
+ SELECT expected.name, functions.prosrc AS body,
189
+ functions.prorettype = to_regtype('trigger')
190
+ AND language.lanname = 'plpgsql'
191
+ AND functions.prokind = 'f'
192
+ AND functions.provolatile = 'v'
193
+ AND functions.proparallel = 'u'
194
+ AND NOT functions.prosecdef
195
+ AND NOT functions.proisstrict
196
+ AND functions.proconfig IS NULL
197
+ AND NOT functions.proleakproof AS canonical
198
+ FROM unnest(${tx.array([...EXPECTED_FUNCTION_BODIES.keys()], 'TEXT')}) AS expected(name)
199
+ LEFT JOIN pg_proc AS functions
200
+ ON functions.oid = to_regprocedure(expected.name || '()')
201
+ LEFT JOIN pg_language AS language ON language.oid = functions.prolang
202
+ `;
203
+ return (functions.length === EXPECTED_FUNCTION_BODIES.size &&
204
+ functions.every(({ name, body, canonical }) => {
205
+ const expected = EXPECTED_FUNCTION_BODIES.get(name);
206
+ return canonical && body !== null && expected !== undefined
207
+ ? normalizeFunctionBody(body) === normalizeFunctionBody(expected)
208
+ : false;
209
+ }));
210
+ }
211
+ /** Initialize or migrate the shared schema without locking live tables when current. */
212
+ export async function initializePostgresSchema(ctx) {
213
+ const lockName = postgresAdvisoryLockName('schema');
214
+ await ctx.sql.begin(async (tx) => {
215
+ await tx `SELECT pg_advisory_xact_lock(hashtextextended(${lockName}, 0))`;
216
+ if (await hasCurrentSchema(tx))
217
+ return;
218
+ await tx.unsafe(POSTGRES_SCHEMA).simple();
219
+ const appliedAt = await databaseNow(tx);
220
+ await tx `
221
+ INSERT INTO bunqueue_schema_migrations (version, applied_at)
222
+ VALUES (${POSTGRES_SCHEMA_VERSION}, ${appliedAt})
223
+ ON CONFLICT (version) DO NOTHING
224
+ `;
225
+ });
226
+ }
@@ -0,0 +1,6 @@
1
+ import type { TransactionSQL } from 'bun';
2
+ import type { Job } from '../../../domain/types/job';
3
+ import { type PostgresContext } from './context';
4
+ import type { PostgresAdmissionResult } from './admissionResult';
5
+ /** Reconcile same-batch dependency generations without reordering admission events. */
6
+ export declare function reconcilePostgresSerialAdmissions(tx: TransactionSQL, ctx: PostgresContext, admissions: readonly PostgresAdmissionResult[]): Promise<Job[]>;
@@ -0,0 +1,96 @@
1
+ import { decodePostgresJob, encodePostgresValue, eventPayload, postgresByteaBase64, postgresStateForJob, } from './codec';
2
+ import { databaseNow } from './context';
3
+ function latestInsertions(admissions) {
4
+ const latest = new Map();
5
+ for (let index = 0; index < admissions.length; index++) {
6
+ if (admissions[index].inserted)
7
+ latest.set(String(admissions[index].job.id), index);
8
+ }
9
+ return latest;
10
+ }
11
+ function correctedJob(row, admission, now) {
12
+ const stored = decodePostgresJob(row);
13
+ const state = postgresStateForJob(stored.job, row.dependencies_satisfied, now);
14
+ if (admission.timelineIndex === undefined)
15
+ return { job: stored.job, state };
16
+ const timeline = [...stored.job.timeline];
17
+ const entry = timeline[admission.timelineIndex];
18
+ if (entry)
19
+ timeline[admission.timelineIndex] = { ...entry, state };
20
+ return { job: { ...stored.job, timeline }, state };
21
+ }
22
+ async function loadFinalRows(tx, ctx, ids) {
23
+ return await tx `
24
+ SELECT job.*, NOT EXISTS (
25
+ SELECT 1
26
+ FROM bunqueue_dependencies AS dependency
27
+ WHERE dependency.namespace = job.namespace AND dependency.job_id = job.id
28
+ AND NOT EXISTS (
29
+ SELECT 1 FROM bunqueue_completions AS completion
30
+ WHERE completion.namespace = dependency.namespace
31
+ AND completion.job_id = dependency.dependency_id
32
+ )
33
+ AND NOT EXISTS (
34
+ SELECT 1 FROM bunqueue_jobs AS completed
35
+ WHERE completed.namespace = dependency.namespace
36
+ AND completed.id = dependency.dependency_id AND completed.state = 'completed'
37
+ )
38
+ ) AS dependencies_satisfied
39
+ FROM bunqueue_jobs AS job
40
+ WHERE job.namespace = ${ctx.config.namespace}
41
+ AND job.id = ANY(${tx.array([...ids], 'TEXT')})
42
+ ORDER BY job.id
43
+ FOR UPDATE OF job
44
+ `;
45
+ }
46
+ async function persistFinalRows(tx, ctx, prepared) {
47
+ if (prepared.length === 0)
48
+ return;
49
+ await tx `
50
+ UPDATE bunqueue_jobs AS job
51
+ SET payload = decode(batch.payload_base64, 'base64'), state = batch.state
52
+ FROM unnest(
53
+ ${tx.array(prepared.map(({ id }) => id), 'TEXT')},
54
+ ${tx.array(prepared.map(({ payload }) => payload), 'TEXT')},
55
+ ${tx.array(prepared.map(({ state }) => state), 'TEXT')}
56
+ ) AS batch(id, payload_base64, state)
57
+ WHERE job.namespace = ${ctx.config.namespace} AND job.id = batch.id
58
+ `;
59
+ await tx `
60
+ UPDATE bunqueue_events AS event
61
+ SET payload = decode(batch.payload_base64, 'base64')
62
+ FROM unnest(
63
+ ${tx.array(prepared.map(({ eventId }) => eventId), 'BIGINT')},
64
+ ${tx.array(prepared.map(({ eventPayload: payload }) => payload), 'TEXT')}
65
+ ) AS batch(id, payload_base64)
66
+ WHERE event.namespace = ${ctx.config.namespace} AND event.id = batch.id
67
+ `;
68
+ }
69
+ /** Reconcile same-batch dependency generations without reordering admission events. */
70
+ export async function reconcilePostgresSerialAdmissions(tx, ctx, admissions) {
71
+ const latest = latestInsertions(admissions);
72
+ if (latest.size === 0)
73
+ return admissions.map(({ job }) => job);
74
+ const now = await databaseNow(tx);
75
+ const rows = await loadFinalRows(tx, ctx, [...latest.keys()]);
76
+ const prepared = rows.map((row) => {
77
+ const insertionIndex = latest.get(row.id);
78
+ const admission = admissions[insertionIndex];
79
+ const { job, state } = correctedJob(row, admission, now);
80
+ return {
81
+ id: row.id,
82
+ job,
83
+ state,
84
+ payload: postgresByteaBase64(encodePostgresValue(job)),
85
+ eventId: admission.pushedEventId,
86
+ eventPayload: postgresByteaBase64(eventPayload({ job, state })),
87
+ insertionIndex,
88
+ };
89
+ });
90
+ await persistFinalRows(tx, ctx, prepared);
91
+ const survivors = new Map(prepared.map((entry) => [entry.id, entry]));
92
+ return admissions.map((admission, index) => {
93
+ const survivor = survivors.get(String(admission.job.id));
94
+ return survivor && index >= survivor.insertionIndex ? survivor.job : admission.job;
95
+ });
96
+ }
@@ -0,0 +1,3 @@
1
+ import type { PostgresContext, PostgresReadSql } from './context';
2
+ /** Reject an unsafe local read model before allocating or decoding its payloads. */
3
+ export declare function assertPostgresSnapshotBudget(ctx: PostgresContext, sql: PostgresReadSql, queue?: string): Promise<void>;
@@ -0,0 +1,83 @@
1
+ /** Reject an unsafe local read model before allocating or decoding its payloads. */
2
+ export async function assertPostgresSnapshotBudget(ctx, sql, queue) {
3
+ const queueFilter = queue ?? null;
4
+ const [weight] = await sql `
5
+ WITH retained_jobs AS MATERIALIZED (
6
+ SELECT payload, result, dlq_entry, dlq_retry_state
7
+ FROM bunqueue_jobs
8
+ WHERE namespace = ${ctx.config.namespace}
9
+ AND (${queueFilter}::text IS NULL OR queue = ${queueFilter})
10
+ AND (${queueFilter}::text IS NOT NULL OR state <> 'completed')
11
+ UNION ALL
12
+ (
13
+ SELECT payload, result, dlq_entry, dlq_retry_state
14
+ FROM bunqueue_jobs
15
+ WHERE namespace = ${ctx.config.namespace}
16
+ AND ${queueFilter}::text IS NULL
17
+ AND state = 'completed'
18
+ ORDER BY completed_at DESC NULLS LAST, id DESC
19
+ LIMIT ${ctx.config.maxCompletedJobs}
20
+ )
21
+ ), pinned AS MATERIALIZED (
22
+ SELECT DISTINCT dependency.dependency_id AS job_id
23
+ FROM bunqueue_dependencies AS dependency
24
+ JOIN bunqueue_jobs AS consumer
25
+ ON consumer.namespace = dependency.namespace AND consumer.id = dependency.job_id
26
+ WHERE dependency.namespace = ${ctx.config.namespace}
27
+ AND consumer.state = ANY(${sql.array(['waiting', 'prioritized', 'delayed', 'waiting-children', 'active'], 'TEXT')})
28
+ ), recent_completions AS MATERIALIZED (
29
+ SELECT completion.job_id, completion.result
30
+ FROM bunqueue_completions AS completion
31
+ WHERE completion.namespace = ${ctx.config.namespace}
32
+ AND (${queueFilter}::text IS NULL OR completion.queue = ${queueFilter})
33
+ AND NOT EXISTS (
34
+ SELECT 1 FROM pinned WHERE pinned.job_id = completion.job_id
35
+ )
36
+ ORDER BY completion.completed_at DESC, completion.job_id DESC
37
+ LIMIT ${ctx.config.maxJobResults}
38
+ ), selected_completions AS MATERIALIZED (
39
+ SELECT completion.job_id, completion.result
40
+ FROM bunqueue_completions AS completion
41
+ JOIN pinned ON pinned.job_id = completion.job_id
42
+ WHERE completion.namespace = ${ctx.config.namespace}
43
+ AND (${queueFilter}::text IS NULL OR completion.queue = ${queueFilter})
44
+ UNION ALL
45
+ SELECT job_id, result FROM recent_completions
46
+ )
47
+ SELECT
48
+ (
49
+ (SELECT COUNT(*) FROM retained_jobs) +
50
+ (SELECT COUNT(*) FROM selected_completions)
51
+ )::bigint AS items,
52
+ (
53
+ COALESCE((
54
+ SELECT SUM(
55
+ octet_length(payload) + COALESCE(octet_length(result), 0) +
56
+ COALESCE(octet_length(dlq_entry), 0) +
57
+ COALESCE(octet_length(dlq_retry_state), 0)
58
+ ) FROM retained_jobs
59
+ ), 0) +
60
+ COALESCE((SELECT SUM(COALESCE(octet_length(result), 0)) FROM selected_completions), 0) +
61
+ COALESCE((
62
+ SELECT SUM(octet_length(payload)) FROM bunqueue_crons
63
+ WHERE namespace = ${ctx.config.namespace} AND ${queueFilter}::text IS NULL
64
+ ), 0) +
65
+ COALESCE((
66
+ SELECT SUM(
67
+ COALESCE(octet_length(stall_config), 0) +
68
+ COALESCE(octet_length(dlq_config), 0)
69
+ ) FROM bunqueue_queue_state
70
+ WHERE namespace = ${ctx.config.namespace}
71
+ AND (${queueFilter}::text IS NULL OR queue = ${queueFilter})
72
+ ), 0)
73
+ )::bigint AS payload_bytes
74
+ `;
75
+ const scope = queue === undefined ? 'manager' : `queue "${queue}"`;
76
+ if (Number(weight.items) > ctx.config.maxSnapshotJobs) {
77
+ throw new Error(`PostgreSQL ${scope} snapshot exceeds maxSnapshotJobs=${ctx.config.maxSnapshotJobs}`);
78
+ }
79
+ if (Number(weight.payload_bytes) > ctx.config.maxSnapshotPayloadBytes) {
80
+ throw new Error(`PostgreSQL ${scope} snapshot exceeds ` +
81
+ `maxSnapshotPayloadBytes=${ctx.config.maxSnapshotPayloadBytes}`);
82
+ }
83
+ }
@@ -0,0 +1,10 @@
1
+ import type { PostgresStorageHealth, ResolvedPostgresStorageConfig } from './types';
2
+ /** Aggregate independent PostgreSQL subsystem failures without hiding older degradation. */
3
+ export declare class PostgresStorageHealthTracker {
4
+ private readonly config;
5
+ private readonly errors;
6
+ constructor(config: ResolvedPostgresStorageConfig);
7
+ record(key: string, error: unknown, prefix?: string): void;
8
+ clear(key: string): void;
9
+ snapshot(): PostgresStorageHealth;
10
+ }
@@ -0,0 +1,29 @@
1
+ /** Aggregate independent PostgreSQL subsystem failures without hiding older degradation. */
2
+ export class PostgresStorageHealthTracker {
3
+ config;
4
+ errors = new Map();
5
+ constructor(config) {
6
+ this.config = config;
7
+ }
8
+ record(key, error, prefix = '') {
9
+ const message = error instanceof Error ? error.message : String(error);
10
+ const since = this.errors.get(key)?.since ?? Date.now();
11
+ this.errors.set(key, { message: `${prefix}${message}`, since });
12
+ }
13
+ clear(key) {
14
+ this.errors.delete(key);
15
+ }
16
+ snapshot() {
17
+ const errors = [...this.errors.entries()].sort(([left], [right]) => left.localeCompare(right));
18
+ const messages = errors.map(([, { message }]) => message);
19
+ const sinceValues = errors.map(([, { since }]) => since);
20
+ return {
21
+ ok: messages.length === 0,
22
+ error: messages.length > 0 ? messages.join('; ') : null,
23
+ since: sinceValues.length > 0 ? Math.min(...sinceValues) : null,
24
+ backend: 'postgres',
25
+ brokerId: this.config.brokerId,
26
+ namespace: this.config.namespace,
27
+ };
28
+ }
29
+ }
@@ -0,0 +1,100 @@
1
+ import type { JobId } from '../../../domain/types/job';
2
+ import { setPostgresDlqConfig, setPostgresStallConfig } from './control';
3
+ import { type ListPostgresJobsOptions } from './queries';
4
+ import { PostgresAdmissionStore } from './admissionStore';
5
+ import type { CronJobInput } from '../../../domain/types/cron';
6
+ import { type GroupPullOptions } from '../../../domain/types/group';
7
+ import type { Worker } from '../../../domain/types/worker';
8
+ import type { QueueMetricType } from '../../../domain/types/metrics';
9
+ import type { ClaimedPostgresJob, PostgresCompletionInput, PostgresFailureInput } from './types';
10
+ import { finalizePostgresLifetimeMetrics } from './lifetimeMetricsFinalizer';
11
+ import { loadPostgresJobProjections } from './readModels';
12
+ /** Database-authoritative PostgreSQL queue store safe for concurrent brokers. */
13
+ export declare class PostgresQueueStore extends PostgresAdmissionStore {
14
+ getGroupJobsCount: (queue: string, groupId?: string) => Promise<number>;
15
+ getGroupActiveCount: (queue: string, groupId: string) => Promise<number>;
16
+ setGroupRateLimit: (queue: string, groupId: string, max: number, duration: number) => Promise<void>;
17
+ getGroupRateLimit: (queue: string, groupId: string) => Promise<import("../../../domain/types/group").GroupRateLimitOverride | null>;
18
+ removeGroupRateLimit: (queue: string, groupId: string) => Promise<number>;
19
+ getGroupRateLimitTtl: (queue: string, groupId: string, maxJobs?: number) => Promise<number>;
20
+ setGroupConcurrency: (queue: string, groupId: string, concurrency: number) => Promise<void>;
21
+ getGroupConcurrency: (queue: string, groupId: string) => Promise<number | null>;
22
+ removeGroupConcurrency: (queue: string, groupId: string) => Promise<number>;
23
+ now(): Promise<number>;
24
+ claim(queue: string, count: number, owner?: string, leaseDurationMs?: number, groupOptions?: GroupPullOptions): Promise<ClaimedPostgresJob[]>;
25
+ complete(id: JobId, token: string, result?: unknown, remove?: boolean): Promise<import("./types").PostgresTransitionResult>;
26
+ completeMany(items: readonly PostgresCompletionInput[]): Promise<import("./types").PostgresBatchCompletionResult[]>;
27
+ fail(input: PostgresFailureInput): Promise<import("./types").PostgresTransitionResult>;
28
+ renew(id: JobId, token: string, durationMs: number): Promise<number | null>;
29
+ recoverExpired(limit?: number): Promise<number>;
30
+ maintainDlq(limit?: number): Promise<import("./dlqLifecycle").PostgresDlqMaintenanceResult>;
31
+ addCron: (input: CronJobInput) => Promise<import("../../../domain/types").CronJob>;
32
+ getCron: (name: string) => Promise<import("../../../domain/types").CronJob | undefined>;
33
+ listCrons: () => Promise<import("../../../domain/types").CronJob[]>;
34
+ removeCron: (name: string) => Promise<boolean>;
35
+ processCrons: (limit?: number) => Promise<number>;
36
+ saveWorker: (worker: Worker) => Promise<void>;
37
+ heartbeatWorker: (id: string, stats?: {
38
+ activeJobs?: number;
39
+ processed?: number;
40
+ failed?: number;
41
+ }, clientId?: string) => Promise<boolean>;
42
+ removeWorker: (id: string, clientId?: string) => Promise<boolean>;
43
+ removeClientWorkers: (clientId: string) => Promise<number>;
44
+ listWorkers: () => Promise<Worker[]>;
45
+ getQueueMetrics: (queue: string, type: QueueMetricType, start?: number, end?: number) => Promise<import("../../../client").QueueMetrics>;
46
+ trimQueueEvents: (queue: string, maxLength: number) => Promise<number>;
47
+ releaseClientLease: (id: JobId, token: string) => Promise<boolean>;
48
+ getJob: (id: JobId) => Promise<import("./types").PostgresStoredJob | null>;
49
+ getJobs: (ids: readonly JobId[]) => Promise<import("./types").PostgresStoredJob[]>;
50
+ findMissingDependencies: (ids: readonly JobId[]) => Promise<JobId[]>;
51
+ getResult: (id: JobId) => Promise<{
52
+ found: boolean;
53
+ result: unknown;
54
+ }>;
55
+ getCounts: (queue?: string) => Promise<import("./types").PostgresCounts>;
56
+ getQueues: () => Promise<string[]>;
57
+ getDlq: (queue: string, limit?: number) => Promise<import("../../../domain/types/dlq").DlqEntry[]>;
58
+ getChildrenValues: (id: JobId) => Promise<Record<string, unknown>>;
59
+ getFailedChildrenValues: (id: JobId) => Promise<Record<string, string>>;
60
+ getIgnoredChildrenFailures: (id: JobId) => Promise<Record<string, string>>;
61
+ addLog: (id: JobId, message: string, level: "info" | "warn" | "error") => Promise<boolean>;
62
+ getLogs: (id: JobId) => Promise<import("../../../domain/types/worker").JobLogEntry[]>;
63
+ clearLogs: (id: JobId, keepLogs?: number) => Promise<void>;
64
+ getQueueState: (queue: string) => Promise<import("./types").PostgresQueueState>;
65
+ list: (queue: string, options?: ListPostgresJobsOptions) => Promise<import("./types").PostgresStoredJob[]>;
66
+ loadAll: () => Promise<import("./types").PostgresStoredJob[]>;
67
+ loadResults: (queue?: string) => Promise<import("./types").PostgresCompletionResult[]>;
68
+ latestEventId: () => Promise<number>;
69
+ loadLifetimeMetrics: () => Promise<import("./lifetimeMetrics").PostgresLifetimeMetricsSnapshot>;
70
+ finalizeLifetimeMetrics: (apply: Parameters<typeof finalizePostgresLifetimeMetrics>[1]) => Promise<void>;
71
+ loadCloudReadModel: () => Promise<import("./cloudReadModel").PostgresCloudReadModel>;
72
+ loadManagerSnapshot: () => Promise<import("./readModels").PostgresManagerSnapshot>;
73
+ loadQueueReadModel: (queue: string) => Promise<import("./readModels").PostgresQueueReadModel>;
74
+ loadJobProjections: (requests: Parameters<typeof loadPostgresJobProjections>[1]) => Promise<ReadonlyMap<JobId, import("./readModels").PostgresJobProjection>>;
75
+ updateData: (id: JobId, data: unknown) => Promise<boolean>;
76
+ updateProgress: (id: JobId, value: number, message?: string) => Promise<boolean>;
77
+ changePriority: (id: JobId, priority: number, lifo?: boolean) => Promise<boolean>;
78
+ changeDelay: (id: JobId, runAt: number, token?: string) => Promise<boolean>;
79
+ moveToWaitingChildren: (id: JobId, token?: string) => Promise<boolean>;
80
+ clearUniqueKey: (id: JobId) => Promise<boolean>;
81
+ removeDependency: (id: JobId) => Promise<boolean>;
82
+ removeUnprocessedChildren: (parentId: JobId) => Promise<JobId[]>;
83
+ updateParent: (childId: JobId, parentId: JobId) => Promise<void>;
84
+ promote: (id: JobId) => Promise<boolean>;
85
+ cancel: (id: JobId) => Promise<boolean>;
86
+ discard: (id: JobId, token?: string) => Promise<boolean>;
87
+ remove: (id: JobId, token?: string) => Promise<boolean>;
88
+ removeDlq: (queue: string, id: JobId) => Promise<boolean>;
89
+ purgeDlq: (queue: string) => Promise<JobId[]>;
90
+ clean: (queue: string, graceMs: number, state?: string, limit?: number) => Promise<JobId[]>;
91
+ retry: (id: JobId, timestamp?: number) => Promise<boolean>;
92
+ pause: (queue: string, paused: boolean) => Promise<void>;
93
+ setRateLimit: (queue: string, limit: number | null, durationMs: number | null, ttlMs?: number | null) => Promise<void>;
94
+ setConcurrency: (queue: string, limit: number | null) => Promise<void>;
95
+ setStallConfig: (queue: string, config: Parameters<typeof setPostgresStallConfig>[2]) => Promise<void>;
96
+ setDlqConfig: (queue: string, config: Parameters<typeof setPostgresDlqConfig>[2]) => Promise<void>;
97
+ drain: (queue: string) => Promise<number>;
98
+ obliterate: (queue: string) => Promise<number>;
99
+ promoteMany: (queue: string, count?: number) => Promise<JobId[]>;
100
+ }