bunqueue 2.8.60 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (324) hide show
  1. package/README.md +108 -76
  2. package/dist/application/background/dlq.js +2 -0
  3. package/dist/application/contextFactory.js +5 -0
  4. package/dist/application/dlqManager.d.ts +10 -0
  5. package/dist/application/dlqManager.js +47 -9
  6. package/dist/application/dlqRetry.js +59 -38
  7. package/dist/application/eventsManager.d.ts +1 -1
  8. package/dist/application/eventsManager.js +30 -26
  9. package/dist/application/operations/jobManagement.d.ts +4 -0
  10. package/dist/application/operations/jobMoveOperations.js +9 -4
  11. package/dist/application/postgres-queue-manager/batchSnapshot.d.ts +16 -0
  12. package/dist/application/postgres-queue-manager/batchSnapshot.js +17 -0
  13. package/dist/application/postgres-queue-manager/cloud.d.ts +30 -0
  14. package/dist/application/postgres-queue-manager/cloud.js +55 -0
  15. package/dist/application/postgres-queue-manager/config.d.ts +5 -0
  16. package/dist/application/postgres-queue-manager/config.js +1 -0
  17. package/dist/application/postgres-queue-manager/control.d.ts +26 -0
  18. package/dist/application/postgres-queue-manager/control.js +186 -0
  19. package/dist/application/postgres-queue-manager/deferredWrites.d.ts +13 -0
  20. package/dist/application/postgres-queue-manager/deferredWrites.js +60 -0
  21. package/dist/application/postgres-queue-manager/delivery.d.ts +19 -0
  22. package/dist/application/postgres-queue-manager/delivery.js +80 -0
  23. package/dist/application/postgres-queue-manager/lease.d.ts +13 -0
  24. package/dist/application/postgres-queue-manager/lease.js +88 -0
  25. package/dist/application/postgres-queue-manager/lifetimeMetrics.d.ts +32 -0
  26. package/dist/application/postgres-queue-manager/lifetimeMetrics.js +53 -0
  27. package/dist/application/postgres-queue-manager/maintenance.d.ts +14 -0
  28. package/dist/application/postgres-queue-manager/maintenance.js +100 -0
  29. package/dist/application/postgres-queue-manager/operationGate.d.ts +26 -0
  30. package/dist/application/postgres-queue-manager/operationGate.js +96 -0
  31. package/dist/application/postgres-queue-manager/operations.d.ts +25 -0
  32. package/dist/application/postgres-queue-manager/operations.js +194 -0
  33. package/dist/application/postgres-queue-manager/projectionRefreshes.d.ts +43 -0
  34. package/dist/application/postgres-queue-manager/projectionRefreshes.js +170 -0
  35. package/dist/application/postgres-queue-manager/queries.d.ts +142 -0
  36. package/dist/application/postgres-queue-manager/queries.js +231 -0
  37. package/dist/application/postgres-queue-manager/relationships.d.ts +10 -0
  38. package/dist/application/postgres-queue-manager/relationships.js +45 -0
  39. package/dist/application/postgres-queue-manager/services.d.ts +31 -0
  40. package/dist/application/postgres-queue-manager/services.js +149 -0
  41. package/dist/application/postgres-queue-manager/snapshot.d.ts +51 -0
  42. package/dist/application/postgres-queue-manager/snapshot.js +236 -0
  43. package/dist/application/postgres-queue-manager/snapshotViews.d.ts +15 -0
  44. package/dist/application/postgres-queue-manager/snapshotViews.js +100 -0
  45. package/dist/application/postgres-queue-manager/startupEventBuffer.d.ts +12 -0
  46. package/dist/application/postgres-queue-manager/startupEventBuffer.js +36 -0
  47. package/dist/application/postgres-queue-manager/state.d.ts +47 -0
  48. package/dist/application/postgres-queue-manager/state.js +273 -0
  49. package/dist/application/postgres-queue-manager/terminalDelivery.d.ts +20 -0
  50. package/dist/application/postgres-queue-manager/terminalDelivery.js +100 -0
  51. package/dist/application/postgresQueueManager.d.ts +2 -0
  52. package/dist/application/postgresQueueManager.js +1 -0
  53. package/dist/application/queue-manager/flow-failures.js +4 -0
  54. package/dist/application/queue-manager/limits.d.ts +2 -0
  55. package/dist/application/queue-manager/limits.js +4 -0
  56. package/dist/application/queue-manager/observability.js +15 -3
  57. package/dist/application/queue-manager/queries.d.ts +7 -0
  58. package/dist/application/queue-manager/queries.js +9 -0
  59. package/dist/application/queue-manager/services.d.ts +1 -1
  60. package/dist/application/queue-manager/services.js +4 -2
  61. package/dist/application/queue-manager/state.js +16 -1
  62. package/dist/cli/commands/server.js +1 -1
  63. package/dist/client/forwarder.d.ts +6 -4
  64. package/dist/client/forwarder.js +5 -3
  65. package/dist/client/queue/dlq.d.ts +2 -0
  66. package/dist/client/queue/dlq.js +14 -0
  67. package/dist/client/queue/dlqOps.d.ts +2 -0
  68. package/dist/client/queue/dlqOps.js +4 -0
  69. package/dist/client/queue/helpers.js +2 -0
  70. package/dist/client/queue/runtime/configuration.d.ts +4 -0
  71. package/dist/client/queue/runtime/configuration.js +8 -0
  72. package/dist/client/worker/runtime/execution.js +3 -8
  73. package/dist/client/worker/runtime/polling.d.ts +1 -0
  74. package/dist/client/worker/runtime/polling.js +9 -0
  75. package/dist/config/resolve.d.ts +14 -0
  76. package/dist/config/resolve.js +50 -5
  77. package/dist/config/types.d.ts +18 -0
  78. package/dist/domain/queue/dlqShard.d.ts +2 -0
  79. package/dist/domain/queue/dlqShard.js +16 -0
  80. package/dist/domain/queue/shard/dlq.d.ts +1 -0
  81. package/dist/domain/queue/shard/dlq.js +3 -0
  82. package/dist/domain/types/commands/dlq.d.ts +5 -0
  83. package/dist/domain/types/commands/union.d.ts +1 -1
  84. package/dist/domain/types/cron.d.ts +5 -0
  85. package/dist/domain/types/cron.js +14 -3
  86. package/dist/domain/types/dlq.d.ts +1 -1
  87. package/dist/domain/types/dlq.js +1 -2
  88. package/dist/domain/types/jobs/model.d.ts +1 -1
  89. package/dist/infrastructure/cloud/commandHandler.js +5 -3
  90. package/dist/infrastructure/cloud/commands/integrations.js +11 -11
  91. package/dist/infrastructure/cloud/commands/jobs.js +48 -40
  92. package/dist/infrastructure/cloud/commands/queues.js +61 -75
  93. package/dist/infrastructure/cloud/queueAdapter/local.d.ts +41 -0
  94. package/dist/infrastructure/cloud/queueAdapter/local.js +187 -0
  95. package/dist/infrastructure/cloud/queueAdapter/postgres.d.ts +42 -0
  96. package/dist/infrastructure/cloud/queueAdapter/postgres.js +188 -0
  97. package/dist/infrastructure/cloud/queueAdapter/registry.d.ts +4 -0
  98. package/dist/infrastructure/cloud/queueAdapter/registry.js +15 -0
  99. package/dist/infrastructure/cloud/queueAdapter/types.d.ts +87 -0
  100. package/dist/infrastructure/cloud/queueAdapter/types.js +1 -0
  101. package/dist/infrastructure/cloud/snapshot/analytics.d.ts +2 -0
  102. package/dist/infrastructure/cloud/snapshot/analytics.js +7 -0
  103. package/dist/infrastructure/cloud/snapshot/collector.d.ts +4 -0
  104. package/dist/infrastructure/cloud/snapshot/collector.js +39 -1
  105. package/dist/infrastructure/cloud/snapshot/config.d.ts +3 -0
  106. package/dist/infrastructure/cloud/snapshot/config.js +43 -0
  107. package/dist/infrastructure/cloud/snapshot/jobs.d.ts +3 -0
  108. package/dist/infrastructure/cloud/snapshot/jobs.js +32 -1
  109. package/dist/infrastructure/cloud/snapshotCollector.js +20 -35
  110. package/dist/infrastructure/cloud/snapshotHelpers.d.ts +3 -3
  111. package/dist/infrastructure/cloud/snapshotHelpers.js +3 -3
  112. package/dist/infrastructure/cloud/statsRefresh.js +2 -1
  113. package/dist/infrastructure/cloud/types/command.d.ts +2 -2
  114. package/dist/infrastructure/persistence/postgres/admission.d.ts +18 -0
  115. package/dist/infrastructure/persistence/postgres/admission.js +193 -0
  116. package/dist/infrastructure/persistence/postgres/admissionParent.d.ts +5 -0
  117. package/dist/infrastructure/persistence/postgres/admissionParent.js +35 -0
  118. package/dist/infrastructure/persistence/postgres/admissionResult.d.ts +9 -0
  119. package/dist/infrastructure/persistence/postgres/admissionResult.js +1 -0
  120. package/dist/infrastructure/persistence/postgres/admissionStore.d.ts +12 -0
  121. package/dist/infrastructure/persistence/postgres/admissionStore.js +101 -0
  122. package/dist/infrastructure/persistence/postgres/advisoryLocks.d.ts +2 -0
  123. package/dist/infrastructure/persistence/postgres/advisoryLocks.js +13 -0
  124. package/dist/infrastructure/persistence/postgres/batchAdmission.d.ts +11 -0
  125. package/dist/infrastructure/persistence/postgres/batchAdmission.js +110 -0
  126. package/dist/infrastructure/persistence/postgres/batchCompletion.d.ts +4 -0
  127. package/dist/infrastructure/persistence/postgres/batchCompletion.js +174 -0
  128. package/dist/infrastructure/persistence/postgres/batchEvents.d.ts +14 -0
  129. package/dist/infrastructure/persistence/postgres/batchEvents.js +72 -0
  130. package/dist/infrastructure/persistence/postgres/brokerSessions.d.ts +14 -0
  131. package/dist/infrastructure/persistence/postgres/brokerSessions.js +94 -0
  132. package/dist/infrastructure/persistence/postgres/claimBatch.d.ts +11 -0
  133. package/dist/infrastructure/persistence/postgres/claimBatch.js +56 -0
  134. package/dist/infrastructure/persistence/postgres/claimSelection.d.ts +4 -0
  135. package/dist/infrastructure/persistence/postgres/claimSelection.js +198 -0
  136. package/dist/infrastructure/persistence/postgres/claims.d.ts +3 -0
  137. package/dist/infrastructure/persistence/postgres/claims.js +137 -0
  138. package/dist/infrastructure/persistence/postgres/cloudReadModel.d.ts +26 -0
  139. package/dist/infrastructure/persistence/postgres/cloudReadModel.js +123 -0
  140. package/dist/infrastructure/persistence/postgres/codec.d.ts +30 -0
  141. package/dist/infrastructure/persistence/postgres/codec.js +82 -0
  142. package/dist/infrastructure/persistence/postgres/completionEvents.d.ts +11 -0
  143. package/dist/infrastructure/persistence/postgres/completionEvents.js +21 -0
  144. package/dist/infrastructure/persistence/postgres/completionLifecycle.d.ts +11 -0
  145. package/dist/infrastructure/persistence/postgres/completionLifecycle.js +145 -0
  146. package/dist/infrastructure/persistence/postgres/completionOutcome.d.ts +4 -0
  147. package/dist/infrastructure/persistence/postgres/completionOutcome.js +112 -0
  148. package/dist/infrastructure/persistence/postgres/completionQueries.d.ts +10 -0
  149. package/dist/infrastructure/persistence/postgres/completionQueries.js +87 -0
  150. package/dist/infrastructure/persistence/postgres/connection.d.ts +3 -0
  151. package/dist/infrastructure/persistence/postgres/connection.js +15 -0
  152. package/dist/infrastructure/persistence/postgres/context.d.ts +28 -0
  153. package/dist/infrastructure/persistence/postgres/context.js +74 -0
  154. package/dist/infrastructure/persistence/postgres/control.d.ts +23 -0
  155. package/dist/infrastructure/persistence/postgres/control.js +105 -0
  156. package/dist/infrastructure/persistence/postgres/crons.d.ts +18 -0
  157. package/dist/infrastructure/persistence/postgres/crons.js +205 -0
  158. package/dist/infrastructure/persistence/postgres/deduplication.d.ts +9 -0
  159. package/dist/infrastructure/persistence/postgres/deduplication.js +47 -0
  160. package/dist/infrastructure/persistence/postgres/dependencyDestruction.d.ts +14 -0
  161. package/dist/infrastructure/persistence/postgres/dependencyDestruction.js +74 -0
  162. package/dist/infrastructure/persistence/postgres/dependencyPromotion.d.ts +29 -0
  163. package/dist/infrastructure/persistence/postgres/dependencyPromotion.js +212 -0
  164. package/dist/infrastructure/persistence/postgres/destructiveMutations.d.ts +4 -0
  165. package/dist/infrastructure/persistence/postgres/destructiveMutations.js +111 -0
  166. package/dist/infrastructure/persistence/postgres/dlqLifecycle.d.ts +13 -0
  167. package/dist/infrastructure/persistence/postgres/dlqLifecycle.js +184 -0
  168. package/dist/infrastructure/persistence/postgres/dlqMaintenance.d.ts +6 -0
  169. package/dist/infrastructure/persistence/postgres/dlqMaintenance.js +36 -0
  170. package/dist/infrastructure/persistence/postgres/dlqRetryPlan.d.ts +21 -0
  171. package/dist/infrastructure/persistence/postgres/dlqRetryPlan.js +92 -0
  172. package/dist/infrastructure/persistence/postgres/eventCommitGc.d.ts +27 -0
  173. package/dist/infrastructure/persistence/postgres/eventCommitGc.js +62 -0
  174. package/dist/infrastructure/persistence/postgres/eventJournal.d.ts +18 -0
  175. package/dist/infrastructure/persistence/postgres/eventJournal.js +76 -0
  176. package/dist/infrastructure/persistence/postgres/eventJournalSchema.d.ts +5 -0
  177. package/dist/infrastructure/persistence/postgres/eventJournalSchema.js +253 -0
  178. package/dist/infrastructure/persistence/postgres/eventPruneWatermarks.d.ts +24 -0
  179. package/dist/infrastructure/persistence/postgres/eventPruneWatermarks.js +111 -0
  180. package/dist/infrastructure/persistence/postgres/eventRetention.d.ts +18 -0
  181. package/dist/infrastructure/persistence/postgres/eventRetention.js +76 -0
  182. package/dist/infrastructure/persistence/postgres/events.d.ts +45 -0
  183. package/dist/infrastructure/persistence/postgres/events.js +249 -0
  184. package/dist/infrastructure/persistence/postgres/expiry.d.ts +3 -0
  185. package/dist/infrastructure/persistence/postgres/expiry.js +74 -0
  186. package/dist/infrastructure/persistence/postgres/flowFailures.d.ts +17 -0
  187. package/dist/infrastructure/persistence/postgres/flowFailures.js +199 -0
  188. package/dist/infrastructure/persistence/postgres/jobData.d.ts +3 -0
  189. package/dist/infrastructure/persistence/postgres/jobData.js +32 -0
  190. package/dist/infrastructure/persistence/postgres/leaseRelease.d.ts +9 -0
  191. package/dist/infrastructure/persistence/postgres/leaseRelease.js +120 -0
  192. package/dist/infrastructure/persistence/postgres/leaseRenewal.d.ts +4 -0
  193. package/dist/infrastructure/persistence/postgres/leaseRenewal.js +35 -0
  194. package/dist/infrastructure/persistence/postgres/lifetimeMetrics.d.ts +15 -0
  195. package/dist/infrastructure/persistence/postgres/lifetimeMetrics.js +46 -0
  196. package/dist/infrastructure/persistence/postgres/lifetimeMetricsFinalizer.d.ts +4 -0
  197. package/dist/infrastructure/persistence/postgres/lifetimeMetricsFinalizer.js +13 -0
  198. package/dist/infrastructure/persistence/postgres/logs.d.ts +6 -0
  199. package/dist/infrastructure/persistence/postgres/logs.js +70 -0
  200. package/dist/infrastructure/persistence/postgres/maintenance.d.ts +6 -0
  201. package/dist/infrastructure/persistence/postgres/maintenance.js +138 -0
  202. package/dist/infrastructure/persistence/postgres/maintenanceFlights.d.ts +14 -0
  203. package/dist/infrastructure/persistence/postgres/maintenanceFlights.js +66 -0
  204. package/dist/infrastructure/persistence/postgres/metricWrites.d.ts +9 -0
  205. package/dist/infrastructure/persistence/postgres/metricWrites.js +94 -0
  206. package/dist/infrastructure/persistence/postgres/mutations.d.ts +9 -0
  207. package/dist/infrastructure/persistence/postgres/mutations.js +171 -0
  208. package/dist/infrastructure/persistence/postgres/outcomes.d.ts +4 -0
  209. package/dist/infrastructure/persistence/postgres/outcomes.js +194 -0
  210. package/dist/infrastructure/persistence/postgres/policies.d.ts +11 -0
  211. package/dist/infrastructure/persistence/postgres/policies.js +18 -0
  212. package/dist/infrastructure/persistence/postgres/postCommitMaintenance.d.ts +17 -0
  213. package/dist/infrastructure/persistence/postgres/postCommitMaintenance.js +117 -0
  214. package/dist/infrastructure/persistence/postgres/promotion.d.ts +3 -0
  215. package/dist/infrastructure/persistence/postgres/promotion.js +43 -0
  216. package/dist/infrastructure/persistence/postgres/queries.d.ts +22 -0
  217. package/dist/infrastructure/persistence/postgres/queries.js +152 -0
  218. package/dist/infrastructure/persistence/postgres/queueDestruction.d.ts +3 -0
  219. package/dist/infrastructure/persistence/postgres/queueDestruction.js +154 -0
  220. package/dist/infrastructure/persistence/postgres/queueLifecycle.d.ts +10 -0
  221. package/dist/infrastructure/persistence/postgres/queueLifecycle.js +60 -0
  222. package/dist/infrastructure/persistence/postgres/rateLimit.d.ts +6 -0
  223. package/dist/infrastructure/persistence/postgres/rateLimit.js +10 -0
  224. package/dist/infrastructure/persistence/postgres/readModels.d.ts +32 -0
  225. package/dist/infrastructure/persistence/postgres/readModels.js +72 -0
  226. package/dist/infrastructure/persistence/postgres/recovery.d.ts +3 -0
  227. package/dist/infrastructure/persistence/postgres/recovery.js +178 -0
  228. package/dist/infrastructure/persistence/postgres/relationships.d.ts +9 -0
  229. package/dist/infrastructure/persistence/postgres/relationships.js +201 -0
  230. package/dist/infrastructure/persistence/postgres/removeUnprocessedChildren.d.ts +4 -0
  231. package/dist/infrastructure/persistence/postgres/removeUnprocessedChildren.js +241 -0
  232. package/dist/infrastructure/persistence/postgres/repeatMutations.d.ts +5 -0
  233. package/dist/infrastructure/persistence/postgres/repeatMutations.js +37 -0
  234. package/dist/infrastructure/persistence/postgres/runtime.d.ts +46 -0
  235. package/dist/infrastructure/persistence/postgres/runtime.js +236 -0
  236. package/dist/infrastructure/persistence/postgres/runtimeConfig.d.ts +21 -0
  237. package/dist/infrastructure/persistence/postgres/runtimeConfig.js +39 -0
  238. package/dist/infrastructure/persistence/postgres/schema.d.ts +4 -0
  239. package/dist/infrastructure/persistence/postgres/schema.js +257 -0
  240. package/dist/infrastructure/persistence/postgres/schemaInitialization.d.ts +3 -0
  241. package/dist/infrastructure/persistence/postgres/schemaInitialization.js +221 -0
  242. package/dist/infrastructure/persistence/postgres/serialAdmission.d.ts +6 -0
  243. package/dist/infrastructure/persistence/postgres/serialAdmission.js +96 -0
  244. package/dist/infrastructure/persistence/postgres/snapshotBudget.d.ts +3 -0
  245. package/dist/infrastructure/persistence/postgres/snapshotBudget.js +83 -0
  246. package/dist/infrastructure/persistence/postgres/storageHealth.d.ts +10 -0
  247. package/dist/infrastructure/persistence/postgres/storageHealth.js +29 -0
  248. package/dist/infrastructure/persistence/postgres/store.d.ts +90 -0
  249. package/dist/infrastructure/persistence/postgres/store.js +136 -0
  250. package/dist/infrastructure/persistence/postgres/telemetry.d.ts +6 -0
  251. package/dist/infrastructure/persistence/postgres/telemetry.js +88 -0
  252. package/dist/infrastructure/persistence/postgres/terminal.d.ts +8 -0
  253. package/dist/infrastructure/persistence/postgres/terminal.js +137 -0
  254. package/dist/infrastructure/persistence/postgres/transactionRetry.d.ts +6 -0
  255. package/dist/infrastructure/persistence/postgres/transactionRetry.js +42 -0
  256. package/dist/infrastructure/persistence/postgres/types.d.ts +175 -0
  257. package/dist/infrastructure/persistence/postgres/types.js +1 -0
  258. package/dist/infrastructure/persistence/postgres/workers.d.ts +15 -0
  259. package/dist/infrastructure/persistence/postgres/workers.js +126 -0
  260. package/dist/infrastructure/persistence/postgres.d.ts +2 -0
  261. package/dist/infrastructure/persistence/postgres.js +1 -0
  262. package/dist/infrastructure/persistence/sqlite/jobs.js +2 -0
  263. package/dist/infrastructure/scheduler/cron/persisted.d.ts +5 -0
  264. package/dist/infrastructure/scheduler/cron/persisted.js +27 -0
  265. package/dist/infrastructure/scheduler/cron/runtime.js +5 -10
  266. package/dist/infrastructure/scheduler/cron/validation.d.ts +3 -0
  267. package/dist/infrastructure/scheduler/cron/validation.js +11 -0
  268. package/dist/infrastructure/scheduler/cronParser.d.ts +1 -1
  269. package/dist/infrastructure/scheduler/cronParser.js +144 -11
  270. package/dist/infrastructure/server/bootstrap.d.ts +2 -3
  271. package/dist/infrastructure/server/bootstrap.js +33 -59
  272. package/dist/infrastructure/server/errors.d.ts +4 -0
  273. package/dist/infrastructure/server/errors.js +54 -0
  274. package/dist/infrastructure/server/handler-routes/control.d.ts +5 -5
  275. package/dist/infrastructure/server/handler-routes/control.js +3 -1
  276. package/dist/infrastructure/server/handler-routes/monitoring.d.ts +2 -2
  277. package/dist/infrastructure/server/handler.js +9 -11
  278. package/dist/infrastructure/server/handlers/advanced/dependencies.js +7 -6
  279. package/dist/infrastructure/server/handlers/advanced/jobs.js +19 -6
  280. package/dist/infrastructure/server/handlers/advanced/queue.d.ts +9 -9
  281. package/dist/infrastructure/server/handlers/advanced/queue.js +91 -27
  282. package/dist/infrastructure/server/handlers/core.js +32 -31
  283. package/dist/infrastructure/server/handlers/cron.d.ts +4 -4
  284. package/dist/infrastructure/server/handlers/cron.js +60 -59
  285. package/dist/infrastructure/server/handlers/dashboard.d.ts +1 -1
  286. package/dist/infrastructure/server/handlers/dashboard.js +21 -8
  287. package/dist/infrastructure/server/handlers/dlq.d.ts +6 -3
  288. package/dist/infrastructure/server/handlers/dlq.js +35 -9
  289. package/dist/infrastructure/server/handlers/flow.js +2 -1
  290. package/dist/infrastructure/server/handlers/management.d.ts +5 -5
  291. package/dist/infrastructure/server/handlers/management.js +36 -9
  292. package/dist/infrastructure/server/handlers/monitoring/health.d.ts +5 -5
  293. package/dist/infrastructure/server/handlers/monitoring/health.js +45 -16
  294. package/dist/infrastructure/server/handlers/monitoring/operations.d.ts +1 -1
  295. package/dist/infrastructure/server/handlers/monitoring/operations.js +8 -1
  296. package/dist/infrastructure/server/handlers/monitoring/workers.d.ts +3 -3
  297. package/dist/infrastructure/server/handlers/monitoring/workers.js +31 -7
  298. package/dist/infrastructure/server/handlers/pushBatchValidation.d.ts +3 -1
  299. package/dist/infrastructure/server/handlers/pushBatchValidation.js +52 -7
  300. package/dist/infrastructure/server/handlers/query.d.ts +1 -1
  301. package/dist/infrastructure/server/handlers/query.js +5 -4
  302. package/dist/infrastructure/server/http.js +2 -2
  303. package/dist/infrastructure/server/httpDashboardEndpoints.d.ts +1 -1
  304. package/dist/infrastructure/server/httpDashboardEndpoints.js +19 -6
  305. package/dist/infrastructure/server/httpEndpoints.js +18 -7
  306. package/dist/infrastructure/server/httpRouteQueues.js +11 -1
  307. package/dist/infrastructure/server/shutdownCoordinator.d.ts +24 -0
  308. package/dist/infrastructure/server/shutdownCoordinator.js +106 -0
  309. package/dist/infrastructure/server/sseHandler.js +8 -3
  310. package/dist/infrastructure/server/storageAdapter.d.ts +29 -0
  311. package/dist/infrastructure/server/storageAdapter.js +61 -0
  312. package/dist/infrastructure/server/storageManager.d.ts +12 -0
  313. package/dist/infrastructure/server/storageManager.js +102 -0
  314. package/dist/infrastructure/server/tcp.js +2 -3
  315. package/dist/infrastructure/server/ws/snapshots.d.ts +1 -1
  316. package/dist/infrastructure/server/ws/snapshots.js +19 -4
  317. package/dist/infrastructure/server/wsHandler.js +10 -5
  318. package/dist/main.js +1 -1
  319. package/dist/mcp/backend/embedded/services.js +2 -1
  320. package/dist/mcp/index.d.ts +2 -2
  321. package/dist/mcp/index.js +2 -2
  322. package/dist/shared/storageHealth.d.ts +9 -0
  323. package/dist/shared/storageHealth.js +12 -0
  324. package/package.json +74 -65
