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,45 @@
1
+ import type { PostgresContext } from './context';
2
+ import type { PostgresDeliveredStoreEvent } from './types';
3
+ type EventListener = (event: PostgresDeliveredStoreEvent) => void;
4
+ type InvalidationListener = (queue: string) => void;
5
+ type DrainStatusListener = (error: Error | null) => void;
6
+ export declare function postgresEventDrainBatchSize(maxQueueEvents: number): number;
7
+ /** Commit-ordered journal polling with LISTEN/NOTIFY used only as a wakeup hint. */
8
+ export declare class PostgresEventStream {
9
+ private readonly ctx;
10
+ private subscription;
11
+ private pollTimer;
12
+ private readonly listeners;
13
+ private readonly invalidationListeners;
14
+ private readonly drainStatusListeners;
15
+ private readonly waiters;
16
+ private readonly queueCursors;
17
+ private readonly retentionQueues;
18
+ private journalCursor;
19
+ private cursor;
20
+ private checkpointScanRequested;
21
+ private drainRequested;
22
+ private draining;
23
+ private retentionRetryTimer;
24
+ private closed;
25
+ constructor(ctx: PostgresContext);
26
+ start(): Promise<void>;
27
+ subscribe(listener: EventListener): () => void;
28
+ subscribeInvalidation(listener: InvalidationListener): () => void;
29
+ subscribeDrainStatus(listener: DrainStatusListener): () => void;
30
+ close(): Promise<void>;
31
+ wait(queue: string, timeoutMs: number, signal?: AbortSignal): Promise<void>;
32
+ private handleNotification;
33
+ private wake;
34
+ private wakeAll;
35
+ private removeWaiter;
36
+ private drain;
37
+ private drainLoop;
38
+ private convergeEventRetention;
39
+ private scheduleRetentionRetry;
40
+ private applyEvent;
41
+ private invalidateQueue;
42
+ private scanPruneWatermarks;
43
+ private reportDrainStatus;
44
+ }
45
+ export {};
@@ -0,0 +1,276 @@
1
+ import { latestPostgresEventJournalBaseline, loadPostgresJournalEventsAfter, } from './eventJournal';
2
+ import { PostgresEventCatchupCursors } from './eventCatchupCursors';
3
+ import { loadPostgresEventPruneWatermarks } from './eventPruneWatermarks';
4
+ import { POSTGRES_EVENT_CHANNEL } from './schema';
5
+ import { tryTrimPostgresQueueEvents } from './telemetry';
6
+ const MIN_EVENT_DRAIN_BATCH = 1_000;
7
+ const MAX_EVENT_DRAIN_BATCH = 4_096;
8
+ export function postgresEventDrainBatchSize(maxQueueEvents) {
9
+ return Math.max(MIN_EVENT_DRAIN_BATCH, Math.min(MAX_EVENT_DRAIN_BATCH, maxQueueEvents));
10
+ }
11
+ function requiresQueueInvalidation(event) {
12
+ return event.type.startsWith('queue-') || (!event.job && event.state === null);
13
+ }
14
+ /** Commit-ordered journal polling with LISTEN/NOTIFY used only as a wakeup hint. */
15
+ export class PostgresEventStream {
16
+ ctx;
17
+ subscription = null;
18
+ pollTimer = null;
19
+ listeners = new Set();
20
+ invalidationListeners = new Set();
21
+ drainStatusListeners = new Set();
22
+ waiters = new Map();
23
+ queueCursors = new PostgresEventCatchupCursors();
24
+ retentionQueues = new Set();
25
+ journalCursor = { commitSeq: 0, eventId: 0 };
26
+ cursor = 0;
27
+ checkpointScanRequested = false;
28
+ drainRequested = false;
29
+ draining = null;
30
+ retentionRetryTimer = null;
31
+ closed = false;
32
+ constructor(ctx) {
33
+ this.ctx = ctx;
34
+ }
35
+ async start() {
36
+ const [baseline, watermarks] = await Promise.all([
37
+ latestPostgresEventJournalBaseline(this.ctx),
38
+ loadPostgresEventPruneWatermarks(this.ctx),
39
+ ]);
40
+ this.cursor = baseline.latestEventId;
41
+ this.journalCursor = { commitSeq: baseline.commitSeq, eventId: Number.MAX_SAFE_INTEGER };
42
+ this.queueCursors.reset(baseline.commitSeq);
43
+ for (const watermark of watermarks) {
44
+ if (watermark.commitSeq > baseline.commitSeq) {
45
+ this.queueCursors.applied(watermark.queue, watermark.commitSeq);
46
+ }
47
+ // `PostgresQueueManagerState` loads a full snapshot of every queue after
48
+ // this call, so recorded prunes are already covered and must not refresh
49
+ // the freshly loaded read model.
50
+ this.queueCursors.remember(watermark);
51
+ }
52
+ this.subscription = await this.ctx.sql.listen(POSTGRES_EVENT_CHANNEL, (payload) => this.handleNotification(payload), () => void this.drain());
53
+ this.pollTimer = setInterval(() => void this.drain(), this.ctx.config.pollIntervalMs);
54
+ }
55
+ subscribe(listener) {
56
+ this.listeners.add(listener);
57
+ return () => this.listeners.delete(listener);
58
+ }
59
+ subscribeInvalidation(listener) {
60
+ this.invalidationListeners.add(listener);
61
+ return () => this.invalidationListeners.delete(listener);
62
+ }
63
+ subscribeDrainStatus(listener) {
64
+ this.drainStatusListeners.add(listener);
65
+ return () => this.drainStatusListeners.delete(listener);
66
+ }
67
+ async close() {
68
+ this.closed = true;
69
+ if (this.pollTimer)
70
+ clearInterval(this.pollTimer);
71
+ this.pollTimer = null;
72
+ if (this.retentionRetryTimer)
73
+ clearTimeout(this.retentionRetryTimer);
74
+ this.retentionRetryTimer = null;
75
+ await this.subscription?.unlisten();
76
+ this.subscription = null;
77
+ for (const registrations of this.waiters.values()) {
78
+ for (const registration of [...registrations])
79
+ registration.resolve();
80
+ }
81
+ this.waiters.clear();
82
+ await this.draining;
83
+ }
84
+ wait(queue, timeoutMs, signal) {
85
+ if (this.closed || timeoutMs <= 0 || signal?.aborted)
86
+ return Promise.resolve();
87
+ return new Promise((resolve) => {
88
+ const finish = () => {
89
+ this.removeWaiter(queue, registration);
90
+ resolve();
91
+ };
92
+ const onAbort = () => finish();
93
+ const registration = {
94
+ resolve: finish,
95
+ timer: setTimeout(finish, timeoutMs),
96
+ ...(signal && { signal, onAbort }),
97
+ };
98
+ let registrations = this.waiters.get(queue);
99
+ if (!registrations) {
100
+ registrations = new Set();
101
+ this.waiters.set(queue, registrations);
102
+ }
103
+ registrations.add(registration);
104
+ signal?.addEventListener('abort', onAbort, { once: true });
105
+ });
106
+ }
107
+ handleNotification(payload) {
108
+ try {
109
+ const parsed = JSON.parse(payload);
110
+ if (parsed.namespace !== this.ctx.config.namespace)
111
+ return;
112
+ if (parsed.queue)
113
+ this.wake(parsed.queue);
114
+ if (parsed.scanPruneWatermarks === true ||
115
+ (Number.isSafeInteger(parsed.prunedThrough) && parsed.prunedThrough > 0)) {
116
+ this.checkpointScanRequested = true;
117
+ }
118
+ if (parsed.queue && parsed.retentionRequested === true) {
119
+ this.retentionQueues.add(parsed.queue);
120
+ }
121
+ }
122
+ catch {
123
+ this.checkpointScanRequested = true;
124
+ this.wakeAll();
125
+ }
126
+ void this.drain(false);
127
+ }
128
+ wake(queue) {
129
+ const registrations = this.waiters.get(queue);
130
+ if (!registrations)
131
+ return;
132
+ for (const registration of [...registrations])
133
+ registration.resolve();
134
+ }
135
+ wakeAll() {
136
+ for (const queue of this.waiters.keys())
137
+ this.wake(queue);
138
+ }
139
+ removeWaiter(queue, registration) {
140
+ const registrations = this.waiters.get(queue);
141
+ registrations?.delete(registration);
142
+ if (registrations?.size === 0)
143
+ this.waiters.delete(queue);
144
+ clearTimeout(registration.timer);
145
+ if (registration.signal && registration.onAbort) {
146
+ registration.signal.removeEventListener('abort', registration.onAbort);
147
+ }
148
+ }
149
+ async drain(scanPruneWatermarks = true) {
150
+ if (scanPruneWatermarks)
151
+ this.checkpointScanRequested = true;
152
+ this.drainRequested = true;
153
+ if (this.closed)
154
+ return;
155
+ if (this.draining)
156
+ return this.draining;
157
+ this.draining = this.drainLoop()
158
+ .then(() => {
159
+ if (!this.closed && !this.retentionRetryTimer)
160
+ this.reportDrainStatus(null);
161
+ })
162
+ .catch((error) => {
163
+ this.reportDrainStatus(error instanceof Error ? error : new Error(String(error)));
164
+ this.scheduleRetentionRetry();
165
+ })
166
+ .finally(() => {
167
+ this.draining = null;
168
+ if (this.drainRequested && !this.closed)
169
+ void this.drain(false);
170
+ });
171
+ return this.draining;
172
+ }
173
+ async drainLoop() {
174
+ const batchSize = postgresEventDrainBatchSize(this.ctx.config.maxQueueEvents);
175
+ while (!this.closed) {
176
+ this.drainRequested = false;
177
+ await this.convergeEventRetention();
178
+ await this.scanPruneWatermarks();
179
+ const entries = await loadPostgresJournalEventsAfter(this.ctx, this.journalCursor, batchSize);
180
+ // Always re-check retention against the pre-batch position: a prune that
181
+ // committed after the previous scan can have removed queue history this
182
+ // batch does not contain, and applying the batch would hide the gap.
183
+ if (entries.length > 0)
184
+ this.checkpointScanRequested = true;
185
+ await this.scanPruneWatermarks();
186
+ for (const entry of entries)
187
+ this.applyEvent(entry);
188
+ if (entries.length >= batchSize || this.drainRequested)
189
+ continue;
190
+ return;
191
+ }
192
+ }
193
+ async convergeEventRetention() {
194
+ if (this.retentionRetryTimer)
195
+ return;
196
+ const maxLength = this.ctx.config.maxQueueEvents;
197
+ const queues = [...this.retentionQueues].sort();
198
+ for (const queue of queues) {
199
+ this.retentionQueues.delete(queue);
200
+ try {
201
+ const removed = await tryTrimPostgresQueueEvents(this.ctx, queue, maxLength);
202
+ if (removed === null) {
203
+ this.retentionQueues.add(queue);
204
+ this.scheduleRetentionRetry();
205
+ }
206
+ }
207
+ catch (error) {
208
+ this.retentionQueues.add(queue);
209
+ throw error;
210
+ }
211
+ }
212
+ }
213
+ scheduleRetentionRetry() {
214
+ if (this.closed || this.retentionRetryTimer || this.retentionQueues.size === 0)
215
+ return;
216
+ const delay = Math.min(this.ctx.config.pollIntervalMs, 250);
217
+ this.retentionRetryTimer = setTimeout(() => {
218
+ this.retentionRetryTimer = null;
219
+ if (!this.closed && this.retentionQueues.size > 0)
220
+ void this.drain(false);
221
+ }, delay);
222
+ }
223
+ applyEvent(entry) {
224
+ const { event, commitSeq } = entry;
225
+ this.journalCursor = { commitSeq, eventId: event.id };
226
+ this.cursor = Math.max(this.cursor, event.id);
227
+ this.queueCursors.applied(event.queue, commitSeq);
228
+ if (requiresQueueInvalidation(event))
229
+ this.invalidateQueue(event.queue);
230
+ const delivered = { ...event, commitSeq };
231
+ for (const listener of this.listeners) {
232
+ try {
233
+ listener(delivered);
234
+ }
235
+ catch {
236
+ // Listener isolation: one observer cannot stop durable cursor progress.
237
+ }
238
+ }
239
+ }
240
+ invalidateQueue(queue) {
241
+ for (const listener of this.invalidationListeners) {
242
+ try {
243
+ listener(queue);
244
+ }
245
+ catch {
246
+ // Invalidation observers cannot interrupt durable cursor progress.
247
+ }
248
+ }
249
+ }
250
+ async scanPruneWatermarks() {
251
+ if (!this.checkpointScanRequested)
252
+ return;
253
+ this.checkpointScanRequested = false;
254
+ try {
255
+ const watermarks = await loadPostgresEventPruneWatermarks(this.ctx);
256
+ for (const watermark of watermarks) {
257
+ if (this.queueCursors.requiresRefresh(watermark))
258
+ this.invalidateQueue(watermark.queue);
259
+ }
260
+ }
261
+ catch (error) {
262
+ this.checkpointScanRequested = true;
263
+ throw error;
264
+ }
265
+ }
266
+ reportDrainStatus(error) {
267
+ for (const listener of this.drainStatusListeners) {
268
+ try {
269
+ listener(error);
270
+ }
271
+ catch {
272
+ // Diagnostics must not stop the next polling retry.
273
+ }
274
+ }
275
+ }
276
+ }
@@ -0,0 +1,3 @@
1
+ import { type PostgresContext } from './context';
2
+ /** Delete pending jobs whose TTL elapsed, matching the existing SQLite pull semantics. */
3
+ export declare function expirePendingPostgresJobs(ctx: PostgresContext, queue: string, requestedNow?: number): Promise<number>;
@@ -0,0 +1,74 @@
1
+ import { jobId } from '../../../domain/types/job';
2
+ import { decodePostgresJob } from './codec';
3
+ import { databaseNow, recordPostgresEvent } from './context';
4
+ import { lockPostgresDestructionCandidates, partitionPostgresDestructionCandidates, } from './dependencyDestruction';
5
+ /** Delete pending jobs whose TTL elapsed, matching the existing SQLite pull semantics. */
6
+ export async function expirePendingPostgresJobs(ctx, queue, requestedNow) {
7
+ return await ctx.sql.begin(async (tx) => {
8
+ const now = requestedNow ?? (await databaseNow(tx));
9
+ const candidates = await tx `
10
+ SELECT id FROM bunqueue_jobs
11
+ WHERE namespace = ${ctx.config.namespace}
12
+ AND queue = ${queue}
13
+ AND state IN ('waiting', 'prioritized', 'delayed')
14
+ AND ttl IS NOT NULL
15
+ AND created_at + ttl < ${now}
16
+ ORDER BY created_at, id
17
+ LIMIT 1000
18
+ `;
19
+ const candidateIds = candidates.map((row) => jobId(row.id));
20
+ if (candidateIds.length === 0)
21
+ return 0;
22
+ await lockPostgresDestructionCandidates(tx, ctx, candidateIds);
23
+ const rows = await tx `
24
+ SELECT * FROM bunqueue_jobs
25
+ WHERE namespace = ${ctx.config.namespace}
26
+ AND queue = ${queue}
27
+ AND state IN ('waiting', 'prioritized', 'delayed')
28
+ AND ttl IS NOT NULL
29
+ AND created_at + ttl < ${now}
30
+ AND id = ANY(${tx.array(candidateIds.map(String), 'TEXT')})
31
+ ORDER BY created_at, id
32
+ `;
33
+ const plannedIds = rows.map((row) => jobId(row.id));
34
+ const { deletableIds } = await partitionPostgresDestructionCandidates(tx, ctx, plannedIds, plannedIds);
35
+ const deletable = new Set(deletableIds.map(String));
36
+ const removedRows = rows.filter((row) => deletable.has(row.id));
37
+ if (removedRows.length === 0)
38
+ return 0;
39
+ const ids = removedRows.map((row) => row.id);
40
+ await tx `
41
+ DELETE FROM bunqueue_job_logs
42
+ WHERE namespace = ${ctx.config.namespace} AND job_id = ANY(${tx.array(ids, 'TEXT')})
43
+ `;
44
+ await tx `
45
+ DELETE FROM bunqueue_flow_failures
46
+ WHERE namespace = ${ctx.config.namespace}
47
+ AND parent_id = ANY(${tx.array(ids, 'TEXT')})
48
+ `;
49
+ await tx `
50
+ DELETE FROM bunqueue_dependencies
51
+ WHERE namespace = ${ctx.config.namespace}
52
+ AND job_id = ANY(${tx.array(ids, 'TEXT')})
53
+ `;
54
+ await tx `
55
+ DELETE FROM bunqueue_jobs
56
+ WHERE namespace = ${ctx.config.namespace}
57
+ AND id = ANY(${tx.array(ids, 'TEXT')})
58
+ `;
59
+ for (const row of removedRows) {
60
+ const job = decodePostgresJob(row).job;
61
+ await recordPostgresEvent(tx, ctx, {
62
+ queue,
63
+ type: 'removed',
64
+ jobId: job.id,
65
+ occurredAt: now,
66
+ job,
67
+ state: row.state,
68
+ error: 'Job TTL expired',
69
+ removed: true,
70
+ });
71
+ }
72
+ return removedRows.length;
73
+ });
74
+ }
@@ -0,0 +1,17 @@
1
+ import type { TransactionSQL } from 'bun';
2
+ import { type Job, type JobId } from '../../../domain/types/job';
3
+ import { type PostgresContext } from './context';
4
+ export interface PostgresDlqLimitRequest {
5
+ readonly queue: string;
6
+ readonly maxEntries: number;
7
+ }
8
+ /** Serialize mutations involving one flow parent across brokers. */
9
+ export declare function lockPostgresFlowParent(tx: TransactionSQL, ctx: PostgresContext, parentId: JobId): Promise<void>;
10
+ /** Acquire a flow-parent batch in canonical order with one database round trip. */
11
+ export declare function lockPostgresFlowParents(tx: TransactionSQL, ctx: PostgresContext, parentIds: readonly JobId[]): Promise<void>;
12
+ /** Lock child attachment, then its current parent, before a terminal row mutation. */
13
+ export declare function lockPostgresJobFlowParent(tx: TransactionSQL, ctx: PostgresContext, childId: JobId): Promise<void>;
14
+ /** Apply a terminal child's configured parent policy in the same transaction. */
15
+ export declare function applyPostgresFlowFailure(tx: TransactionSQL, ctx: PostgresContext, child: Job, errorValue: string | undefined, now: number): Promise<PostgresDlqLimitRequest | null>;
16
+ export declare function clearPostgresParentFlowFailures(tx: TransactionSQL, ctx: PostgresContext, parentId: JobId): Promise<void>;
17
+ export declare function getPostgresFlowFailureValues(ctx: PostgresContext, parentId: JobId, mode: 'ignore' | 'continue'): Promise<Record<string, string>>;
@@ -0,0 +1,199 @@
1
+ import { createDlqEntry } from '../../../domain/types/dlq';
2
+ import { MAX_TIMELINE_ENTRIES } from '../../../domain/types/job';
3
+ import { postgresAdvisoryLockName } from './advisoryLocks';
4
+ import { decodePostgresJob, encodePostgresValue } from './codec';
5
+ import { recordPostgresEvent } from './context';
6
+ import { getPostgresQueuePolicies } from './policies';
7
+ import { lockPostgresDependencyCompletions } from './dependencyPromotion';
8
+ const LINKABLE_STATES = [
9
+ 'waiting',
10
+ 'prioritized',
11
+ 'delayed',
12
+ 'waiting-children',
13
+ ];
14
+ function failureMode(job) {
15
+ if (!job.parentId)
16
+ return null;
17
+ if (job.failParentOnFailure)
18
+ return 'fail';
19
+ if (job.continueParentOnFailure)
20
+ return 'continue';
21
+ if (job.ignoreDependencyOnFailure)
22
+ return 'ignore';
23
+ if (job.removeDependencyOnFailure)
24
+ return 'remove';
25
+ return null;
26
+ }
27
+ function readyState(job, now) {
28
+ if (job.runAt > now)
29
+ return 'delayed';
30
+ return job.priority > 0 ? 'prioritized' : 'waiting';
31
+ }
32
+ async function storeFailureValue(input, mode) {
33
+ const { tx, ctx, child, error, now } = input;
34
+ await tx `
35
+ INSERT INTO bunqueue_flow_failures
36
+ (namespace, parent_id, child_id, child_queue, mode, error, created_at)
37
+ VALUES
38
+ (${ctx.config.namespace}, ${String(child.parentId)}, ${String(child.id)}, ${child.queue},
39
+ ${mode}, ${error}, ${now})
40
+ ON CONFLICT (namespace, parent_id, child_id) DO UPDATE SET
41
+ child_queue = excluded.child_queue,
42
+ mode = excluded.mode,
43
+ error = excluded.error,
44
+ created_at = excluded.created_at
45
+ `;
46
+ }
47
+ async function unresolvedCount(tx, ctx, parentId) {
48
+ const [row] = await tx `
49
+ SELECT COUNT(*)::bigint AS count
50
+ FROM bunqueue_dependencies AS dependency
51
+ WHERE dependency.namespace = ${ctx.config.namespace}
52
+ AND dependency.job_id = ${String(parentId)}
53
+ AND NOT EXISTS (
54
+ SELECT 1 FROM bunqueue_completions AS completion
55
+ WHERE completion.namespace = dependency.namespace
56
+ AND completion.job_id = dependency.dependency_id
57
+ )
58
+ `;
59
+ return Number(row.count);
60
+ }
61
+ async function failParent(input) {
62
+ const { tx, ctx, parent, child, error, now } = input;
63
+ const message = `Child job ${String(child.id)} failed: ${error}`;
64
+ parent.completedAt = now;
65
+ if (parent.timeline.length < MAX_TIMELINE_ENTRIES) {
66
+ parent.timeline.push({ state: 'failed', timestamp: now, error: message });
67
+ }
68
+ const { dlq } = await getPostgresQueuePolicies(tx, ctx, parent.queue);
69
+ const entry = createDlqEntry(parent, "unknown" /* FailureReason.Unknown */, message, dlq, now);
70
+ await tx `
71
+ DELETE FROM bunqueue_dependencies
72
+ WHERE namespace = ${ctx.config.namespace} AND job_id = ${String(parent.id)}
73
+ `;
74
+ await tx `
75
+ DELETE FROM bunqueue_flow_failures
76
+ WHERE namespace = ${ctx.config.namespace} AND parent_id = ${String(parent.id)}
77
+ `;
78
+ await tx `
79
+ UPDATE bunqueue_jobs
80
+ SET payload = ${encodePostgresValue(parent)}, state = 'failed', completed_at = ${now},
81
+ error = ${message}, failure_reason = ${"unknown" /* FailureReason.Unknown */},
82
+ dlq_entry = ${encodePostgresValue(entry)}, dlq_retry_state = NULL,
83
+ version = version + 1
84
+ WHERE namespace = ${ctx.config.namespace} AND id = ${String(parent.id)}
85
+ `;
86
+ await recordPostgresEvent(tx, ctx, {
87
+ queue: parent.queue,
88
+ type: 'failed',
89
+ jobId: parent.id,
90
+ occurredAt: now,
91
+ job: parent,
92
+ state: 'failed',
93
+ error: message,
94
+ dlqEntry: entry,
95
+ dlqRetryState: null,
96
+ });
97
+ return { queue: parent.queue, maxEntries: dlq.maxEntries };
98
+ }
99
+ async function releaseDependencies(input, mode) {
100
+ const { tx, ctx, parent, child, now } = input;
101
+ if (mode === 'ignore' || mode === 'continue') {
102
+ await storeFailureValue(input, mode);
103
+ }
104
+ const released = mode === 'continue' ? [...parent.dependsOn] : [child.id];
105
+ const remaining = parent.dependsOn.filter((id) => !released.includes(id));
106
+ await tx `
107
+ DELETE FROM bunqueue_dependencies
108
+ WHERE namespace = ${ctx.config.namespace}
109
+ AND job_id = ${String(parent.id)}
110
+ AND dependency_id = ANY(${tx.array(released.map(String), 'TEXT')})
111
+ `;
112
+ const resolved = (await unresolvedCount(tx, ctx, parent.id)) === 0;
113
+ const updated = { ...parent, dependsOn: remaining };
114
+ const state = resolved ? readyState(updated, now) : 'waiting-children';
115
+ await tx `
116
+ UPDATE bunqueue_jobs
117
+ SET payload = ${encodePostgresValue(updated)}, state = ${state}, version = version + 1
118
+ WHERE namespace = ${ctx.config.namespace} AND id = ${String(parent.id)}
119
+ `;
120
+ if (resolved) {
121
+ await recordPostgresEvent(tx, ctx, {
122
+ queue: parent.queue,
123
+ type: 'retried',
124
+ jobId: parent.id,
125
+ occurredAt: now,
126
+ job: updated,
127
+ state,
128
+ });
129
+ }
130
+ }
131
+ /** Serialize mutations involving one flow parent across brokers. */
132
+ export async function lockPostgresFlowParent(tx, ctx, parentId) {
133
+ await lockPostgresFlowParents(tx, ctx, [parentId]);
134
+ }
135
+ /** Acquire a flow-parent batch in canonical order with one database round trip. */
136
+ export async function lockPostgresFlowParents(tx, ctx, parentIds) {
137
+ const lockNames = [...new Set(parentIds.map(String))].map((id) => postgresAdvisoryLockName('flow', ctx.config.namespace, id));
138
+ if (lockNames.length === 0)
139
+ return;
140
+ await tx `
141
+ WITH ordered_ids AS MATERIALIZED (
142
+ SELECT DISTINCT hashtextextended(lock_name, 0) AS lock_key
143
+ FROM unnest(${tx.array(lockNames, 'TEXT')}) AS parent(lock_name)
144
+ ORDER BY lock_key
145
+ ), locked_ids AS MATERIALIZED (
146
+ SELECT lock_key, pg_advisory_xact_lock(lock_key) AS acquired
147
+ FROM ordered_ids
148
+ ORDER BY lock_key
149
+ )
150
+ SELECT COUNT(*) FROM locked_ids
151
+ `;
152
+ }
153
+ /** Lock child attachment, then its current parent, before a terminal row mutation. */
154
+ export async function lockPostgresJobFlowParent(tx, ctx, childId) {
155
+ await lockPostgresDependencyCompletions(tx, ctx, [childId]);
156
+ const [row] = await tx `
157
+ SELECT parent_id FROM bunqueue_jobs
158
+ WHERE namespace = ${ctx.config.namespace} AND id = ${String(childId)}
159
+ `;
160
+ if (row?.parent_id)
161
+ await lockPostgresFlowParent(tx, ctx, row.parent_id);
162
+ }
163
+ /** Apply a terminal child's configured parent policy in the same transaction. */
164
+ export async function applyPostgresFlowFailure(tx, ctx, child, errorValue, now) {
165
+ const mode = failureMode(child);
166
+ if (!mode || !child.parentId)
167
+ return null;
168
+ const rows = await tx `
169
+ SELECT * FROM bunqueue_jobs
170
+ WHERE namespace = ${ctx.config.namespace} AND id = ${String(child.parentId)}
171
+ FOR UPDATE
172
+ `;
173
+ const row = rows[0];
174
+ if (!row || !LINKABLE_STATES.includes(row.state))
175
+ return null;
176
+ const parent = decodePostgresJob(row).job;
177
+ const error = errorValue ?? 'unknown error';
178
+ const input = { tx, ctx, parent, child, error, now };
179
+ if (mode === 'fail')
180
+ return await failParent(input);
181
+ await releaseDependencies(input, mode);
182
+ return null;
183
+ }
184
+ export async function clearPostgresParentFlowFailures(tx, ctx, parentId) {
185
+ await tx `
186
+ DELETE FROM bunqueue_flow_failures
187
+ WHERE namespace = ${ctx.config.namespace} AND parent_id = ${String(parentId)}
188
+ `;
189
+ }
190
+ export async function getPostgresFlowFailureValues(ctx, parentId, mode) {
191
+ const rows = await ctx.sql `
192
+ SELECT child_id, child_queue, error
193
+ FROM bunqueue_flow_failures
194
+ WHERE namespace = ${ctx.config.namespace}
195
+ AND parent_id = ${String(parentId)} AND mode = ${mode}
196
+ ORDER BY created_at, child_id
197
+ `;
198
+ return Object.fromEntries(rows.map((row) => [`${row.child_queue}:${row.child_id}`, row.error]));
199
+ }
@@ -0,0 +1,15 @@
1
+ import type { TransactionSQL } from 'bun';
2
+ import type { GroupPullOptions } from '../../../domain/types/group';
3
+ import type { PostgresContext } from './context';
4
+ import type { PostgresJobRow } from './types';
5
+ /** Assign durable rotation positions to every pending group lacking one. */
6
+ export declare function ensurePostgresGroupStates(tx: TransactionSQL, ctx: PostgresContext, queue: string, sequence: number): Promise<number>;
7
+ /** Reset fixed windows when they expire or a worker changes the effective defaults. */
8
+ export declare function refreshPostgresGroupRateWindows(tx: TransactionSQL, ctx: PostgresContext, queue: string, options: GroupPullOptions | undefined, now: number): Promise<void>;
9
+ /** Consume group budgets and move the durable round-robin cursor after row locks are secured. */
10
+ export declare function commitPostgresGroupClaims(tx: TransactionSQL, ctx: PostgresContext, input: {
11
+ queue: string;
12
+ rows: readonly PostgresJobRow[];
13
+ options?: GroupPullOptions;
14
+ sequence: number;
15
+ }): Promise<void>;