bunqueue 2.8.59 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +109 -77
- package/dist/application/background/dlq.js +2 -0
- package/dist/application/contextFactory.js +5 -0
- package/dist/application/dlqManager.d.ts +11 -1
- package/dist/application/dlqManager.js +48 -10
- package/dist/application/dlqRetry.js +59 -38
- package/dist/application/eventsManager.d.ts +1 -1
- package/dist/application/eventsManager.js +30 -26
- package/dist/application/lockManager.js +1 -1
- package/dist/application/operations/jobManagement.d.ts +4 -0
- package/dist/application/operations/jobMoveOperations.js +9 -4
- package/dist/application/postgres-queue-manager/batchSnapshot.d.ts +16 -0
- package/dist/application/postgres-queue-manager/batchSnapshot.js +17 -0
- package/dist/application/postgres-queue-manager/cloud.d.ts +30 -0
- package/dist/application/postgres-queue-manager/cloud.js +55 -0
- package/dist/application/postgres-queue-manager/config.d.ts +5 -0
- package/dist/application/postgres-queue-manager/config.js +1 -0
- package/dist/application/postgres-queue-manager/control.d.ts +26 -0
- package/dist/application/postgres-queue-manager/control.js +186 -0
- package/dist/application/postgres-queue-manager/deferredWrites.d.ts +13 -0
- package/dist/application/postgres-queue-manager/deferredWrites.js +60 -0
- package/dist/application/postgres-queue-manager/delivery.d.ts +19 -0
- package/dist/application/postgres-queue-manager/delivery.js +80 -0
- package/dist/application/postgres-queue-manager/lease.d.ts +13 -0
- package/dist/application/postgres-queue-manager/lease.js +88 -0
- package/dist/application/postgres-queue-manager/lifetimeMetrics.d.ts +32 -0
- package/dist/application/postgres-queue-manager/lifetimeMetrics.js +53 -0
- package/dist/application/postgres-queue-manager/maintenance.d.ts +14 -0
- package/dist/application/postgres-queue-manager/maintenance.js +100 -0
- package/dist/application/postgres-queue-manager/operationGate.d.ts +26 -0
- package/dist/application/postgres-queue-manager/operationGate.js +96 -0
- package/dist/application/postgres-queue-manager/operations.d.ts +25 -0
- package/dist/application/postgres-queue-manager/operations.js +194 -0
- package/dist/application/postgres-queue-manager/projectionRefreshes.d.ts +43 -0
- package/dist/application/postgres-queue-manager/projectionRefreshes.js +170 -0
- package/dist/application/postgres-queue-manager/queries.d.ts +142 -0
- package/dist/application/postgres-queue-manager/queries.js +231 -0
- package/dist/application/postgres-queue-manager/relationships.d.ts +10 -0
- package/dist/application/postgres-queue-manager/relationships.js +45 -0
- package/dist/application/postgres-queue-manager/services.d.ts +31 -0
- package/dist/application/postgres-queue-manager/services.js +149 -0
- package/dist/application/postgres-queue-manager/snapshot.d.ts +51 -0
- package/dist/application/postgres-queue-manager/snapshot.js +236 -0
- package/dist/application/postgres-queue-manager/snapshotViews.d.ts +15 -0
- package/dist/application/postgres-queue-manager/snapshotViews.js +100 -0
- package/dist/application/postgres-queue-manager/startupEventBuffer.d.ts +12 -0
- package/dist/application/postgres-queue-manager/startupEventBuffer.js +36 -0
- package/dist/application/postgres-queue-manager/state.d.ts +47 -0
- package/dist/application/postgres-queue-manager/state.js +273 -0
- package/dist/application/postgres-queue-manager/terminalDelivery.d.ts +20 -0
- package/dist/application/postgres-queue-manager/terminalDelivery.js +100 -0
- package/dist/application/postgresQueueManager.d.ts +2 -0
- package/dist/application/postgresQueueManager.js +1 -0
- package/dist/application/queue-manager/ack.js +1 -1
- package/dist/application/queue-manager/delivery.js +1 -1
- package/dist/application/queue-manager/flow-failures.js +4 -0
- package/dist/application/queue-manager/limits.d.ts +2 -0
- package/dist/application/queue-manager/limits.js +4 -0
- package/dist/application/queue-manager/observability.js +15 -3
- package/dist/application/queue-manager/queries.d.ts +7 -0
- package/dist/application/queue-manager/queries.js +9 -0
- package/dist/application/queue-manager/services.d.ts +1 -1
- package/dist/application/queue-manager/services.js +4 -2
- package/dist/application/queue-manager/state.js +16 -1
- package/dist/application/statsManager.d.ts +1 -1
- package/dist/application/statsManager.js +1 -1
- package/dist/cli/commands/server.js +1 -1
- package/dist/client/events.js +2 -2
- package/dist/client/flow.js +0 -1
- package/dist/client/forwarder.d.ts +6 -4
- package/dist/client/forwarder.js +5 -3
- package/dist/client/queue/dlq.d.ts +2 -0
- package/dist/client/queue/dlq.js +14 -0
- package/dist/client/queue/dlqOps.d.ts +2 -0
- package/dist/client/queue/dlqOps.js +4 -0
- package/dist/client/queue/helpers.js +2 -0
- package/dist/client/queue/operations/add/single.js +1 -1
- package/dist/client/queue/runtime/configuration.d.ts +4 -0
- package/dist/client/queue/runtime/configuration.js +8 -0
- package/dist/client/sandboxed/runtime/state.js +2 -2
- package/dist/client/tcp/connection.d.ts +1 -1
- package/dist/client/tcp/connection.js +1 -1
- package/dist/client/tcp/runtime/state.js +2 -2
- package/dist/client/types/metrics.d.ts +1 -1
- package/dist/client/worker/runtime/control.js +0 -1
- package/dist/client/worker/runtime/execution.js +3 -8
- package/dist/client/worker/runtime/lifecycle.js +0 -1
- package/dist/client/worker/runtime/polling.d.ts +1 -0
- package/dist/client/worker/runtime/polling.js +9 -0
- package/dist/client/worker/runtime/state.js +3 -3
- package/dist/client/workflow/compensationChild.d.ts +2 -0
- package/dist/client/workflow/compensationChild.js +3 -1
- package/dist/client/workflow/compensationPass.d.ts +1 -0
- package/dist/client/workflow/compensationPass.js +18 -2
- package/dist/client/workflow/compensator.d.ts +2 -1
- package/dist/client/workflow/compensator.js +11 -3
- package/dist/client/workflow/engine.js +1 -1
- package/dist/client/workflow/executionFence.d.ts +15 -0
- package/dist/client/workflow/executionFence.js +29 -0
- package/dist/client/workflow/executor.d.ts +5 -11
- package/dist/client/workflow/executor.js +48 -47
- package/dist/client/workflow/executorLifecycle.d.ts +1 -0
- package/dist/client/workflow/executorLifecycle.js +41 -10
- package/dist/client/workflow/executorNodes.d.ts +1 -0
- package/dist/client/workflow/executorNodes.js +45 -16
- package/dist/client/workflow/executorQueue.d.ts +9 -0
- package/dist/client/workflow/executorQueue.js +15 -0
- package/dist/client/workflow/forEachRunner.d.ts +4 -0
- package/dist/client/workflow/forEachRunner.js +70 -0
- package/dist/client/workflow/loops.d.ts +4 -5
- package/dist/client/workflow/loops.js +27 -93
- package/dist/client/workflow/mapRunner.d.ts +1 -1
- package/dist/client/workflow/mapRunner.js +11 -2
- package/dist/client/workflow/recovery.d.ts +1 -0
- package/dist/client/workflow/recovery.js +24 -18
- package/dist/client/workflow/rollbackControl.d.ts +1 -0
- package/dist/client/workflow/rollbackControl.js +5 -2
- package/dist/client/workflow/runner.d.ts +3 -1
- package/dist/client/workflow/runner.js +26 -3
- package/dist/client/workflow/stepTypes.js +1 -1
- package/dist/client/workflow/subWorkflowRunner.d.ts +1 -0
- package/dist/client/workflow/subWorkflowRunner.js +7 -0
- package/dist/client/workflow/waitFor.d.ts +4 -0
- package/dist/client/workflow/waitFor.js +23 -11
- package/dist/client/workflow/workflowDecisions.d.ts +1 -1
- package/dist/client/workflow/workflowDecisions.js +3 -1
- package/dist/config/resolve.d.ts +14 -0
- package/dist/config/resolve.js +50 -5
- package/dist/config/types.d.ts +18 -0
- package/dist/domain/queue/dlqShard.d.ts +2 -0
- package/dist/domain/queue/dlqShard.js +16 -0
- package/dist/domain/queue/shard/dlq.d.ts +1 -0
- package/dist/domain/queue/shard/dlq.js +3 -0
- package/dist/domain/types/commands/dlq.d.ts +5 -0
- package/dist/domain/types/commands/union.d.ts +1 -1
- package/dist/domain/types/cron.d.ts +5 -0
- package/dist/domain/types/cron.js +14 -3
- package/dist/domain/types/dlq.d.ts +1 -1
- package/dist/domain/types/dlq.js +1 -2
- package/dist/domain/types/jobs/model.d.ts +1 -1
- package/dist/infrastructure/cloud/commandHandler.js +5 -3
- package/dist/infrastructure/cloud/commands/integrations.js +11 -11
- package/dist/infrastructure/cloud/commands/jobs.js +48 -40
- package/dist/infrastructure/cloud/commands/queues.js +61 -75
- package/dist/infrastructure/cloud/queueAdapter/local.d.ts +41 -0
- package/dist/infrastructure/cloud/queueAdapter/local.js +187 -0
- package/dist/infrastructure/cloud/queueAdapter/postgres.d.ts +42 -0
- package/dist/infrastructure/cloud/queueAdapter/postgres.js +188 -0
- package/dist/infrastructure/cloud/queueAdapter/registry.d.ts +4 -0
- package/dist/infrastructure/cloud/queueAdapter/registry.js +15 -0
- package/dist/infrastructure/cloud/queueAdapter/types.d.ts +87 -0
- package/dist/infrastructure/cloud/queueAdapter/types.js +1 -0
- package/dist/infrastructure/cloud/snapshot/analytics.d.ts +2 -0
- package/dist/infrastructure/cloud/snapshot/analytics.js +7 -0
- package/dist/infrastructure/cloud/snapshot/collector.d.ts +4 -0
- package/dist/infrastructure/cloud/snapshot/collector.js +39 -1
- package/dist/infrastructure/cloud/snapshot/config.d.ts +3 -0
- package/dist/infrastructure/cloud/snapshot/config.js +43 -0
- package/dist/infrastructure/cloud/snapshot/jobs.d.ts +3 -0
- package/dist/infrastructure/cloud/snapshot/jobs.js +32 -1
- package/dist/infrastructure/cloud/snapshotCollector.js +20 -35
- package/dist/infrastructure/cloud/snapshotHelpers.d.ts +3 -3
- package/dist/infrastructure/cloud/snapshotHelpers.js +3 -3
- package/dist/infrastructure/cloud/statsRefresh.js +2 -1
- package/dist/infrastructure/cloud/types/command.d.ts +2 -2
- package/dist/infrastructure/persistence/postgres/admission.d.ts +18 -0
- package/dist/infrastructure/persistence/postgres/admission.js +193 -0
- package/dist/infrastructure/persistence/postgres/admissionParent.d.ts +5 -0
- package/dist/infrastructure/persistence/postgres/admissionParent.js +35 -0
- package/dist/infrastructure/persistence/postgres/admissionResult.d.ts +9 -0
- package/dist/infrastructure/persistence/postgres/admissionResult.js +1 -0
- package/dist/infrastructure/persistence/postgres/admissionStore.d.ts +12 -0
- package/dist/infrastructure/persistence/postgres/admissionStore.js +101 -0
- package/dist/infrastructure/persistence/postgres/advisoryLocks.d.ts +2 -0
- package/dist/infrastructure/persistence/postgres/advisoryLocks.js +13 -0
- package/dist/infrastructure/persistence/postgres/batchAdmission.d.ts +11 -0
- package/dist/infrastructure/persistence/postgres/batchAdmission.js +110 -0
- package/dist/infrastructure/persistence/postgres/batchCompletion.d.ts +4 -0
- package/dist/infrastructure/persistence/postgres/batchCompletion.js +174 -0
- package/dist/infrastructure/persistence/postgres/batchEvents.d.ts +14 -0
- package/dist/infrastructure/persistence/postgres/batchEvents.js +72 -0
- package/dist/infrastructure/persistence/postgres/brokerSessions.d.ts +14 -0
- package/dist/infrastructure/persistence/postgres/brokerSessions.js +94 -0
- package/dist/infrastructure/persistence/postgres/claimBatch.d.ts +11 -0
- package/dist/infrastructure/persistence/postgres/claimBatch.js +56 -0
- package/dist/infrastructure/persistence/postgres/claimSelection.d.ts +4 -0
- package/dist/infrastructure/persistence/postgres/claimSelection.js +198 -0
- package/dist/infrastructure/persistence/postgres/claims.d.ts +3 -0
- package/dist/infrastructure/persistence/postgres/claims.js +137 -0
- package/dist/infrastructure/persistence/postgres/cloudReadModel.d.ts +26 -0
- package/dist/infrastructure/persistence/postgres/cloudReadModel.js +123 -0
- package/dist/infrastructure/persistence/postgres/codec.d.ts +30 -0
- package/dist/infrastructure/persistence/postgres/codec.js +82 -0
- package/dist/infrastructure/persistence/postgres/completionEvents.d.ts +11 -0
- package/dist/infrastructure/persistence/postgres/completionEvents.js +21 -0
- package/dist/infrastructure/persistence/postgres/completionLifecycle.d.ts +11 -0
- package/dist/infrastructure/persistence/postgres/completionLifecycle.js +145 -0
- package/dist/infrastructure/persistence/postgres/completionOutcome.d.ts +4 -0
- package/dist/infrastructure/persistence/postgres/completionOutcome.js +112 -0
- package/dist/infrastructure/persistence/postgres/completionQueries.d.ts +10 -0
- package/dist/infrastructure/persistence/postgres/completionQueries.js +87 -0
- package/dist/infrastructure/persistence/postgres/connection.d.ts +3 -0
- package/dist/infrastructure/persistence/postgres/connection.js +15 -0
- package/dist/infrastructure/persistence/postgres/context.d.ts +28 -0
- package/dist/infrastructure/persistence/postgres/context.js +74 -0
- package/dist/infrastructure/persistence/postgres/control.d.ts +23 -0
- package/dist/infrastructure/persistence/postgres/control.js +105 -0
- package/dist/infrastructure/persistence/postgres/crons.d.ts +18 -0
- package/dist/infrastructure/persistence/postgres/crons.js +205 -0
- package/dist/infrastructure/persistence/postgres/deduplication.d.ts +9 -0
- package/dist/infrastructure/persistence/postgres/deduplication.js +47 -0
- package/dist/infrastructure/persistence/postgres/dependencyDestruction.d.ts +14 -0
- package/dist/infrastructure/persistence/postgres/dependencyDestruction.js +74 -0
- package/dist/infrastructure/persistence/postgres/dependencyPromotion.d.ts +29 -0
- package/dist/infrastructure/persistence/postgres/dependencyPromotion.js +212 -0
- package/dist/infrastructure/persistence/postgres/destructiveMutations.d.ts +4 -0
- package/dist/infrastructure/persistence/postgres/destructiveMutations.js +111 -0
- package/dist/infrastructure/persistence/postgres/dlqLifecycle.d.ts +13 -0
- package/dist/infrastructure/persistence/postgres/dlqLifecycle.js +184 -0
- package/dist/infrastructure/persistence/postgres/dlqMaintenance.d.ts +6 -0
- package/dist/infrastructure/persistence/postgres/dlqMaintenance.js +36 -0
- package/dist/infrastructure/persistence/postgres/dlqRetryPlan.d.ts +21 -0
- package/dist/infrastructure/persistence/postgres/dlqRetryPlan.js +92 -0
- package/dist/infrastructure/persistence/postgres/eventCommitGc.d.ts +27 -0
- package/dist/infrastructure/persistence/postgres/eventCommitGc.js +62 -0
- package/dist/infrastructure/persistence/postgres/eventJournal.d.ts +18 -0
- package/dist/infrastructure/persistence/postgres/eventJournal.js +76 -0
- package/dist/infrastructure/persistence/postgres/eventJournalSchema.d.ts +5 -0
- package/dist/infrastructure/persistence/postgres/eventJournalSchema.js +253 -0
- package/dist/infrastructure/persistence/postgres/eventPruneWatermarks.d.ts +24 -0
- package/dist/infrastructure/persistence/postgres/eventPruneWatermarks.js +111 -0
- package/dist/infrastructure/persistence/postgres/eventRetention.d.ts +18 -0
- package/dist/infrastructure/persistence/postgres/eventRetention.js +76 -0
- package/dist/infrastructure/persistence/postgres/events.d.ts +45 -0
- package/dist/infrastructure/persistence/postgres/events.js +249 -0
- package/dist/infrastructure/persistence/postgres/expiry.d.ts +3 -0
- package/dist/infrastructure/persistence/postgres/expiry.js +74 -0
- package/dist/infrastructure/persistence/postgres/flowFailures.d.ts +17 -0
- package/dist/infrastructure/persistence/postgres/flowFailures.js +199 -0
- package/dist/infrastructure/persistence/postgres/jobData.d.ts +3 -0
- package/dist/infrastructure/persistence/postgres/jobData.js +32 -0
- package/dist/infrastructure/persistence/postgres/leaseRelease.d.ts +9 -0
- package/dist/infrastructure/persistence/postgres/leaseRelease.js +120 -0
- package/dist/infrastructure/persistence/postgres/leaseRenewal.d.ts +4 -0
- package/dist/infrastructure/persistence/postgres/leaseRenewal.js +35 -0
- package/dist/infrastructure/persistence/postgres/lifetimeMetrics.d.ts +15 -0
- package/dist/infrastructure/persistence/postgres/lifetimeMetrics.js +46 -0
- package/dist/infrastructure/persistence/postgres/lifetimeMetricsFinalizer.d.ts +4 -0
- package/dist/infrastructure/persistence/postgres/lifetimeMetricsFinalizer.js +13 -0
- package/dist/infrastructure/persistence/postgres/logs.d.ts +6 -0
- package/dist/infrastructure/persistence/postgres/logs.js +70 -0
- package/dist/infrastructure/persistence/postgres/maintenance.d.ts +6 -0
- package/dist/infrastructure/persistence/postgres/maintenance.js +138 -0
- package/dist/infrastructure/persistence/postgres/maintenanceFlights.d.ts +14 -0
- package/dist/infrastructure/persistence/postgres/maintenanceFlights.js +66 -0
- package/dist/infrastructure/persistence/postgres/metricWrites.d.ts +9 -0
- package/dist/infrastructure/persistence/postgres/metricWrites.js +94 -0
- package/dist/infrastructure/persistence/postgres/mutations.d.ts +9 -0
- package/dist/infrastructure/persistence/postgres/mutations.js +171 -0
- package/dist/infrastructure/persistence/postgres/outcomes.d.ts +4 -0
- package/dist/infrastructure/persistence/postgres/outcomes.js +194 -0
- package/dist/infrastructure/persistence/postgres/policies.d.ts +11 -0
- package/dist/infrastructure/persistence/postgres/policies.js +18 -0
- package/dist/infrastructure/persistence/postgres/postCommitMaintenance.d.ts +17 -0
- package/dist/infrastructure/persistence/postgres/postCommitMaintenance.js +117 -0
- package/dist/infrastructure/persistence/postgres/promotion.d.ts +3 -0
- package/dist/infrastructure/persistence/postgres/promotion.js +43 -0
- package/dist/infrastructure/persistence/postgres/queries.d.ts +22 -0
- package/dist/infrastructure/persistence/postgres/queries.js +152 -0
- package/dist/infrastructure/persistence/postgres/queueDestruction.d.ts +3 -0
- package/dist/infrastructure/persistence/postgres/queueDestruction.js +154 -0
- package/dist/infrastructure/persistence/postgres/queueLifecycle.d.ts +10 -0
- package/dist/infrastructure/persistence/postgres/queueLifecycle.js +60 -0
- package/dist/infrastructure/persistence/postgres/rateLimit.d.ts +6 -0
- package/dist/infrastructure/persistence/postgres/rateLimit.js +10 -0
- package/dist/infrastructure/persistence/postgres/readModels.d.ts +32 -0
- package/dist/infrastructure/persistence/postgres/readModels.js +72 -0
- package/dist/infrastructure/persistence/postgres/recovery.d.ts +3 -0
- package/dist/infrastructure/persistence/postgres/recovery.js +178 -0
- package/dist/infrastructure/persistence/postgres/relationships.d.ts +9 -0
- package/dist/infrastructure/persistence/postgres/relationships.js +201 -0
- package/dist/infrastructure/persistence/postgres/removeUnprocessedChildren.d.ts +4 -0
- package/dist/infrastructure/persistence/postgres/removeUnprocessedChildren.js +241 -0
- package/dist/infrastructure/persistence/postgres/repeatMutations.d.ts +5 -0
- package/dist/infrastructure/persistence/postgres/repeatMutations.js +37 -0
- package/dist/infrastructure/persistence/postgres/runtime.d.ts +46 -0
- package/dist/infrastructure/persistence/postgres/runtime.js +236 -0
- package/dist/infrastructure/persistence/postgres/runtimeConfig.d.ts +21 -0
- package/dist/infrastructure/persistence/postgres/runtimeConfig.js +39 -0
- package/dist/infrastructure/persistence/postgres/schema.d.ts +4 -0
- package/dist/infrastructure/persistence/postgres/schema.js +257 -0
- package/dist/infrastructure/persistence/postgres/schemaInitialization.d.ts +3 -0
- package/dist/infrastructure/persistence/postgres/schemaInitialization.js +221 -0
- package/dist/infrastructure/persistence/postgres/serialAdmission.d.ts +6 -0
- package/dist/infrastructure/persistence/postgres/serialAdmission.js +96 -0
- package/dist/infrastructure/persistence/postgres/snapshotBudget.d.ts +3 -0
- package/dist/infrastructure/persistence/postgres/snapshotBudget.js +83 -0
- package/dist/infrastructure/persistence/postgres/storageHealth.d.ts +10 -0
- package/dist/infrastructure/persistence/postgres/storageHealth.js +29 -0
- package/dist/infrastructure/persistence/postgres/store.d.ts +90 -0
- package/dist/infrastructure/persistence/postgres/store.js +136 -0
- package/dist/infrastructure/persistence/postgres/telemetry.d.ts +6 -0
- package/dist/infrastructure/persistence/postgres/telemetry.js +88 -0
- package/dist/infrastructure/persistence/postgres/terminal.d.ts +8 -0
- package/dist/infrastructure/persistence/postgres/terminal.js +137 -0
- package/dist/infrastructure/persistence/postgres/transactionRetry.d.ts +6 -0
- package/dist/infrastructure/persistence/postgres/transactionRetry.js +42 -0
- package/dist/infrastructure/persistence/postgres/types.d.ts +175 -0
- package/dist/infrastructure/persistence/postgres/types.js +1 -0
- package/dist/infrastructure/persistence/postgres/workers.d.ts +15 -0
- package/dist/infrastructure/persistence/postgres/workers.js +126 -0
- package/dist/infrastructure/persistence/postgres.d.ts +2 -0
- package/dist/infrastructure/persistence/postgres.js +1 -0
- package/dist/infrastructure/persistence/sqlite/jobs.js +2 -0
- package/dist/infrastructure/persistence/sqlite.d.ts +1 -1
- package/dist/infrastructure/scheduler/cron/persisted.d.ts +5 -0
- package/dist/infrastructure/scheduler/cron/persisted.js +27 -0
- package/dist/infrastructure/scheduler/cron/runtime.js +5 -10
- package/dist/infrastructure/scheduler/cron/validation.d.ts +3 -0
- package/dist/infrastructure/scheduler/cron/validation.js +11 -0
- package/dist/infrastructure/scheduler/cronParser.d.ts +1 -1
- package/dist/infrastructure/scheduler/cronParser.js +144 -11
- package/dist/infrastructure/server/bootstrap.d.ts +2 -3
- package/dist/infrastructure/server/bootstrap.js +33 -59
- package/dist/infrastructure/server/errors.d.ts +4 -0
- package/dist/infrastructure/server/errors.js +54 -0
- package/dist/infrastructure/server/handler-routes/control.d.ts +5 -5
- package/dist/infrastructure/server/handler-routes/control.js +3 -1
- package/dist/infrastructure/server/handler-routes/jobs.js +0 -3
- package/dist/infrastructure/server/handler-routes/monitoring.d.ts +2 -2
- package/dist/infrastructure/server/handler.js +9 -11
- package/dist/infrastructure/server/handlerRoutes.d.ts +2 -2
- package/dist/infrastructure/server/handlerRoutes.js +2 -2
- package/dist/infrastructure/server/handlers/advanced/dependencies.js +7 -6
- package/dist/infrastructure/server/handlers/advanced/jobs.js +19 -6
- package/dist/infrastructure/server/handlers/advanced/queue.d.ts +9 -9
- package/dist/infrastructure/server/handlers/advanced/queue.js +91 -27
- package/dist/infrastructure/server/handlers/core.js +32 -31
- package/dist/infrastructure/server/handlers/cron.d.ts +4 -4
- package/dist/infrastructure/server/handlers/cron.js +60 -59
- package/dist/infrastructure/server/handlers/dashboard.d.ts +1 -1
- package/dist/infrastructure/server/handlers/dashboard.js +21 -8
- package/dist/infrastructure/server/handlers/dlq.d.ts +6 -3
- package/dist/infrastructure/server/handlers/dlq.js +35 -9
- package/dist/infrastructure/server/handlers/flow.js +2 -1
- package/dist/infrastructure/server/handlers/management.d.ts +5 -5
- package/dist/infrastructure/server/handlers/management.js +36 -9
- package/dist/infrastructure/server/handlers/monitoring/health.d.ts +5 -5
- package/dist/infrastructure/server/handlers/monitoring/health.js +45 -16
- package/dist/infrastructure/server/handlers/monitoring/operations.d.ts +1 -1
- package/dist/infrastructure/server/handlers/monitoring/operations.js +8 -1
- package/dist/infrastructure/server/handlers/monitoring/workers.d.ts +3 -3
- package/dist/infrastructure/server/handlers/monitoring/workers.js +31 -7
- package/dist/infrastructure/server/handlers/pushBatchValidation.d.ts +3 -1
- package/dist/infrastructure/server/handlers/pushBatchValidation.js +52 -7
- package/dist/infrastructure/server/handlers/query.d.ts +1 -1
- package/dist/infrastructure/server/handlers/query.js +5 -4
- package/dist/infrastructure/server/http.js +2 -2
- package/dist/infrastructure/server/httpDashboardEndpoints.d.ts +1 -1
- package/dist/infrastructure/server/httpDashboardEndpoints.js +19 -6
- package/dist/infrastructure/server/httpEndpoints.js +20 -7
- package/dist/infrastructure/server/httpRouteQueues.js +11 -1
- package/dist/infrastructure/server/shutdownCoordinator.d.ts +24 -0
- package/dist/infrastructure/server/shutdownCoordinator.js +106 -0
- package/dist/infrastructure/server/sseHandler.js +8 -3
- package/dist/infrastructure/server/storageAdapter.d.ts +29 -0
- package/dist/infrastructure/server/storageAdapter.js +61 -0
- package/dist/infrastructure/server/storageManager.d.ts +12 -0
- package/dist/infrastructure/server/storageManager.js +102 -0
- package/dist/infrastructure/server/tcp.js +2 -3
- package/dist/infrastructure/server/ws/snapshots.d.ts +1 -1
- package/dist/infrastructure/server/ws/snapshots.js +19 -4
- package/dist/infrastructure/server/wsHandler.js +10 -5
- package/dist/main.js +1 -1
- package/dist/mcp/backend/embedded/services.js +2 -1
- package/dist/mcp/index.d.ts +2 -2
- package/dist/mcp/index.js +2 -2
- package/dist/shared/storageHealth.d.ts +9 -0
- package/dist/shared/storageHealth.js +12 -0
- package/package.json +85 -74
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { claimPostgresJobs } from './claims';
|
|
2
|
+
import { getPostgresQueueState, setPostgresConcurrency, setPostgresDlqConfig, setPostgresPaused, setPostgresRateLimit, setPostgresStallConfig, } from './control';
|
|
3
|
+
import { drainPostgresQueue, obliteratePostgresQueue } from './queueDestruction';
|
|
4
|
+
import { promotePostgresJobs } from './promotion';
|
|
5
|
+
import { changePostgresDelay, changePostgresPriority, clearPostgresJobUniqueKey, movePostgresJobToWaitingChildren, promotePostgresJob, updatePostgresJobData, updatePostgresProgress, } from './mutations';
|
|
6
|
+
import { removePostgresJob, retryPostgresTerminalJob } from './destructiveMutations';
|
|
7
|
+
import { completePostgresJob } from './completionOutcome';
|
|
8
|
+
import { failPostgresJob } from './outcomes';
|
|
9
|
+
import { renewPostgresLease } from './leaseRenewal';
|
|
10
|
+
import { getPostgresCounts, getPostgresJob, getPostgresJobs, findMissingPostgresDependencies, latestPostgresEventId, listPostgresDlq, listPostgresJobs, listPostgresQueues, loadAllPostgresJobs, } from './queries';
|
|
11
|
+
import { getPostgresChildrenValues, getPostgresCompletionResult, loadPostgresCompletionResults, } from './completionQueries';
|
|
12
|
+
import { recoverExpiredPostgresLeases } from './recovery';
|
|
13
|
+
import { getPostgresFlowFailureValues } from './flowFailures';
|
|
14
|
+
import { PostgresAdmissionStore } from './admissionStore';
|
|
15
|
+
import { cleanPostgresQueue, purgePostgresDlq } from './maintenance';
|
|
16
|
+
import { maintainPostgresDlq } from './dlqLifecycle';
|
|
17
|
+
import { addPostgresJobLog, clearPostgresJobLogs, getPostgresJobLogs } from './logs';
|
|
18
|
+
import { getPostgresCron, listPostgresCrons, processPostgresCrons, removePostgresCron, upsertPostgresCron, } from './crons';
|
|
19
|
+
import { heartbeatPostgresWorker, listPostgresWorkers, removePostgresClientWorkers, removePostgresWorker, savePostgresWorker, } from './workers';
|
|
20
|
+
import { getPostgresQueueMetrics, trimPostgresQueueEvents } from './telemetry';
|
|
21
|
+
import { releasePostgresClientLease } from './leaseRelease';
|
|
22
|
+
import { removePostgresChildDependency, updatePostgresJobParent } from './relationships';
|
|
23
|
+
import { cancelPostgresJob, discardPostgresJob, removePostgresDlqJob } from './terminal';
|
|
24
|
+
import { databaseNow, runPostgresPostCommitMaintenance } from './context';
|
|
25
|
+
import { completePostgresJobs } from './batchCompletion';
|
|
26
|
+
import { prunePostgresCompletionTombstones } from './completionLifecycle';
|
|
27
|
+
import { loadPostgresLifetimeMetrics } from './lifetimeMetrics';
|
|
28
|
+
import { finalizePostgresLifetimeMetrics } from './lifetimeMetricsFinalizer';
|
|
29
|
+
import { loadPostgresCloudReadModel } from './cloudReadModel';
|
|
30
|
+
import { removePostgresUnprocessedChildren } from './removeUnprocessedChildren';
|
|
31
|
+
import { loadPostgresJobProjections, loadPostgresManagerSnapshot, loadPostgresQueueReadModel, } from './readModels';
|
|
32
|
+
/** Database-authoritative PostgreSQL queue store safe for concurrent brokers. */
|
|
33
|
+
export class PostgresQueueStore extends PostgresAdmissionStore {
|
|
34
|
+
async now() {
|
|
35
|
+
await this.initialize();
|
|
36
|
+
return await databaseNow(this.context.sql);
|
|
37
|
+
}
|
|
38
|
+
async claim(queue, count, owner = this.config.brokerId, leaseDurationMs = this.config.leaseDurationMs) {
|
|
39
|
+
await this.initialize();
|
|
40
|
+
return await claimPostgresJobs(this.context, queue, count, owner, leaseDurationMs);
|
|
41
|
+
}
|
|
42
|
+
async complete(id, token, result, remove = false) {
|
|
43
|
+
await this.initialize();
|
|
44
|
+
const transition = await completePostgresJob(this.context, id, token, result, remove);
|
|
45
|
+
if (transition.applied && (remove || transition.job?.removeOnComplete)) {
|
|
46
|
+
await runPostgresPostCommitMaintenance(this.context, 'completion-retention', () => prunePostgresCompletionTombstones(this.context));
|
|
47
|
+
}
|
|
48
|
+
return transition;
|
|
49
|
+
}
|
|
50
|
+
async completeMany(items) {
|
|
51
|
+
await this.initialize();
|
|
52
|
+
const transitions = await completePostgresJobs(this.context, items);
|
|
53
|
+
if (transitions.some((transition) => transition.applied && transition.removed)) {
|
|
54
|
+
await runPostgresPostCommitMaintenance(this.context, 'completion-retention', () => prunePostgresCompletionTombstones(this.context));
|
|
55
|
+
}
|
|
56
|
+
return transitions;
|
|
57
|
+
}
|
|
58
|
+
async fail(input) {
|
|
59
|
+
await this.initialize();
|
|
60
|
+
return await failPostgresJob(this.context, input);
|
|
61
|
+
}
|
|
62
|
+
async renew(id, token, durationMs) {
|
|
63
|
+
await this.initialize();
|
|
64
|
+
return await renewPostgresLease(this.context, id, token, durationMs);
|
|
65
|
+
}
|
|
66
|
+
async recoverExpired(limit) {
|
|
67
|
+
await this.initialize();
|
|
68
|
+
return await recoverExpiredPostgresLeases(this.context, limit);
|
|
69
|
+
}
|
|
70
|
+
async maintainDlq(limit) {
|
|
71
|
+
await this.initialize();
|
|
72
|
+
return await maintainPostgresDlq(this.context, limit);
|
|
73
|
+
}
|
|
74
|
+
addCron = (input) => upsertPostgresCron(this.context, input);
|
|
75
|
+
getCron = (name) => getPostgresCron(this.context, name);
|
|
76
|
+
listCrons = () => listPostgresCrons(this.context);
|
|
77
|
+
removeCron = (name) => removePostgresCron(this.context, name);
|
|
78
|
+
processCrons = (limit) => processPostgresCrons(this.context, limit);
|
|
79
|
+
saveWorker = (worker) => savePostgresWorker(this.context, worker);
|
|
80
|
+
heartbeatWorker = (id, stats, clientId) => heartbeatPostgresWorker(this.context, id, stats, clientId);
|
|
81
|
+
removeWorker = (id, clientId) => removePostgresWorker(this.context, id, clientId);
|
|
82
|
+
removeClientWorkers = (clientId) => removePostgresClientWorkers(this.context, clientId);
|
|
83
|
+
listWorkers = () => listPostgresWorkers(this.context);
|
|
84
|
+
getQueueMetrics = (queue, type, start, end) => getPostgresQueueMetrics(this.context, queue, type, start, end);
|
|
85
|
+
trimQueueEvents = (queue, maxLength) => trimPostgresQueueEvents(this.context, queue, maxLength);
|
|
86
|
+
releaseClientLease = (id, token) => releasePostgresClientLease(this.context, id, token);
|
|
87
|
+
getJob = (id) => getPostgresJob(this.context, id);
|
|
88
|
+
getJobs = (ids) => getPostgresJobs(this.context, ids);
|
|
89
|
+
findMissingDependencies = (ids) => findMissingPostgresDependencies(this.context, ids);
|
|
90
|
+
getResult = (id) => getPostgresCompletionResult(this.context, id);
|
|
91
|
+
getCounts = (queue) => getPostgresCounts(this.context, queue);
|
|
92
|
+
getQueues = () => listPostgresQueues(this.context);
|
|
93
|
+
getDlq = (queue, limit) => listPostgresDlq(this.context, queue, limit);
|
|
94
|
+
getChildrenValues = (id) => getPostgresChildrenValues(this.context, id);
|
|
95
|
+
getFailedChildrenValues = (id) => getPostgresFlowFailureValues(this.context, id, 'continue');
|
|
96
|
+
getIgnoredChildrenFailures = (id) => getPostgresFlowFailureValues(this.context, id, 'ignore');
|
|
97
|
+
addLog = (id, message, level) => addPostgresJobLog(this.context, id, message, level);
|
|
98
|
+
getLogs = (id) => getPostgresJobLogs(this.context, id);
|
|
99
|
+
clearLogs = (id, keepLogs) => clearPostgresJobLogs(this.context, id, keepLogs);
|
|
100
|
+
getQueueState = (queue) => getPostgresQueueState(this.context, queue);
|
|
101
|
+
list = (queue, options) => listPostgresJobs(this.context, queue, options);
|
|
102
|
+
loadAll = () => loadAllPostgresJobs(this.context);
|
|
103
|
+
loadResults = (queue) => loadPostgresCompletionResults(this.context, queue);
|
|
104
|
+
latestEventId = () => latestPostgresEventId(this.context);
|
|
105
|
+
loadLifetimeMetrics = () => loadPostgresLifetimeMetrics(this.context);
|
|
106
|
+
finalizeLifetimeMetrics = (apply) => finalizePostgresLifetimeMetrics(this.context, apply);
|
|
107
|
+
loadCloudReadModel = () => loadPostgresCloudReadModel(this.context);
|
|
108
|
+
loadManagerSnapshot = () => loadPostgresManagerSnapshot(this.context);
|
|
109
|
+
loadQueueReadModel = (queue) => loadPostgresQueueReadModel(this.context, queue);
|
|
110
|
+
loadJobProjections = (requests) => loadPostgresJobProjections(this.context, requests);
|
|
111
|
+
updateData = (id, data) => updatePostgresJobData(this.context, id, data);
|
|
112
|
+
updateProgress = (id, value, message) => updatePostgresProgress(this.context, id, value, message);
|
|
113
|
+
changePriority = (id, priority, lifo) => changePostgresPriority(this.context, id, priority, lifo);
|
|
114
|
+
changeDelay = (id, runAt, token) => changePostgresDelay(this.context, id, runAt, token);
|
|
115
|
+
moveToWaitingChildren = (id, token) => movePostgresJobToWaitingChildren(this.context, id, token);
|
|
116
|
+
clearUniqueKey = (id) => clearPostgresJobUniqueKey(this.context, id);
|
|
117
|
+
removeDependency = (id) => removePostgresChildDependency(this.context, id);
|
|
118
|
+
removeUnprocessedChildren = (parentId) => removePostgresUnprocessedChildren(this.context, parentId);
|
|
119
|
+
updateParent = (childId, parentId) => updatePostgresJobParent(this.context, childId, parentId);
|
|
120
|
+
promote = (id) => promotePostgresJob(this.context, id);
|
|
121
|
+
cancel = (id) => cancelPostgresJob(this.context, id);
|
|
122
|
+
discard = (id, token) => discardPostgresJob(this.context, id, token);
|
|
123
|
+
remove = (id, token) => removePostgresJob(this.context, id, token);
|
|
124
|
+
removeDlq = (queue, id) => removePostgresDlqJob(this.context, queue, id);
|
|
125
|
+
purgeDlq = (queue) => purgePostgresDlq(this.context, queue);
|
|
126
|
+
clean = (queue, graceMs, state, limit) => cleanPostgresQueue(this.context, queue, graceMs, state, limit);
|
|
127
|
+
retry = (id, timestamp) => retryPostgresTerminalJob(this.context, id, timestamp);
|
|
128
|
+
pause = (queue, paused) => setPostgresPaused(this.context, queue, paused);
|
|
129
|
+
setRateLimit = (queue, limit, durationMs, ttlMs) => setPostgresRateLimit(this.context, queue, limit, durationMs, ttlMs);
|
|
130
|
+
setConcurrency = (queue, limit) => setPostgresConcurrency(this.context, queue, limit);
|
|
131
|
+
setStallConfig = (queue, config) => setPostgresStallConfig(this.context, queue, config);
|
|
132
|
+
setDlqConfig = (queue, config) => setPostgresDlqConfig(this.context, queue, config);
|
|
133
|
+
drain = (queue) => drainPostgresQueue(this.context, queue);
|
|
134
|
+
obliterate = (queue) => obliteratePostgresQueue(this.context, queue);
|
|
135
|
+
promoteMany = (queue, count) => promotePostgresJobs(this.context, queue, count);
|
|
136
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { QueueMetrics, QueueMetricType } from '../../../domain/types/metrics';
|
|
2
|
+
import type { PostgresContext } from './context';
|
|
3
|
+
export declare function getPostgresQueueMetrics(ctx: PostgresContext, queue: string, type: QueueMetricType, start?: number, end?: number): Promise<QueueMetrics>;
|
|
4
|
+
export declare function trimPostgresQueueEvents(ctx: PostgresContext, queue: string, maxLength: number): Promise<number>;
|
|
5
|
+
/** Converge retained windows after missed notifications or an unclean broker exit. */
|
|
6
|
+
export declare function sweepPostgresEventRetention(ctx: PostgresContext): Promise<number>;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { recordPostgresEventPruneWatermarks, summarizePostgresPrunedEvents, } from './eventPruneWatermarks';
|
|
2
|
+
import { lockPostgresEventRetention, prunePostgresQueueEvents } from './eventRetention';
|
|
3
|
+
import { POSTGRES_EVENT_CHANNEL } from './schema';
|
|
4
|
+
function assertNonNegativeInteger(value, name) {
|
|
5
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
6
|
+
throw new RangeError(`${name} must be a non-negative safe integer`);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export async function getPostgresQueueMetrics(ctx, queue, type, start = 0, end = -1) {
|
|
10
|
+
assertNonNegativeInteger(start, 'start');
|
|
11
|
+
if (end !== -1)
|
|
12
|
+
assertNonNegativeInteger(end, 'end');
|
|
13
|
+
const [metaRows, buckets] = await Promise.all([
|
|
14
|
+
ctx.sql `
|
|
15
|
+
SELECT total_count, prev_ts, prev_count
|
|
16
|
+
FROM bunqueue_metric_totals
|
|
17
|
+
WHERE namespace = ${ctx.config.namespace} AND queue = ${queue} AND metric_type = ${type}
|
|
18
|
+
`,
|
|
19
|
+
ctx.sql `
|
|
20
|
+
SELECT minute, count FROM bunqueue_metric_buckets
|
|
21
|
+
WHERE namespace = ${ctx.config.namespace} AND queue = ${queue} AND metric_type = ${type}
|
|
22
|
+
ORDER BY minute DESC
|
|
23
|
+
LIMIT ${ctx.config.maxMetricDataPoints}
|
|
24
|
+
`,
|
|
25
|
+
]);
|
|
26
|
+
const data = [];
|
|
27
|
+
if (buckets.length > 0) {
|
|
28
|
+
const newest = Number(buckets[0].minute);
|
|
29
|
+
const oldest = Math.max(Number(buckets.at(-1).minute), newest - ctx.config.maxMetricDataPoints + 1);
|
|
30
|
+
data.push(...new Array(newest - oldest + 1).fill(0));
|
|
31
|
+
for (const bucket of buckets)
|
|
32
|
+
data[newest - Number(bucket.minute)] = bucket.count;
|
|
33
|
+
}
|
|
34
|
+
const count = data.length;
|
|
35
|
+
const exclusiveEnd = end === -1 ? count : Math.min(count, end + 1);
|
|
36
|
+
const meta = metaRows[0];
|
|
37
|
+
return {
|
|
38
|
+
meta: {
|
|
39
|
+
count: Number(meta?.total_count ?? 0),
|
|
40
|
+
prevTS: Number(meta?.prev_ts ?? 0),
|
|
41
|
+
prevCount: meta?.prev_count ?? 0,
|
|
42
|
+
},
|
|
43
|
+
data: start >= exclusiveEnd ? [] : data.slice(start, exclusiveEnd),
|
|
44
|
+
count,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export async function trimPostgresQueueEvents(ctx, queue, maxLength) {
|
|
48
|
+
assertNonNegativeInteger(maxLength, 'maxLength');
|
|
49
|
+
return await ctx.sql.begin(async (tx) => {
|
|
50
|
+
await lockPostgresEventRetention(tx, ctx, queue);
|
|
51
|
+
const rows = await prunePostgresQueueEvents(tx, ctx, queue, maxLength);
|
|
52
|
+
const prune = summarizePostgresPrunedEvents(rows);
|
|
53
|
+
const { prunedThrough } = prune;
|
|
54
|
+
if (prunedThrough > 0) {
|
|
55
|
+
await recordPostgresEventPruneWatermarks(tx, ctx, [
|
|
56
|
+
{
|
|
57
|
+
queue,
|
|
58
|
+
sourceEventId: prunedThrough,
|
|
59
|
+
...prune,
|
|
60
|
+
prunesCurrentTransaction: false,
|
|
61
|
+
},
|
|
62
|
+
]);
|
|
63
|
+
await tx.notify(POSTGRES_EVENT_CHANNEL, JSON.stringify({
|
|
64
|
+
namespace: ctx.config.namespace,
|
|
65
|
+
queue,
|
|
66
|
+
brokerId: ctx.config.brokerId,
|
|
67
|
+
prunedThrough,
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
70
|
+
return rows.length;
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/** Converge retained windows after missed notifications or an unclean broker exit. */
|
|
74
|
+
export async function sweepPostgresEventRetention(ctx) {
|
|
75
|
+
const queues = await ctx.sql `
|
|
76
|
+
SELECT queue
|
|
77
|
+
FROM bunqueue_events
|
|
78
|
+
WHERE namespace = ${ctx.config.namespace}
|
|
79
|
+
GROUP BY queue
|
|
80
|
+
HAVING COUNT(*) > ${ctx.config.maxQueueEvents}
|
|
81
|
+
ORDER BY queue
|
|
82
|
+
`;
|
|
83
|
+
let removed = 0;
|
|
84
|
+
for (const { queue } of queues) {
|
|
85
|
+
removed += await trimPostgresQueueEvents(ctx, queue, ctx.config.maxQueueEvents);
|
|
86
|
+
}
|
|
87
|
+
return removed;
|
|
88
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { JobId } from '../../../domain/types/job';
|
|
2
|
+
import { type PostgresContext } from './context';
|
|
3
|
+
/** Cancel only a pending job, matching the existing QueueManager contract. */
|
|
4
|
+
export declare function cancelPostgresJob(ctx: PostgresContext, id: JobId): Promise<boolean>;
|
|
5
|
+
/** Move a runnable pending or actively leased job to the DLQ. */
|
|
6
|
+
export declare function discardPostgresJob(ctx: PostgresContext, id: JobId, token?: string): Promise<boolean>;
|
|
7
|
+
/** Permanently remove exactly one failed job from its queue. */
|
|
8
|
+
export declare function removePostgresDlqJob(ctx: PostgresContext, queue: string, id: JobId): Promise<boolean>;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { createDlqEntry } from '../../../domain/types/dlq';
|
|
2
|
+
import { decodePostgresJob, encodePostgresValue } from './codec';
|
|
3
|
+
import { databaseNow, recordPostgresEvent, runPostgresPostCommitMaintenance, } from './context';
|
|
4
|
+
import { enforcePostgresDlqLimit } from './dlqLifecycle';
|
|
5
|
+
import { getPostgresQueuePolicies } from './policies';
|
|
6
|
+
import { lockPostgresDestructionCandidates, partitionPostgresDestructionCandidates, } from './dependencyDestruction';
|
|
7
|
+
async function lockJob(tx, ctx, id) {
|
|
8
|
+
const rows = await tx `
|
|
9
|
+
SELECT * FROM bunqueue_jobs
|
|
10
|
+
WHERE namespace = ${ctx.config.namespace} AND id = ${String(id)}
|
|
11
|
+
FOR UPDATE
|
|
12
|
+
`;
|
|
13
|
+
return rows[0] ?? null;
|
|
14
|
+
}
|
|
15
|
+
async function deleteJobDependencies(tx, ctx, id) {
|
|
16
|
+
await tx `
|
|
17
|
+
DELETE FROM bunqueue_dependencies
|
|
18
|
+
WHERE namespace = ${ctx.config.namespace} AND job_id = ${String(id)}
|
|
19
|
+
`;
|
|
20
|
+
}
|
|
21
|
+
async function deleteParentFailureValues(tx, ctx, id) {
|
|
22
|
+
await tx `
|
|
23
|
+
DELETE FROM bunqueue_flow_failures
|
|
24
|
+
WHERE namespace = ${ctx.config.namespace} AND parent_id = ${String(id)}
|
|
25
|
+
`;
|
|
26
|
+
}
|
|
27
|
+
/** Cancel only a pending job, matching the existing QueueManager contract. */
|
|
28
|
+
export async function cancelPostgresJob(ctx, id) {
|
|
29
|
+
return await ctx.sql.begin(async (tx) => {
|
|
30
|
+
await lockPostgresDestructionCandidates(tx, ctx, [id]);
|
|
31
|
+
const row = await lockJob(tx, ctx, id);
|
|
32
|
+
if (!row || !['waiting', 'prioritized', 'delayed', 'waiting-children'].includes(row.state)) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
const { protectedIds } = await partitionPostgresDestructionCandidates(tx, ctx, [id], [id]);
|
|
36
|
+
if (protectedIds.length > 0)
|
|
37
|
+
return false;
|
|
38
|
+
const job = decodePostgresJob(row).job;
|
|
39
|
+
await deleteJobDependencies(tx, ctx, id);
|
|
40
|
+
await tx `
|
|
41
|
+
DELETE FROM bunqueue_job_logs
|
|
42
|
+
WHERE namespace = ${ctx.config.namespace} AND job_id = ${String(id)}
|
|
43
|
+
`;
|
|
44
|
+
await deleteParentFailureValues(tx, ctx, id);
|
|
45
|
+
await tx `
|
|
46
|
+
DELETE FROM bunqueue_jobs
|
|
47
|
+
WHERE namespace = ${ctx.config.namespace} AND id = ${String(id)}
|
|
48
|
+
`;
|
|
49
|
+
await recordPostgresEvent(tx, ctx, {
|
|
50
|
+
queue: job.queue,
|
|
51
|
+
type: 'removed',
|
|
52
|
+
jobId: id,
|
|
53
|
+
occurredAt: await databaseNow(tx),
|
|
54
|
+
job,
|
|
55
|
+
state: row.state,
|
|
56
|
+
removed: true,
|
|
57
|
+
});
|
|
58
|
+
return true;
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
/** Move a runnable pending or actively leased job to the DLQ. */
|
|
62
|
+
export async function discardPostgresJob(ctx, id, token) {
|
|
63
|
+
const request = await ctx.sql.begin(async (tx) => {
|
|
64
|
+
const row = await lockJob(tx, ctx, id);
|
|
65
|
+
if (!row || !['waiting', 'prioritized', 'delayed', 'active'].includes(row.state))
|
|
66
|
+
return null;
|
|
67
|
+
const now = await databaseNow(tx);
|
|
68
|
+
if (row.state === 'active' &&
|
|
69
|
+
(row.lease_token !== token || Number(row.lease_until ?? 0) <= now)) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
const job = decodePostgresJob(row).job;
|
|
73
|
+
job.completedAt = now;
|
|
74
|
+
const { dlq } = await getPostgresQueuePolicies(tx, ctx, job.queue);
|
|
75
|
+
const entry = createDlqEntry(job, "unknown" /* FailureReason.Unknown */, null, dlq, now);
|
|
76
|
+
await deleteJobDependencies(tx, ctx, id);
|
|
77
|
+
await deleteParentFailureValues(tx, ctx, id);
|
|
78
|
+
await tx `
|
|
79
|
+
UPDATE bunqueue_jobs
|
|
80
|
+
SET payload = ${encodePostgresValue(job)}, state = 'failed', completed_at = ${now},
|
|
81
|
+
lease_owner = NULL, lease_broker_id = NULL, lease_broker_session_id = NULL,
|
|
82
|
+
lease_token = NULL, lease_until = NULL,
|
|
83
|
+
error = NULL, failure_reason = ${"unknown" /* FailureReason.Unknown */},
|
|
84
|
+
dlq_entry = ${encodePostgresValue(entry)}, dlq_retry_state = NULL,
|
|
85
|
+
version = version + 1
|
|
86
|
+
WHERE namespace = ${ctx.config.namespace} AND id = ${String(id)}
|
|
87
|
+
`;
|
|
88
|
+
await recordPostgresEvent(tx, ctx, {
|
|
89
|
+
queue: job.queue,
|
|
90
|
+
type: 'failed',
|
|
91
|
+
jobId: id,
|
|
92
|
+
occurredAt: now,
|
|
93
|
+
job,
|
|
94
|
+
state: 'failed',
|
|
95
|
+
dlqEntry: entry,
|
|
96
|
+
dlqRetryState: null,
|
|
97
|
+
});
|
|
98
|
+
return { queue: job.queue, maxEntries: dlq.maxEntries };
|
|
99
|
+
});
|
|
100
|
+
if (!request)
|
|
101
|
+
return false;
|
|
102
|
+
await runPostgresPostCommitMaintenance(ctx, `dlq-limit:${request.queue}`, () => enforcePostgresDlqLimit(ctx, request.queue, request.maxEntries));
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
/** Permanently remove exactly one failed job from its queue. */
|
|
106
|
+
export async function removePostgresDlqJob(ctx, queue, id) {
|
|
107
|
+
return await ctx.sql.begin(async (tx) => {
|
|
108
|
+
await lockPostgresDestructionCandidates(tx, ctx, [id]);
|
|
109
|
+
const row = await lockJob(tx, ctx, id);
|
|
110
|
+
if (!row || row.queue !== queue || row.state !== 'failed')
|
|
111
|
+
return false;
|
|
112
|
+
const { protectedIds } = await partitionPostgresDestructionCandidates(tx, ctx, [id], [id]);
|
|
113
|
+
if (protectedIds.length > 0)
|
|
114
|
+
return false;
|
|
115
|
+
const job = decodePostgresJob(row).job;
|
|
116
|
+
await deleteJobDependencies(tx, ctx, id);
|
|
117
|
+
await tx `
|
|
118
|
+
DELETE FROM bunqueue_job_logs
|
|
119
|
+
WHERE namespace = ${ctx.config.namespace} AND job_id = ${String(id)}
|
|
120
|
+
`;
|
|
121
|
+
await deleteParentFailureValues(tx, ctx, id);
|
|
122
|
+
await tx `
|
|
123
|
+
DELETE FROM bunqueue_jobs
|
|
124
|
+
WHERE namespace = ${ctx.config.namespace} AND id = ${String(id)}
|
|
125
|
+
`;
|
|
126
|
+
await recordPostgresEvent(tx, ctx, {
|
|
127
|
+
queue,
|
|
128
|
+
type: 'removed',
|
|
129
|
+
jobId: id,
|
|
130
|
+
occurredAt: await databaseNow(tx),
|
|
131
|
+
job,
|
|
132
|
+
state: 'failed',
|
|
133
|
+
removed: true,
|
|
134
|
+
});
|
|
135
|
+
return true;
|
|
136
|
+
});
|
|
137
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { TransactionSQL } from 'bun';
|
|
2
|
+
import type { PostgresContext } from './context';
|
|
3
|
+
/** Retry only PostgreSQL failures that guarantee the current transaction was aborted. */
|
|
4
|
+
export declare function isRetryablePostgresTransactionError(error: unknown): boolean;
|
|
5
|
+
/** Replay the complete callback after rollback-certain contention, never after ambiguous I/O. */
|
|
6
|
+
export declare function runPostgresTransactionWithRetry<T>(ctx: PostgresContext, operation: (tx: TransactionSQL) => Promise<T>): Promise<T>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { storageLog } from '../../../shared/logger';
|
|
2
|
+
const MAX_TRANSACTION_ATTEMPTS = 2;
|
|
3
|
+
const RETRYABLE_SQL_STATES = new Set(['40001', '40P01', '55P03']);
|
|
4
|
+
function sqlState(error) {
|
|
5
|
+
if (typeof error !== 'object' || error === null)
|
|
6
|
+
return null;
|
|
7
|
+
const record = error;
|
|
8
|
+
for (const field of ['errno', 'sqlState', 'code']) {
|
|
9
|
+
const value = record[field];
|
|
10
|
+
if (typeof value === 'string' && /^[0-9A-Z]{5}$/.test(value))
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
/** Retry only PostgreSQL failures that guarantee the current transaction was aborted. */
|
|
16
|
+
export function isRetryablePostgresTransactionError(error) {
|
|
17
|
+
const state = sqlState(error);
|
|
18
|
+
return state !== null && RETRYABLE_SQL_STATES.has(state);
|
|
19
|
+
}
|
|
20
|
+
function retryDelayMs(failedAttempt) {
|
|
21
|
+
const base = 10 * 2 ** (failedAttempt - 1);
|
|
22
|
+
return base + Math.floor(Math.random() * base);
|
|
23
|
+
}
|
|
24
|
+
/** Replay the complete callback after rollback-certain contention, never after ambiguous I/O. */
|
|
25
|
+
export async function runPostgresTransactionWithRetry(ctx, operation) {
|
|
26
|
+
for (let attempt = 1;; attempt++) {
|
|
27
|
+
try {
|
|
28
|
+
return await ctx.sql.begin(operation);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (attempt >= MAX_TRANSACTION_ATTEMPTS || !isRetryablePostgresTransactionError(error)) {
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
storageLog.warn('Retrying PostgreSQL transaction after rollback', {
|
|
35
|
+
failedAttempt: attempt,
|
|
36
|
+
maxAttempts: MAX_TRANSACTION_ATTEMPTS,
|
|
37
|
+
sqlState: sqlState(error),
|
|
38
|
+
});
|
|
39
|
+
await Bun.sleep(retryDelayMs(attempt));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import type { DlqConfig, DlqEntry, DlqRetryState } from '../../../domain/types/dlq';
|
|
2
|
+
import type { Job, JobId } from '../../../domain/types/job';
|
|
3
|
+
import type { StallConfig } from '../../../domain/types/stall';
|
|
4
|
+
export type PostgresJobState = 'waiting' | 'prioritized' | 'delayed' | 'waiting-children' | 'active' | 'completed' | 'failed';
|
|
5
|
+
export interface PostgresStorageConfig {
|
|
6
|
+
readonly url: string;
|
|
7
|
+
readonly namespace?: string;
|
|
8
|
+
readonly brokerId?: string;
|
|
9
|
+
readonly poolSize?: number;
|
|
10
|
+
readonly leaseDurationMs?: number;
|
|
11
|
+
readonly pollIntervalMs?: number;
|
|
12
|
+
readonly statementTimeoutMs?: number;
|
|
13
|
+
readonly lockTimeoutMs?: number;
|
|
14
|
+
readonly idleTransactionTimeoutMs?: number;
|
|
15
|
+
readonly maxConcurrentOperations?: number;
|
|
16
|
+
readonly maxQueuedOperations?: number;
|
|
17
|
+
readonly maxSnapshotJobs?: number;
|
|
18
|
+
readonly maxSnapshotPayloadBytes?: number;
|
|
19
|
+
readonly maxQueueEvents?: number;
|
|
20
|
+
readonly maxMetricDataPoints?: number;
|
|
21
|
+
readonly maxCompletedJobs?: number;
|
|
22
|
+
readonly maxJobResults?: number;
|
|
23
|
+
}
|
|
24
|
+
export interface ResolvedPostgresStorageConfig {
|
|
25
|
+
readonly url: string;
|
|
26
|
+
readonly namespace: string;
|
|
27
|
+
readonly brokerId: string;
|
|
28
|
+
readonly brokerSessionId: string;
|
|
29
|
+
readonly poolSize: number;
|
|
30
|
+
readonly leaseDurationMs: number;
|
|
31
|
+
readonly pollIntervalMs: number;
|
|
32
|
+
readonly statementTimeoutMs: number;
|
|
33
|
+
readonly lockTimeoutMs: number;
|
|
34
|
+
readonly idleTransactionTimeoutMs: number;
|
|
35
|
+
readonly maxConcurrentOperations: number;
|
|
36
|
+
readonly maxQueuedOperations: number;
|
|
37
|
+
readonly maxSnapshotJobs: number;
|
|
38
|
+
readonly maxSnapshotPayloadBytes: number;
|
|
39
|
+
readonly maxQueueEvents: number;
|
|
40
|
+
readonly maxMetricDataPoints: number;
|
|
41
|
+
readonly maxCompletedJobs: number;
|
|
42
|
+
readonly maxJobResults: number;
|
|
43
|
+
}
|
|
44
|
+
export interface PostgresJobRow {
|
|
45
|
+
namespace: string;
|
|
46
|
+
id: string;
|
|
47
|
+
queue: string;
|
|
48
|
+
payload: Uint8Array;
|
|
49
|
+
state: PostgresJobState;
|
|
50
|
+
priority: number;
|
|
51
|
+
lifo: boolean;
|
|
52
|
+
run_at: number | string | bigint;
|
|
53
|
+
created_at: number | string | bigint;
|
|
54
|
+
started_at: number | string | bigint | null;
|
|
55
|
+
completed_at: number | string | bigint | null;
|
|
56
|
+
attempts: number;
|
|
57
|
+
max_attempts: number;
|
|
58
|
+
ttl: number | string | bigint | null;
|
|
59
|
+
timeout: number | string | bigint | null;
|
|
60
|
+
unique_key: string | null;
|
|
61
|
+
unique_expires_at: number | string | bigint | null;
|
|
62
|
+
custom_id: string | null;
|
|
63
|
+
group_id: string | null;
|
|
64
|
+
parent_id: string | null;
|
|
65
|
+
lease_owner: string | null;
|
|
66
|
+
lease_broker_id: string | null;
|
|
67
|
+
lease_broker_session_id: string | null;
|
|
68
|
+
lease_token: string | null;
|
|
69
|
+
lease_until: number | string | bigint | null;
|
|
70
|
+
lease_renewals: number;
|
|
71
|
+
result: Uint8Array | null;
|
|
72
|
+
dlq_entry: Uint8Array | null;
|
|
73
|
+
dlq_retry_state: Uint8Array | null;
|
|
74
|
+
error: string | null;
|
|
75
|
+
failure_reason: string | null;
|
|
76
|
+
version: number | string | bigint;
|
|
77
|
+
}
|
|
78
|
+
export interface ClaimedPostgresJob {
|
|
79
|
+
readonly job: Job;
|
|
80
|
+
readonly token: string;
|
|
81
|
+
readonly owner: string;
|
|
82
|
+
readonly brokerId: string;
|
|
83
|
+
readonly leaseUntil: number;
|
|
84
|
+
}
|
|
85
|
+
export interface PostgresStoredJob {
|
|
86
|
+
readonly job: Job;
|
|
87
|
+
readonly state: PostgresJobState;
|
|
88
|
+
readonly result: unknown;
|
|
89
|
+
readonly error: string | null;
|
|
90
|
+
readonly dlqEntry: DlqEntry | null;
|
|
91
|
+
readonly dlqRetryState: DlqRetryState | null;
|
|
92
|
+
readonly token: string | null;
|
|
93
|
+
readonly leaseOwner: string | null;
|
|
94
|
+
readonly leaseBrokerId: string | null;
|
|
95
|
+
readonly leaseUntil: number | null;
|
|
96
|
+
readonly leaseRenewals: number;
|
|
97
|
+
readonly version: number;
|
|
98
|
+
}
|
|
99
|
+
export interface PostgresCompletionResult {
|
|
100
|
+
readonly jobId: JobId;
|
|
101
|
+
readonly queue: string;
|
|
102
|
+
readonly result: unknown;
|
|
103
|
+
readonly pinned: boolean;
|
|
104
|
+
}
|
|
105
|
+
export interface PostgresQueueState {
|
|
106
|
+
readonly queue: string;
|
|
107
|
+
readonly paused: boolean;
|
|
108
|
+
readonly rateLimit: number | null;
|
|
109
|
+
readonly rateDurationMs: number | null;
|
|
110
|
+
readonly rateWindowStartedAt: number | null;
|
|
111
|
+
readonly rateExpiresAt: number | null;
|
|
112
|
+
readonly rateCount: number;
|
|
113
|
+
readonly concurrencyLimit: number | null;
|
|
114
|
+
readonly stallConfig: StallConfig;
|
|
115
|
+
readonly dlqConfig: DlqConfig;
|
|
116
|
+
}
|
|
117
|
+
export interface PostgresCounts {
|
|
118
|
+
readonly waiting: number;
|
|
119
|
+
readonly active: number;
|
|
120
|
+
readonly completed: number;
|
|
121
|
+
readonly failed: number;
|
|
122
|
+
readonly delayed: number;
|
|
123
|
+
readonly prioritized: number;
|
|
124
|
+
readonly waitingChildren: number;
|
|
125
|
+
}
|
|
126
|
+
export interface PostgresTransitionResult {
|
|
127
|
+
readonly applied: boolean;
|
|
128
|
+
readonly alreadyFinalized: boolean;
|
|
129
|
+
readonly job: Job | null;
|
|
130
|
+
readonly state: PostgresJobState | null;
|
|
131
|
+
}
|
|
132
|
+
export interface PostgresCompletionInput {
|
|
133
|
+
readonly id: JobId;
|
|
134
|
+
readonly token: string;
|
|
135
|
+
readonly result?: unknown;
|
|
136
|
+
readonly removeOnComplete?: boolean;
|
|
137
|
+
}
|
|
138
|
+
export interface PostgresBatchCompletionResult extends PostgresTransitionResult {
|
|
139
|
+
readonly removed: boolean;
|
|
140
|
+
}
|
|
141
|
+
export interface PostgresFailureInput {
|
|
142
|
+
readonly id: JobId;
|
|
143
|
+
readonly token: string;
|
|
144
|
+
readonly error?: string;
|
|
145
|
+
readonly stack?: string[];
|
|
146
|
+
readonly unrecoverable?: boolean;
|
|
147
|
+
readonly removeOnFail?: boolean;
|
|
148
|
+
readonly failureReason?: string;
|
|
149
|
+
}
|
|
150
|
+
export interface PostgresStoreEvent {
|
|
151
|
+
readonly id: number;
|
|
152
|
+
readonly queue: string;
|
|
153
|
+
readonly type: string;
|
|
154
|
+
readonly jobId: JobId;
|
|
155
|
+
readonly occurredAt: number;
|
|
156
|
+
readonly job: Job | null;
|
|
157
|
+
readonly state: PostgresJobState | null;
|
|
158
|
+
readonly result?: unknown;
|
|
159
|
+
readonly error?: string;
|
|
160
|
+
readonly removed?: boolean;
|
|
161
|
+
readonly dlqEntry?: DlqEntry | null;
|
|
162
|
+
readonly dlqRetryState?: DlqRetryState | null;
|
|
163
|
+
}
|
|
164
|
+
/** Event delivered from the durable journal after its transaction commit is sequenced. */
|
|
165
|
+
export interface PostgresDeliveredStoreEvent extends PostgresStoreEvent {
|
|
166
|
+
readonly commitSeq: number;
|
|
167
|
+
}
|
|
168
|
+
export interface PostgresStorageHealth {
|
|
169
|
+
readonly ok: boolean;
|
|
170
|
+
readonly error: string | null;
|
|
171
|
+
readonly since: number | null;
|
|
172
|
+
readonly backend: 'postgres';
|
|
173
|
+
readonly brokerId: string;
|
|
174
|
+
readonly namespace: string;
|
|
175
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { SQL, TransactionSQL } from 'bun';
|
|
2
|
+
import type { Worker } from '../../../domain/types/worker';
|
|
3
|
+
import type { PostgresContext } from './context';
|
|
4
|
+
export declare function savePostgresWorker(ctx: PostgresContext, worker: Worker): Promise<void>;
|
|
5
|
+
export declare function removePostgresWorker(ctx: PostgresContext, id: string, clientId?: string): Promise<boolean>;
|
|
6
|
+
export declare function heartbeatPostgresWorker(ctx: PostgresContext, id: string, stats?: {
|
|
7
|
+
activeJobs?: number;
|
|
8
|
+
processed?: number;
|
|
9
|
+
failed?: number;
|
|
10
|
+
}, clientId?: string): Promise<boolean>;
|
|
11
|
+
export declare function removePostgresClientWorkers(ctx: PostgresContext, clientId: string): Promise<number>;
|
|
12
|
+
export declare function removePostgresBrokerWorkers(ctx: PostgresContext): Promise<number>;
|
|
13
|
+
export declare function listPostgresWorkers(ctx: PostgresContext): Promise<Worker[]>;
|
|
14
|
+
export declare function hasActivePostgresWorker(sql: SQL | TransactionSQL, ctx: PostgresContext, queue: string, now: number, timeoutMs?: number): Promise<boolean>;
|
|
15
|
+
export declare function purgeStalePostgresWorkers(ctx: PostgresContext, requestedNow?: number, staleMs?: number): Promise<number>;
|