@@ -0,0 +1,88 @@
1
+ import { DEFAULT_LOCK_TTL, jobId, lockToken, } from '../../domain/types/job';
2
+ import { PostgresQueueManagerDelivery } from './delivery';
3
+ export class PostgresQueueManagerLease extends PostgresQueueManagerDelivery {
4
+ async extendLock(id, token, duration) {
5
+ return await this.runPostgresOperation(async () => {
6
+ await this.postgresReady;
7
+ const target = jobId(String(id));
8
+ const leaseToken = token ?? this.tokenFor(target);
9
+ if (!leaseToken)
10
+ return false;
11
+ const expiresAt = await this.postgresStore.renew(target, leaseToken, duration);
12
+ if (expiresAt !== null) {
13
+ await this.refreshJob(target);
14
+ return true;
15
+ }
16
+ this.forgetToken(target);
17
+ await this.refreshJob(target);
18
+ return false;
19
+ });
20
+ }
21
+ async heartbeatDurable(id, token, duration) {
22
+ return await this.runPostgresOperation(async () => {
23
+ const leaseToken = this.tokenFor(id, token);
24
+ if (!leaseToken)
25
+ return false;
26
+ return await this.extendLock(id, leaseToken, duration ?? this.postgresStore.config.leaseDurationMs);
27
+ });
28
+ }
29
+ async heartbeatBatchDurable(ids, tokens) {
30
+ return await this.runPostgresOperation(async () => {
31
+ const renewed = await Promise.all(ids.map((id, index) => this.heartbeatDurable(id, tokens?.[index])));
32
+ return renewed.filter(Boolean).length;
33
+ });
34
+ }
35
+ jobHeartbeat(id, token) {
36
+ return this.operations.runSync(() => {
37
+ const leaseToken = this.tokenFor(id, token);
38
+ const row = this.postgresSnapshot.get(id);
39
+ if (!leaseToken || row?.state !== 'active')
40
+ return false;
41
+ this.enqueueWrite(async () => {
42
+ const renewed = await this.postgresStore.renew(id, leaseToken, this.postgresStore.config.leaseDurationMs);
43
+ if (renewed !== null)
44
+ await this.refreshJob(id);
45
+ });
46
+ return true;
47
+ });
48
+ }
49
+ jobHeartbeatBatch(ids, tokens) {
50
+ return this.operations.runSync(() => ids.reduce((count, id, index) => count + (this.jobHeartbeat(id, tokens?.[index]) ? 1 : 0), 0));
51
+ }
52
+ verifyLock(id, token) {
53
+ const row = this.postgresSnapshot.get(id);
54
+ return row?.state === 'active' && this.tokenFor(id) === token;
55
+ }
56
+ renewJobLock(id, token, ttl = DEFAULT_LOCK_TTL) {
57
+ return this.operations.runSync(() => {
58
+ if (!this.verifyLock(id, token))
59
+ return false;
60
+ this.enqueueWrite(async () => {
61
+ const renewed = await this.postgresStore.renew(id, token, ttl);
62
+ if (renewed !== null)
63
+ await this.refreshJob(id);
64
+ });
65
+ return true;
66
+ });
67
+ }
68
+ getLockInfo(id) {
69
+ const row = this.postgresSnapshot.get(id);
70
+ const token = this.tokenFor(id);
71
+ if (row?.state !== 'active' || !token || row.leaseUntil === null)
72
+ return null;
73
+ return {
74
+ jobId: id,
75
+ token: lockToken(token),
76
+ owner: row.leaseOwner ?? this.postgresStore.config.brokerId,
77
+ createdAt: row.job.startedAt ?? Date.now(),
78
+ expiresAt: row.leaseUntil,
79
+ lastRenewalAt: row.job.lastHeartbeat,
80
+ renewalCount: row.leaseRenewals,
81
+ ttl: Math.max(1, row.leaseUntil - row.job.lastHeartbeat),
82
+ };
83
+ }
84
+ createLock(id, _owner, _ttl = DEFAULT_LOCK_TTL) {
85
+ const token = this.tokenFor(id);
86
+ return token ? lockToken(token) : null;
87
+ }
88
+ }
@@ -0,0 +1,32 @@
1
+ import { EventType } from '../../domain/types/queue';
2
+ import type { PostgresStoreEvent } from '../../infrastructure/persistence/postgres';
3
+ import type { PostgresLifetimeMetricsSnapshot } from '../../infrastructure/persistence/postgres/lifetimeMetrics';
4
+ interface PostgresMetricCounters {
5
+ readonly totalPushed: {
6
+ value: bigint;
7
+ };
8
+ readonly totalPulled: {
9
+ value: bigint;
10
+ };
11
+ readonly totalCompleted: {
12
+ value: bigint;
13
+ };
14
+ readonly totalFailed: {
15
+ value: bigint;
16
+ };
17
+ }
18
+ interface PostgresPerQueueMetrics {
19
+ clear(): void;
20
+ get(queue: string): {
21
+ totalCompleted: bigint;
22
+ totalFailed: bigint;
23
+ } | undefined;
24
+ set(queue: string, totals: {
25
+ totalCompleted: bigint;
26
+ totalFailed: bigint;
27
+ }): unknown;
28
+ }
29
+ export declare function postgresEventType(value: string): EventType | null;
30
+ export declare function hydratePostgresLifetimeMetrics(metrics: PostgresMetricCounters, perQueue: PostgresPerQueueMetrics, snapshot: PostgresLifetimeMetricsSnapshot): void;
31
+ export declare function applyPostgresEventMetrics(metrics: PostgresMetricCounters, perQueue: PostgresPerQueueMetrics, event: PostgresStoreEvent, includeTerminal: boolean): void;
32
+ export {};
@@ -0,0 +1,53 @@
1
+ export function postgresEventType(value) {
2
+ switch (value) {
3
+ case "pushed" /* EventType.Pushed */:
4
+ case "pulled" /* EventType.Pulled */:
5
+ case "completed" /* EventType.Completed */:
6
+ case "failed" /* EventType.Failed */:
7
+ case "progress" /* EventType.Progress */:
8
+ case "stalled" /* EventType.Stalled */:
9
+ case "removed" /* EventType.Removed */:
10
+ case "delayed" /* EventType.Delayed */:
11
+ case "duplicated" /* EventType.Duplicated */:
12
+ case "retried" /* EventType.Retried */:
13
+ case "waiting-children" /* EventType.WaitingChildren */:
14
+ case "drained" /* EventType.Drained */:
15
+ case "paused" /* EventType.Paused */:
16
+ case "resumed" /* EventType.Resumed */:
17
+ return value;
18
+ default:
19
+ return null;
20
+ }
21
+ }
22
+ export function hydratePostgresLifetimeMetrics(metrics, perQueue, snapshot) {
23
+ metrics.totalCompleted.value = snapshot.totalCompleted;
24
+ metrics.totalFailed.value = snapshot.totalFailed;
25
+ perQueue.clear();
26
+ for (const totals of snapshot.queues) {
27
+ perQueue.set(totals.queue, {
28
+ totalCompleted: totals.totalCompleted,
29
+ totalFailed: totals.totalFailed,
30
+ });
31
+ }
32
+ }
33
+ export function applyPostgresEventMetrics(metrics, perQueue, event, includeTerminal) {
34
+ const type = postgresEventType(event.type);
35
+ if (type === "pushed" /* EventType.Pushed */)
36
+ metrics.totalPushed.value++;
37
+ if (type === "pulled" /* EventType.Pulled */)
38
+ metrics.totalPulled.value++;
39
+ const completed = includeTerminal && type === "completed" /* EventType.Completed */;
40
+ const failed = includeTerminal && type === "failed" /* EventType.Failed */ && event.state === 'failed';
41
+ if (!completed && !failed)
42
+ return;
43
+ const totals = perQueue.get(event.queue) ?? { totalCompleted: 0n, totalFailed: 0n };
44
+ if (completed) {
45
+ metrics.totalCompleted.value++;
46
+ totals.totalCompleted++;
47
+ }
48
+ if (failed) {
49
+ metrics.totalFailed.value++;
50
+ totals.totalFailed++;
51
+ }
52
+ perQueue.set(event.queue, totals);
53
+ }
@@ -0,0 +1,14 @@
1
+ import type { DlqFilter } from '../../domain/types/dlq';
2
+ import type { JobId } from '../../domain/types/job';
3
+ import { PostgresQueueManagerRelationships } from './relationships';
4
+ /** Durable maintenance commands that cannot use the synchronous SQLite façade. */
5
+ export declare class PostgresQueueManagerMaintenance extends PostgresQueueManagerRelationships {
6
+ retryDlqDurable(queue: string, id?: JobId, count?: number, filter?: DlqFilter): Promise<number>;
7
+ purgeDlqDurable(queue: string): Promise<number>;
8
+ removeDlqJobDurable(queue: string, id: JobId): Promise<boolean>;
9
+ retryCompletedDurable(queue: string, id?: JobId, options?: {
10
+ limit?: number;
11
+ timestamp?: number;
12
+ }): Promise<number>;
13
+ cleanDurable(queue: string, graceMs: number, state?: string, limit?: number): Promise<JobId[]>;
14
+ }
@@ -0,0 +1,100 @@
1
+ import { PostgresQueueManagerRelationships } from './relationships';
2
+ function matchesFilter(entry, filter, now) {
3
+ if (filter.reason && entry.reason !== filter.reason)
4
+ return false;
5
+ if (filter.olderThan !== undefined && entry.enteredAt >= filter.olderThan)
6
+ return false;
7
+ if (filter.newerThan !== undefined && entry.enteredAt <= filter.newerThan)
8
+ return false;
9
+ if (filter.expired !== undefined &&
10
+ (entry.expiresAt !== null && entry.expiresAt <= now) !== filter.expired) {
11
+ return false;
12
+ }
13
+ return true;
14
+ }
15
+ function boundedLimit(value) {
16
+ if (value === undefined)
17
+ return Number.MAX_SAFE_INTEGER;
18
+ return Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
19
+ }
20
+ /** Durable maintenance commands that cannot use the synchronous SQLite façade. */
21
+ export class PostgresQueueManagerMaintenance extends PostgresQueueManagerRelationships {
22
+ async retryDlqDurable(queue, id, count, filter) {
23
+ return await this.runPostgresOperation(async () => {
24
+ await this.postgresReady;
25
+ const limit = boundedLimit(count ?? filter?.limit);
26
+ if (limit === 0)
27
+ return 0;
28
+ const now = await this.postgresStore.now();
29
+ let entries = await this.postgresStore.getDlq(queue, 2_147_483_647);
30
+ if (id)
31
+ entries = entries.filter((entry) => entry.job.id === id);
32
+ if (filter)
33
+ entries = entries.filter((entry) => matchesFilter(entry, filter, now));
34
+ const offset = Math.max(0, filter?.offset ?? 0);
35
+ entries = entries.slice(offset, offset + limit);
36
+ let retried = 0;
37
+ for (const entry of entries) {
38
+ if (await this.postgresStore.retry(entry.job.id))
39
+ retried++;
40
+ }
41
+ if (retried > 0)
42
+ await this.refreshQueueAfterCommit(queue);
43
+ return retried;
44
+ });
45
+ }
46
+ async purgeDlqDurable(queue) {
47
+ return await this.runPostgresOperation(async () => {
48
+ await this.postgresReady;
49
+ const ids = await this.postgresStore.purgeDlq(queue);
50
+ if (ids.length > 0)
51
+ await this.refreshQueueAfterCommit(queue);
52
+ return ids.length;
53
+ });
54
+ }
55
+ async removeDlqJobDurable(queue, id) {
56
+ return await this.runPostgresOperation(async () => {
57
+ await this.postgresReady;
58
+ const removed = await this.postgresStore.removeDlq(queue, id);
59
+ if (removed)
60
+ this.postgresSnapshot.remove(id);
61
+ return removed;
62
+ });
63
+ }
64
+ async retryCompletedDurable(queue, id, options = {}) {
65
+ return await this.runPostgresOperation(async () => {
66
+ await this.postgresReady;
67
+ const limit = boundedLimit(options.limit);
68
+ if (limit === 0)
69
+ return 0;
70
+ let rows = await this.postgresStore.list(queue, {
71
+ states: ['completed'],
72
+ limit: 2_147_483_647,
73
+ asc: true,
74
+ });
75
+ if (id)
76
+ rows = rows.filter((row) => row.job.id === id);
77
+ const timestamp = options.timestamp;
78
+ if (timestamp !== undefined) {
79
+ rows = rows.filter((row) => (row.job.completedAt ?? Infinity) <= timestamp);
80
+ }
81
+ let retried = 0;
82
+ for (const row of rows.slice(0, limit)) {
83
+ if (await this.postgresStore.retry(row.job.id))
84
+ retried++;
85
+ }
86
+ if (retried > 0)
87
+ await this.refreshQueueAfterCommit(queue);
88
+ return retried;
89
+ });
90
+ }
91
+ async cleanDurable(queue, graceMs, state, limit) {
92
+ return await this.runPostgresOperation(async () => {
93
+ await this.postgresReady;
94
+ const ids = await this.postgresStore.clean(queue, graceMs, state, limit);
95
+ if (ids.length > 0)
96
+ await this.refreshQueueAfterCommit(queue);
97
+ return ids;
98
+ });
99
+ }
100
+ }
@@ -0,0 +1,26 @@
1
+ export type PostgresSyncAdmission<T> = {
2
+ readonly accepted: true;
3
+ readonly value: T;
4
+ } | {
5
+ readonly accepted: false;
6
+ };
7
+ /** Stop new PostgreSQL operations and drain work admitted before shutdown. */
8
+ export declare class PostgresOperationGate {
9
+ private readonly maxConcurrent;
10
+ private readonly maxQueued;
11
+ private readonly scopes;
12
+ private accepting;
13
+ private active;
14
+ private running;
15
+ private readonly queued;
16
+ private drainPromise;
17
+ private resolveDrain;
18
+ constructor(maxConcurrent?: number, maxQueued?: number);
19
+ run<T>(operation: () => Promise<T>): Promise<T>;
20
+ runSync<T>(operation: () => T): T;
21
+ tryRunSync<T>(operation: () => T): PostgresSyncAdmission<T>;
22
+ closeAndDrain(): Promise<void>;
23
+ private admit;
24
+ private enterSync;
25
+ private finish;
26
+ }
@@ -0,0 +1,96 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
2
+ /** Stop new PostgreSQL operations and drain work admitted before shutdown. */
3
+ export class PostgresOperationGate {
4
+ maxConcurrent;
5
+ maxQueued;
6
+ scopes = new AsyncLocalStorage();
7
+ accepting = true;
8
+ active = 0;
9
+ running = 0;
10
+ queued = [];
11
+ drainPromise = null;
12
+ resolveDrain = null;
13
+ constructor(maxConcurrent = Number.POSITIVE_INFINITY, maxQueued = Number.POSITIVE_INFINITY) {
14
+ this.maxConcurrent = maxConcurrent;
15
+ this.maxQueued = maxQueued;
16
+ }
17
+ async run(operation) {
18
+ const parent = this.scopes.getStore();
19
+ const nested = parent?.active === true;
20
+ await this.admit(nested);
21
+ const scope = { active: true };
22
+ try {
23
+ return await this.scopes.run(scope, operation);
24
+ }
25
+ finally {
26
+ this.finish(scope, nested);
27
+ }
28
+ }
29
+ runSync(operation) {
30
+ const scope = this.enterSync();
31
+ try {
32
+ return this.scopes.run(scope, operation);
33
+ }
34
+ finally {
35
+ this.finish(scope, true);
36
+ }
37
+ }
38
+ tryRunSync(operation) {
39
+ if (!this.accepting && !this.scopes.getStore()?.active)
40
+ return { accepted: false };
41
+ return { accepted: true, value: this.runSync(operation) };
42
+ }
43
+ closeAndDrain() {
44
+ if (this.scopes.getStore()?.active) {
45
+ throw new Error('Cannot shut down PostgreSQL from an active queue operation');
46
+ }
47
+ this.accepting = false;
48
+ if (this.active === 0)
49
+ return Promise.resolve();
50
+ this.drainPromise ??= new Promise((resolve) => {
51
+ this.resolveDrain = resolve;
52
+ });
53
+ return this.drainPromise;
54
+ }
55
+ async admit(nested) {
56
+ if (!this.accepting && !this.scopes.getStore()?.active) {
57
+ throw new Error('PostgreSQL queue manager is shutting down');
58
+ }
59
+ if (nested) {
60
+ this.active++;
61
+ return;
62
+ }
63
+ if (this.running < this.maxConcurrent) {
64
+ this.running++;
65
+ this.active++;
66
+ return;
67
+ }
68
+ if (this.queued.length >= this.maxQueued) {
69
+ throw new Error('PostgreSQL operation queue is saturated');
70
+ }
71
+ this.active++;
72
+ await new Promise((resolve) => this.queued.push({ resolve }));
73
+ }
74
+ enterSync() {
75
+ if (!this.accepting && !this.scopes.getStore()?.active) {
76
+ throw new Error('PostgreSQL queue manager is shutting down');
77
+ }
78
+ this.active++;
79
+ return { active: true };
80
+ }
81
+ finish(scope, nested) {
82
+ scope.active = false;
83
+ this.active--;
84
+ if (!nested) {
85
+ const next = this.queued.shift();
86
+ if (next)
87
+ next.resolve();
88
+ else
89
+ this.running--;
90
+ }
91
+ if (this.active !== 0)
92
+ return;
93
+ this.resolveDrain?.();
94
+ this.resolveDrain = null;
95
+ }
96
+ }
@@ -0,0 +1,25 @@
1
+ import type { JobId } from '../../domain/types/job';
2
+ import { PostgresQueueManagerCloud } from './cloud';
3
+ export declare class PostgresQueueManagerOperations extends PostgresQueueManagerCloud {
4
+ private readonly clientReleaseSessions;
5
+ cancel(id: JobId): Promise<boolean>;
6
+ updateProgress(id: JobId, progress: number, message?: string): Promise<boolean>;
7
+ updateJobData(id: JobId, data: unknown): Promise<boolean>;
8
+ changePriority(id: JobId, priority: number, lifo?: boolean): Promise<boolean>;
9
+ promote(id: JobId): Promise<boolean>;
10
+ promoteJobs(queue: string, count?: number): Promise<number>;
11
+ moveToDelayed(id: JobId, delay: number, token?: string): Promise<boolean>;
12
+ changeDelay(id: JobId, delay: number, token?: string): Promise<boolean>;
13
+ moveActiveToWait(id: JobId, token?: string): Promise<boolean>;
14
+ changeWaitingDelay(id: JobId, delay: number): Promise<boolean>;
15
+ moveToWaitingChildren(id: JobId, token?: string): Promise<boolean>;
16
+ discard(id: JobId, token?: string): Promise<boolean>;
17
+ getDeduplicationJobId(queue: string, key: string): string | null;
18
+ removeDeduplicationKey(queue: string, key: string): Promise<number>;
19
+ removeJobDeduplicationKey(id: string): Promise<boolean>;
20
+ releaseClientJobs(clientId: string): Promise<number>;
21
+ forceReleaseClientJobs(clientId: string): number;
22
+ private getClientReleaseSession;
23
+ private runClientRelease;
24
+ private releaseClientSession;
25
+ }
@@ -0,0 +1,194 @@
1
+ import { PostgresQueueManagerCloud } from './cloud';
2
+ export class PostgresQueueManagerOperations extends PostgresQueueManagerCloud {
3
+ clientReleaseSessions = new Map();
4
+ async cancel(id) {
5
+ return await this.runPostgresOperation(async () => {
6
+ await this.postgresReady;
7
+ const removed = await this.postgresStore.cancel(id);
8
+ if (removed)
9
+ this.postgresSnapshot.remove(id);
10
+ return removed;
11
+ });
12
+ }
13
+ async updateProgress(id, progress, message) {
14
+ return await this.runPostgresOperation(async () => {
15
+ await this.postgresReady;
16
+ const updated = await this.postgresStore.updateProgress(id, progress, message);
17
+ if (updated)
18
+ await this.refreshJob(id);
19
+ return updated;
20
+ });
21
+ }
22
+ async updateJobData(id, data) {
23
+ return await this.runPostgresOperation(async () => {
24
+ await this.postgresReady;
25
+ const updated = await this.postgresStore.updateData(id, data);
26
+ if (updated)
27
+ await this.refreshJob(id);
28
+ return updated;
29
+ });
30
+ }
31
+ async changePriority(id, priority, lifo) {
32
+ return await this.runPostgresOperation(async () => {
33
+ await this.postgresReady;
34
+ const updated = await this.postgresStore.changePriority(id, priority, lifo);
35
+ if (updated)
36
+ await this.refreshJob(id);
37
+ return updated;
38
+ });
39
+ }
40
+ async promote(id) {
41
+ return await this.runPostgresOperation(async () => {
42
+ await this.postgresReady;
43
+ const promoted = await this.postgresStore.promote(id);
44
+ if (promoted)
45
+ await this.refreshJob(id);
46
+ return promoted;
47
+ });
48
+ }
49
+ async promoteJobs(queue, count) {
50
+ return await this.runPostgresOperation(async () => {
51
+ await this.postgresReady;
52
+ const promoted = await this.postgresStore.promoteMany(queue, count);
53
+ if (promoted.length > 0)
54
+ await this.refreshQueueAfterCommit(queue);
55
+ return promoted.length;
56
+ });
57
+ }
58
+ async moveToDelayed(id, delay, token) {
59
+ return await this.runPostgresOperation(() => this.changeDelay(id, delay, token));
60
+ }
61
+ async changeDelay(id, delay, token) {
62
+ return await this.runPostgresOperation(async () => {
63
+ await this.postgresReady;
64
+ const now = await this.postgresStore.now();
65
+ const changed = await this.postgresStore.changeDelay(id, now + Math.max(0, delay), this.tokenFor(id, token) ?? undefined);
66
+ if (changed) {
67
+ this.forgetToken(id);
68
+ await this.refreshJob(id);
69
+ }
70
+ return changed;
71
+ });
72
+ }
73
+ async moveActiveToWait(id, token) {
74
+ return await this.runPostgresOperation(async () => {
75
+ await this.postgresReady;
76
+ const now = await this.postgresStore.now();
77
+ const moved = await this.postgresStore.changeDelay(id, now, this.tokenFor(id, token) ?? undefined);
78
+ if (moved) {
79
+ this.forgetToken(id);
80
+ await this.refreshJob(id);
81
+ }
82
+ return moved;
83
+ });
84
+ }
85
+ async changeWaitingDelay(id, delay) {
86
+ return await this.runPostgresOperation(() => this.changeDelay(id, delay));
87
+ }
88
+ async moveToWaitingChildren(id, token) {
89
+ return await this.runPostgresOperation(async () => {
90
+ await this.postgresReady;
91
+ const moved = await this.postgresStore.moveToWaitingChildren(id, this.tokenFor(id, token) ?? undefined);
92
+ if (moved) {
93
+ this.forgetToken(id);
94
+ await this.refreshJob(id);
95
+ }
96
+ return moved;
97
+ });
98
+ }
99
+ async discard(id, token) {
100
+ return await this.runPostgresOperation(async () => {
101
+ await this.postgresReady;
102
+ const removed = await this.postgresStore.discard(id, this.tokenFor(id, token) ?? undefined);
103
+ if (removed) {
104
+ this.forgetToken(id);
105
+ await this.refreshJob(id);
106
+ }
107
+ return removed;
108
+ });
109
+ }
110
+ getDeduplicationJobId(queue, key) {
111
+ return this.postgresSnapshot.getByUniqueKey(queue, key)?.id ?? null;
112
+ }
113
+ async removeDeduplicationKey(queue, key) {
114
+ return await this.runPostgresOperation(async () => {
115
+ const job = this.postgresSnapshot.getByUniqueKey(queue, key);
116
+ if (!job)
117
+ return 0;
118
+ const removed = await this.postgresStore.clearUniqueKey(job.id);
119
+ if (removed)
120
+ await this.refreshJob(job.id);
121
+ return removed ? 1 : 0;
122
+ });
123
+ }
124
+ async removeJobDeduplicationKey(id) {
125
+ return await this.runPostgresOperation(async () => {
126
+ await this.postgresReady;
127
+ const removed = await this.postgresStore.clearUniqueKey(id);
128
+ if (removed)
129
+ await this.refreshJob(id);
130
+ return removed;
131
+ });
132
+ }
133
+ async releaseClientJobs(clientId) {
134
+ return await this.runPostgresOperation(() => this.runClientRelease(clientId));
135
+ }
136
+ forceReleaseClientJobs(clientId) {
137
+ const admitted = this.operations.tryRunSync(() => {
138
+ const session = this.getClientReleaseSession(clientId);
139
+ const tracked = session.leases.size;
140
+ if (tracked > 0)
141
+ this.enqueueWrite(() => this.runClientRelease(clientId).then(() => undefined));
142
+ return tracked;
143
+ });
144
+ if (admitted.accepted)
145
+ return admitted.value;
146
+ return this.clientReleaseSessions.get(clientId)?.leases.size ?? 0;
147
+ }
148
+ getClientReleaseSession(clientId) {
149
+ const current = this.clientReleaseSessions.get(clientId);
150
+ if (current)
151
+ return current;
152
+ const leases = new Map();
153
+ for (const id of this.clientJobs.get(clientId) ?? []) {
154
+ const token = this.tokenFor(id);
155
+ if (token)
156
+ leases.set(id, token);
157
+ else
158
+ this.clientJobs.get(clientId)?.delete(id);
159
+ }
160
+ if (this.clientJobs.get(clientId)?.size === 0)
161
+ this.clientJobs.delete(clientId);
162
+ const session = { leases, released: 0, inFlight: null };
163
+ this.clientReleaseSessions.set(clientId, session);
164
+ return session;
165
+ }
166
+ async runClientRelease(clientId) {
167
+ const session = this.getClientReleaseSession(clientId);
168
+ if (session.inFlight)
169
+ return await session.inFlight;
170
+ const attempt = this.releaseClientSession(clientId, session).finally(() => {
171
+ if (session.inFlight === attempt)
172
+ session.inFlight = null;
173
+ });
174
+ session.inFlight = attempt;
175
+ return await attempt;
176
+ }
177
+ async releaseClientSession(clientId, session) {
178
+ for (const [id, token] of [...session.leases]) {
179
+ const released = await this.postgresStore.releaseClientLease(id, token);
180
+ session.leases.delete(id);
181
+ this.clientJobs.get(clientId)?.delete(id);
182
+ if (this.clientJobs.get(clientId)?.size === 0)
183
+ this.clientJobs.delete(clientId);
184
+ if (this.activeTokens.get(id) === token)
185
+ this.activeTokens.delete(id);
186
+ if (released)
187
+ session.released++;
188
+ await this.refreshJob(id);
189
+ }
190
+ if (session.leases.size === 0)
191
+ this.clientReleaseSessions.delete(clientId);
192
+ return session.released;
193
+ }
194
+ }
@@ -0,0 +1,43 @@
1
+ import type { JobId } from '../../domain/types/job';
2
+ import type { PostgresJobProjection } from '../../infrastructure/persistence/postgres/readModels';
3
+ import type { PostgresQueueSnapshot } from './snapshot';
4
+ export type { PostgresJobProjection } from '../../infrastructure/persistence/postgres/readModels';
5
+ export declare function applyPostgresJobProjection(snapshot: PostgresQueueSnapshot, activeTokens: Map<JobId, string>, id: JobId, projection: PostgresJobProjection): void;
6
+ type ProjectionLoader = (requests: readonly {
7
+ id: JobId;
8
+ queue: string;
9
+ }[]) => Promise<ReadonlyMap<JobId, PostgresJobProjection>>;
10
+ type ProjectionApplier = (id: JobId, projection: PostgresJobProjection) => void;
11
+ type ProjectionReporter = (queue: string, id: JobId, error: unknown) => void;
12
+ /** Coalesced, generation-fenced repair of the local PostgreSQL read model. */
13
+ export declare class PostgresProjectionRefreshes {
14
+ private readonly load;
15
+ private readonly apply;
16
+ private readonly report;
17
+ private readonly retryDelayMs;
18
+ private static readonly MAX_ACTIVE_BATCHES;
19
+ private static readonly MAX_REQUESTS_PER_BATCH;
20
+ private readonly generations;
21
+ private readonly generationQueues;
22
+ private readonly pending;
23
+ private readonly active;
24
+ private timer;
25
+ private accepting;
26
+ private started;
27
+ constructor(load: ProjectionLoader, apply: ProjectionApplier, report: ProjectionReporter, retryDelayMs: number);
28
+ request(id: JobId, queue: string): void;
29
+ supersede(id: JobId): void;
30
+ supersedeQueue(queue: string): void;
31
+ refreshNow(id: JobId, queue: string): Promise<PostgresJobProjection>;
32
+ refreshManyNow(requests: readonly {
33
+ id: JobId;
34
+ queue: string;
35
+ }[]): Promise<ReadonlyMap<JobId, PostgresJobProjection>>;
36
+ start(): void;
37
+ close(): void;
38
+ drain(): Promise<void>;
39
+ private schedule;
40
+ private runBatch;
41
+ private beginGeneration;
42
+ private endGeneration;
43
+ }