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