bunqueue 2.8.60 → 2.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -78
- package/dist/application/background/dlq.js +2 -0
- package/dist/application/background/recovery/active.d.ts +1 -0
- package/dist/application/background/recovery/active.js +12 -0
- package/dist/application/background/recovery/index.js +3 -1
- package/dist/application/background/recovery/pending.js +1 -0
- package/dist/application/cleanupTasks.js +4 -16
- package/dist/application/contextFactory.js +8 -0
- package/dist/application/dlqManager.d.ts +10 -0
- package/dist/application/dlqManager.js +48 -9
- package/dist/application/dlqRetry.js +60 -38
- package/dist/application/eventsManager.d.ts +9 -2
- package/dist/application/eventsManager.js +106 -55
- package/dist/application/operations/ackHelpers.d.ts +1 -4
- package/dist/application/operations/ackHelpers.js +39 -14
- package/dist/application/operations/flowPush.js +1 -0
- package/dist/application/operations/flowValidation.js +4 -4
- package/dist/application/operations/jobManagement.d.ts +4 -0
- package/dist/application/operations/jobMoveOperations.js +9 -4
- package/dist/application/operations/pull.d.ts +7 -2
- package/dist/application/operations/pull.js +15 -57
- package/dist/application/operations/pullFinalization.d.ts +6 -0
- package/dist/application/operations/pullFinalization.js +69 -0
- package/dist/application/operations/pullStateTransition.d.ts +8 -7
- package/dist/application/operations/pullStateTransition.js +25 -18
- package/dist/application/operations/push.js +3 -0
- package/dist/application/operations/pushBatch.js +14 -7
- package/dist/application/operations/pushContext.d.ts +2 -1
- 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 +30 -0
- package/dist/application/postgres-queue-manager/control.js +210 -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 +20 -0
- package/dist/application/postgres-queue-manager/delivery.js +83 -0
- package/dist/application/postgres-queue-manager/groupQueries.d.ts +10 -0
- package/dist/application/postgres-queue-manager/groupQueries.js +40 -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/control.js +1 -0
- package/dist/application/queue-manager/delivery.d.ts +5 -4
- package/dist/application/queue-manager/delivery.js +15 -8
- package/dist/application/queue-manager/flow-failures.js +4 -0
- package/dist/application/queue-manager/limits.d.ts +13 -0
- package/dist/application/queue-manager/limits.js +65 -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 +17 -2
- package/dist/application/queueTelemetryJournal.d.ts +2 -0
- package/dist/application/queueTelemetryJournal.js +23 -0
- package/dist/application/types/ack.d.ts +3 -1
- package/dist/cli/commandRouter.d.ts +1 -1
- package/dist/cli/commands/server.js +1 -1
- package/dist/client/flowPush.js +6 -0
- package/dist/client/forwarder.d.ts +6 -4
- package/dist/client/forwarder.js +5 -3
- package/dist/client/groupId.d.ts +1 -0
- package/dist/client/groupId.js +1 -0
- package/dist/client/index.d.ts +1 -1
- package/dist/client/jobHelpers.js +1 -0
- 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/bulk.js +4 -4
- package/dist/client/queue/operations/add/payload.d.ts +1 -0
- package/dist/client/queue/operations/add/payload.js +7 -1
- package/dist/client/queue/operations/add/single.js +3 -3
- package/dist/client/queue/operations/groups.d.ts +21 -0
- package/dist/client/queue/operations/groups.js +88 -0
- package/dist/client/queue/runtime/configuration.d.ts +4 -0
- package/dist/client/queue/runtime/configuration.js +8 -0
- package/dist/client/queue/runtime/queries.d.ts +13 -0
- package/dist/client/queue/runtime/queries.js +31 -0
- package/dist/client/queue/runtime/state.d.ts +4 -0
- package/dist/client/queue/runtime/state.js +1 -0
- package/dist/client/types/index.d.ts +2 -2
- package/dist/client/types/options.d.ts +4 -0
- package/dist/client/types/worker.d.ts +8 -0
- package/dist/client/worker/runtime/execution.js +4 -8
- package/dist/client/worker/runtime/options.js +3 -0
- package/dist/client/worker/runtime/polling.d.ts +1 -0
- package/dist/client/worker/runtime/polling.js +9 -0
- package/dist/client/worker/types/options.d.ts +2 -1
- package/dist/client/worker/workerPull.d.ts +2 -0
- package/dist/client/worker/workerPull.js +6 -4
- 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/job/groupFifoOrder.d.ts +9 -0
- package/dist/domain/job/groupFifoOrder.js +26 -0
- package/dist/domain/queue/dlqShard.d.ts +2 -0
- package/dist/domain/queue/dlqShard.js +16 -0
- package/dist/domain/queue/groupLimiterManager.d.ts +23 -0
- package/dist/domain/queue/groupLimiterManager.js +107 -0
- package/dist/domain/queue/groupScheduler.d.ts +31 -0
- package/dist/domain/queue/groupScheduler.js +256 -0
- package/dist/domain/queue/groupSchedulerOrder.d.ts +6 -0
- package/dist/domain/queue/groupSchedulerOrder.js +30 -0
- package/dist/domain/queue/priorityQueue.d.ts +13 -23
- package/dist/domain/queue/priorityQueue.js +53 -42
- package/dist/domain/queue/shard/dlq.d.ts +1 -0
- package/dist/domain/queue/shard/dlq.js +3 -0
- package/dist/domain/queue/shard/keys.d.ts +1 -0
- package/dist/domain/queue/shard/keys.js +25 -2
- package/dist/domain/queue/shard/lifecycle.js +4 -0
- package/dist/domain/queue/shard/limits.d.ts +20 -1
- package/dist/domain/queue/shard/limits.js +56 -0
- package/dist/domain/queue/shard/state.d.ts +5 -0
- package/dist/domain/queue/shard/state.js +9 -1
- package/dist/domain/types/commands/core.d.ts +3 -0
- package/dist/domain/types/commands/dlq.d.ts +5 -0
- package/dist/domain/types/commands/limits.d.ts +41 -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/group.d.ts +21 -0
- package/dist/domain/types/group.js +78 -0
- package/dist/domain/types/jobs/model.d.ts +1 -1
- package/dist/domain/types/priorityQueue.d.ts +1 -0
- 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/jobOptionsBlob.d.ts +1 -0
- package/dist/infrastructure/persistence/jobOptionsBlob.js +10 -2
- package/dist/infrastructure/persistence/migrations.js +11 -0
- package/dist/infrastructure/persistence/postgres/admission.d.ts +18 -0
- package/dist/infrastructure/persistence/postgres/admission.js +196 -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 +128 -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 +14 -0
- package/dist/infrastructure/persistence/postgres/claimBatch.js +69 -0
- package/dist/infrastructure/persistence/postgres/claimSelection.d.ts +11 -0
- package/dist/infrastructure/persistence/postgres/claimSelection.js +140 -0
- package/dist/infrastructure/persistence/postgres/claims.d.ts +10 -0
- package/dist/infrastructure/persistence/postgres/claims.js +153 -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/eventCatchupCursors.d.ts +32 -0
- package/dist/infrastructure/persistence/postgres/eventCatchupCursors.js +66 -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 +267 -0
- package/dist/infrastructure/persistence/postgres/eventPruneWatermarks.d.ts +26 -0
- package/dist/infrastructure/persistence/postgres/eventPruneWatermarks.js +129 -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 +276 -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/groupClaims.d.ts +15 -0
- package/dist/infrastructure/persistence/postgres/groupClaims.js +95 -0
- package/dist/infrastructure/persistence/postgres/groupSchema.d.ts +2 -0
- package/dist/infrastructure/persistence/postgres/groupSchema.js +155 -0
- package/dist/infrastructure/persistence/postgres/groupSchemaFingerprint.d.ts +3 -0
- package/dist/infrastructure/persistence/postgres/groupSchemaFingerprint.js +127 -0
- package/dist/infrastructure/persistence/postgres/groupStateRetention.d.ts +3 -0
- package/dist/infrastructure/persistence/postgres/groupStateRetention.js +93 -0
- package/dist/infrastructure/persistence/postgres/groups.d.ts +11 -0
- package/dist/infrastructure/persistence/postgres/groups.js +117 -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 +158 -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 +45 -0
- package/dist/infrastructure/persistence/postgres/runtime.js +238 -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 +261 -0
- package/dist/infrastructure/persistence/postgres/schemaInitialization.d.ts +3 -0
- package/dist/infrastructure/persistence/postgres/schemaInitialization.js +226 -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 +100 -0
- package/dist/infrastructure/persistence/postgres/store.js +180 -0
- package/dist/infrastructure/persistence/postgres/telemetry.d.ts +8 -0
- package/dist/infrastructure/persistence/postgres/telemetry.js +100 -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 +176 -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/schema.d.ts +2 -2
- package/dist/infrastructure/persistence/schema.js +12 -1
- package/dist/infrastructure/persistence/sqlite/control.d.ts +14 -0
- package/dist/infrastructure/persistence/sqlite/control.js +69 -0
- package/dist/infrastructure/persistence/sqlite/jobs.d.ts +12 -0
- package/dist/infrastructure/persistence/sqlite/jobs.js +38 -0
- package/dist/infrastructure/persistence/sqlite/telemetry.d.ts +2 -1
- package/dist/infrastructure/persistence/sqlite/telemetry.js +5 -64
- package/dist/infrastructure/persistence/sqlite/telemetryWrites.d.ts +4 -0
- package/dist/infrastructure/persistence/sqlite/telemetryWrites.js +123 -0
- package/dist/infrastructure/persistence/sqliteSerializer.js +2 -0
- 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 +16 -1
- package/dist/infrastructure/server/handler-routes/monitoring.d.ts +2 -2
- package/dist/infrastructure/server/handler.js +9 -11
- 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.d.ts +0 -5
- package/dist/infrastructure/server/handlers/core.js +47 -49
- 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/groups.d.ts +11 -0
- package/dist/infrastructure/server/handlers/groups.js +55 -0
- 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 +56 -8
- 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 +18 -7
- package/dist/infrastructure/server/httpRouteQueues.js +11 -1
- package/dist/infrastructure/server/protocol/validation.d.ts +1 -0
- package/dist/infrastructure/server/protocol/validation.js +1 -0
- package/dist/infrastructure/server/protocol.d.ts +1 -1
- package/dist/infrastructure/server/protocol.js +1 -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 +75 -65
|
@@ -3,33 +3,63 @@ import { MAX_TIMELINE_ENTRIES } from '../domain/types/job';
|
|
|
3
3
|
import { retainDlqRetryState, scheduleNextRetry, setDlqRetryState } from '../domain/types/dlq';
|
|
4
4
|
import { shardIndex } from '../shared/hash';
|
|
5
5
|
function prepareRetry(job, now) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
const timeline = [...job.timeline];
|
|
7
|
+
if (timeline.length < MAX_TIMELINE_ENTRIES)
|
|
8
|
+
timeline.push({ state: 'waiting', timestamp: now });
|
|
9
|
+
return {
|
|
10
|
+
...job,
|
|
11
|
+
attempts: 0,
|
|
12
|
+
lastHeartbeat: now,
|
|
13
|
+
runAt: now,
|
|
14
|
+
stallCount: 0,
|
|
15
|
+
startedAt: null,
|
|
16
|
+
timeline,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function canRetry(queue, job, ctx) {
|
|
20
|
+
const idx = shardIndex(queue);
|
|
21
|
+
const shard = ctx.shards[idx];
|
|
22
|
+
const location = ctx.jobIndex.get(job.id);
|
|
23
|
+
if (location?.type !== 'dlq' || location.queueName !== queue)
|
|
24
|
+
return false;
|
|
25
|
+
const customOwner = job.customId ? ctx.customIdMap.get(job.customId) : undefined;
|
|
26
|
+
if (customOwner && customOwner !== job.id)
|
|
27
|
+
return false;
|
|
28
|
+
const keyOwner = job.uniqueKey ? shard.getUniqueKeyEntry(queue, job.uniqueKey) : null;
|
|
29
|
+
return keyOwner === null || keyOwner.jobId === job.id;
|
|
14
30
|
}
|
|
15
|
-
function
|
|
31
|
+
function publishRetry(queue, job, ctx) {
|
|
16
32
|
const idx = shardIndex(queue);
|
|
17
33
|
const shard = ctx.shards[idx];
|
|
18
|
-
prepareRetry(job, now);
|
|
19
34
|
shard.getQueue(queue).push(job);
|
|
20
|
-
shard.incrementQueued(job.id,
|
|
35
|
+
shard.incrementQueued(job.id, false, job.createdAt, queue, job.runAt);
|
|
21
36
|
ctx.jobIndex.set(job.id, { type: 'queue', shardIdx: idx, queueName: queue });
|
|
37
|
+
if (job.customId)
|
|
38
|
+
ctx.customIdMap.set(job.customId, job.id);
|
|
39
|
+
if (job.uniqueKey) {
|
|
40
|
+
shard.registerUniqueKeyWithTtl(queue, job.uniqueKey, job.id, job.deduplicationTtl ?? undefined);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function retryEntry(queue, entry, ctx, now, prepareState) {
|
|
44
|
+
if (!canRetry(queue, entry.job, ctx))
|
|
45
|
+
return null;
|
|
46
|
+
const job = prepareRetry(entry.job, now);
|
|
47
|
+
ctx.shards[shardIndex(queue)].assignGroupFifoOrder(job);
|
|
48
|
+
prepareState(job);
|
|
22
49
|
ctx.storage?.requeueDlqJob(job);
|
|
50
|
+
const removed = ctx.shards[shardIndex(queue)].removeFromDlq(queue, entry.job.id);
|
|
51
|
+
if (!removed)
|
|
52
|
+
throw new Error('DLQ entry disappeared after its retry committed');
|
|
53
|
+
publishRetry(queue, job, ctx);
|
|
54
|
+
return job;
|
|
23
55
|
}
|
|
24
56
|
/** Retry a single job from DLQ and reset the automatic retry generation. */
|
|
25
57
|
export function retryDlqJob(queue, jobId, ctx) {
|
|
26
58
|
const shard = ctx.shards[shardIndex(queue)];
|
|
27
|
-
const entry = shard.
|
|
59
|
+
const entry = shard.getDlqEntries(queue).find((candidate) => candidate.job.id === jobId);
|
|
28
60
|
if (!entry)
|
|
29
61
|
return null;
|
|
30
|
-
|
|
31
|
-
enqueueRetry(queue, entry.job, Date.now(), ctx);
|
|
32
|
-
return entry.job;
|
|
62
|
+
return retryEntry(queue, entry, ctx, Date.now(), (job) => setDlqRetryState(job, null));
|
|
33
63
|
}
|
|
34
64
|
/** Retry jobs from DLQ, optionally bounded to the oldest `limit` entries. */
|
|
35
65
|
export function retryDlqJobs(queue, ctx, jobId, limit) {
|
|
@@ -49,29 +79,21 @@ export function retryDlqJobs(queue, ctx, jobId, limit) {
|
|
|
49
79
|
}
|
|
50
80
|
return retried;
|
|
51
81
|
}
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
enqueueRetry(queue, entry.job, now, ctx);
|
|
59
|
-
}
|
|
60
|
-
return entries.length;
|
|
82
|
+
const ids = shard.getDlqEntries(queue).map((entry) => entry.job.id);
|
|
83
|
+
let retried = 0;
|
|
84
|
+
for (const id of ids)
|
|
85
|
+
if (retryDlqJob(queue, id, ctx))
|
|
86
|
+
retried++;
|
|
87
|
+
return retried;
|
|
61
88
|
}
|
|
62
89
|
/** Retry all DLQ entries selected by a metadata filter. */
|
|
63
90
|
export function retryDlqByFilter(queue, ctx, filter) {
|
|
64
91
|
const shard = ctx.shards[shardIndex(queue)];
|
|
65
92
|
const entries = [...shard.getDlqFiltered(queue, filter)];
|
|
66
|
-
const now = Date.now();
|
|
67
93
|
let retried = 0;
|
|
68
94
|
for (const entry of entries) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
continue;
|
|
72
|
-
setDlqRetryState(removed.job, null);
|
|
73
|
-
enqueueRetry(queue, removed.job, now, ctx);
|
|
74
|
-
retried++;
|
|
95
|
+
if (retryDlqJob(queue, entry.job.id, ctx))
|
|
96
|
+
retried++;
|
|
75
97
|
}
|
|
76
98
|
return retried;
|
|
77
99
|
}
|
|
@@ -85,13 +107,13 @@ export function processAutoRetry(queue, ctx) {
|
|
|
85
107
|
const entries = [...shard.getAutoRetryEntries(queue, now)];
|
|
86
108
|
let retried = 0;
|
|
87
109
|
for (const entry of entries) {
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
110
|
+
const scheduled = { ...entry, attempts: [...entry.attempts] };
|
|
111
|
+
scheduleNextRetry(scheduled, config);
|
|
112
|
+
const job = retryEntry(queue, entry, ctx, now, (candidate) => {
|
|
113
|
+
retainDlqRetryState(candidate, scheduled);
|
|
114
|
+
});
|
|
115
|
+
if (job)
|
|
116
|
+
retried++;
|
|
95
117
|
}
|
|
96
118
|
return retried;
|
|
97
119
|
}
|
|
@@ -7,11 +7,14 @@ import { EventType, type JobEvent } from '../domain/types/queue';
|
|
|
7
7
|
import type { WebhookManager } from './webhookManager';
|
|
8
8
|
/** Event subscriber callback */
|
|
9
9
|
export type EventSubscriber = (event: JobEvent) => void;
|
|
10
|
+
export type EventBatchSubscriber = (events: readonly JobEvent[]) => void;
|
|
10
11
|
/** Events manager class */
|
|
11
12
|
export declare class EventsManager {
|
|
12
13
|
private readonly webhookManager;
|
|
13
14
|
/** Use Set for O(1) subscribe/unsubscribe instead of indexOf+splice */
|
|
14
15
|
private readonly subscribers;
|
|
16
|
+
/** Optional batch path for internal subscribers such as durable telemetry. */
|
|
17
|
+
private readonly batchSubscribers;
|
|
15
18
|
/** Waiters for specific job completions - for efficient WaitJob implementation */
|
|
16
19
|
private readonly completionWaiters;
|
|
17
20
|
constructor(webhookManager: WebhookManager);
|
|
@@ -20,14 +23,14 @@ export declare class EventsManager {
|
|
|
20
23
|
/** Number of jobs with active completion waiters */
|
|
21
24
|
get completionWaiterCount(): number;
|
|
22
25
|
/** Subscribe to job events - O(1) add and remove */
|
|
23
|
-
subscribe(callback: EventSubscriber): () => void;
|
|
26
|
+
subscribe(callback: EventSubscriber, batchCallback?: EventBatchSubscriber): () => void;
|
|
24
27
|
/** Clear all subscribers (for shutdown) */
|
|
25
28
|
clear(): void;
|
|
26
29
|
/**
|
|
27
30
|
* Wait for a specific job to complete - event-driven, no polling
|
|
28
31
|
* Returns true if job completed, false if timeout
|
|
29
32
|
*/
|
|
30
|
-
waitForJobCompletion(jobId: JobId, timeoutMs: number): Promise<boolean>;
|
|
33
|
+
waitForJobCompletion(jobId: JobId, timeoutMs: number, signal?: AbortSignal): Promise<boolean>;
|
|
31
34
|
/** Check if broadcast has any listeners - for batch optimizations */
|
|
32
35
|
needsBroadcast(): boolean;
|
|
33
36
|
/** Broadcast event to all subscribers - optimized to skip work when no listeners */
|
|
@@ -38,6 +41,10 @@ export declare class EventsManager {
|
|
|
38
41
|
timestamp: number;
|
|
39
42
|
error?: string;
|
|
40
43
|
}): void;
|
|
44
|
+
/** Broadcast an ordered batch while allowing internal subscribers to persist once. */
|
|
45
|
+
broadcastBatch(events: readonly JobEvent[]): void;
|
|
46
|
+
private notifyCompletionWaiters;
|
|
47
|
+
private triggerWebhook;
|
|
41
48
|
/** Map internal event type to webhook event */
|
|
42
49
|
private mapEventToWebhook;
|
|
43
50
|
}
|
|
@@ -8,6 +8,8 @@ export class EventsManager {
|
|
|
8
8
|
webhookManager;
|
|
9
9
|
/** Use Set for O(1) subscribe/unsubscribe instead of indexOf+splice */
|
|
10
10
|
subscribers = new Set();
|
|
11
|
+
/** Optional batch path for internal subscribers such as durable telemetry. */
|
|
12
|
+
batchSubscribers = new Map();
|
|
11
13
|
/** Waiters for specific job completions - for efficient WaitJob implementation */
|
|
12
14
|
completionWaiters = new Map();
|
|
13
15
|
constructor(webhookManager) {
|
|
@@ -22,21 +24,24 @@ export class EventsManager {
|
|
|
22
24
|
return this.completionWaiters.size;
|
|
23
25
|
}
|
|
24
26
|
/** Subscribe to job events - O(1) add and remove */
|
|
25
|
-
subscribe(callback) {
|
|
27
|
+
subscribe(callback, batchCallback) {
|
|
26
28
|
this.subscribers.add(callback);
|
|
29
|
+
if (batchCallback)
|
|
30
|
+
this.batchSubscribers.set(callback, batchCallback);
|
|
27
31
|
return () => {
|
|
28
32
|
this.subscribers.delete(callback); // O(1) instead of O(n)
|
|
33
|
+
this.batchSubscribers.delete(callback);
|
|
29
34
|
};
|
|
30
35
|
}
|
|
31
36
|
/** Clear all subscribers (for shutdown) */
|
|
32
37
|
clear() {
|
|
33
38
|
this.subscribers.clear();
|
|
39
|
+
this.batchSubscribers.clear();
|
|
34
40
|
// Clear all waiters
|
|
35
41
|
for (const waiters of this.completionWaiters.values()) {
|
|
36
42
|
for (const waiter of waiters) {
|
|
37
|
-
if (!waiter.cancelled)
|
|
43
|
+
if (!waiter.cancelled)
|
|
38
44
|
waiter.resolve();
|
|
39
|
-
}
|
|
40
45
|
}
|
|
41
46
|
}
|
|
42
47
|
this.completionWaiters.clear();
|
|
@@ -45,40 +50,45 @@ export class EventsManager {
|
|
|
45
50
|
* Wait for a specific job to complete - event-driven, no polling
|
|
46
51
|
* Returns true if job completed, false if timeout
|
|
47
52
|
*/
|
|
48
|
-
waitForJobCompletion(jobId, timeoutMs) {
|
|
53
|
+
waitForJobCompletion(jobId, timeoutMs, signal) {
|
|
49
54
|
const jobKey = String(jobId);
|
|
55
|
+
if (signal?.aborted)
|
|
56
|
+
return Promise.resolve(false);
|
|
50
57
|
return new Promise((resolve) => {
|
|
58
|
+
let settled = false;
|
|
59
|
+
const cleanup = () => {
|
|
60
|
+
clearTimeout(timer);
|
|
61
|
+
signal?.removeEventListener('abort', onAbort);
|
|
62
|
+
const waiters = this.completionWaiters.get(jobKey);
|
|
63
|
+
waiters?.delete(waiter);
|
|
64
|
+
if (waiters?.size === 0)
|
|
65
|
+
this.completionWaiters.delete(jobKey);
|
|
66
|
+
};
|
|
67
|
+
const finish = (completed) => {
|
|
68
|
+
if (settled)
|
|
69
|
+
return;
|
|
70
|
+
settled = true;
|
|
71
|
+
waiter.cancelled = !completed;
|
|
72
|
+
cleanup();
|
|
73
|
+
resolve(completed);
|
|
74
|
+
};
|
|
75
|
+
const onAbort = () => finish(false);
|
|
51
76
|
const waiter = {
|
|
52
|
-
resolve: () =>
|
|
53
|
-
|
|
54
|
-
resolve(true);
|
|
55
|
-
},
|
|
77
|
+
resolve: () => finish(true),
|
|
78
|
+
cancel: () => finish(false),
|
|
56
79
|
cancelled: false,
|
|
57
80
|
};
|
|
58
|
-
const timer = setTimeout(() => {
|
|
59
|
-
// Timeout - mark as cancelled and remove from map to prevent memory leak
|
|
60
|
-
waiter.cancelled = true;
|
|
61
|
-
// Remove the waiter from the array
|
|
62
|
-
const waiters = this.completionWaiters.get(jobKey);
|
|
63
|
-
if (waiters) {
|
|
64
|
-
const index = waiters.indexOf(waiter);
|
|
65
|
-
if (index !== -1) {
|
|
66
|
-
waiters.splice(index, 1);
|
|
67
|
-
}
|
|
68
|
-
// Clean up empty arrays to free memory
|
|
69
|
-
if (waiters.length === 0) {
|
|
70
|
-
this.completionWaiters.delete(jobKey);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
resolve(false);
|
|
74
|
-
}, timeoutMs);
|
|
75
81
|
// Add to waiters
|
|
76
82
|
let waiters = this.completionWaiters.get(jobKey);
|
|
77
83
|
if (!waiters) {
|
|
78
|
-
waiters =
|
|
84
|
+
waiters = new Set();
|
|
79
85
|
this.completionWaiters.set(jobKey, waiters);
|
|
80
86
|
}
|
|
81
|
-
waiters.
|
|
87
|
+
waiters.add(waiter);
|
|
88
|
+
const timer = setTimeout(() => finish(false), timeoutMs);
|
|
89
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
90
|
+
if (signal?.aborted)
|
|
91
|
+
onAbort();
|
|
82
92
|
});
|
|
83
93
|
}
|
|
84
94
|
/** Check if broadcast has any listeners - for batch optimizations */
|
|
@@ -108,40 +118,81 @@ export class EventsManager {
|
|
|
108
118
|
}
|
|
109
119
|
}
|
|
110
120
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
121
|
+
if (hasWaiters)
|
|
122
|
+
this.notifyCompletionWaiters(event);
|
|
123
|
+
if (hasWebhooks)
|
|
124
|
+
this.triggerWebhook(event);
|
|
125
|
+
}
|
|
126
|
+
/** Broadcast an ordered batch while allowing internal subscribers to persist once. */
|
|
127
|
+
broadcastBatch(events) {
|
|
128
|
+
if (events.length === 0)
|
|
129
|
+
return;
|
|
130
|
+
const hasSubscribers = this.subscribers.size > 0;
|
|
131
|
+
const hasWebhooks = this.webhookManager.hasEnabledWebhooks();
|
|
132
|
+
const hasWaiters = this.completionWaiters.size > 0;
|
|
133
|
+
if (!hasSubscribers && !hasWebhooks && !hasWaiters)
|
|
134
|
+
return;
|
|
135
|
+
if (hasSubscribers) {
|
|
136
|
+
for (const [subscriber, batchSubscriber] of this.batchSubscribers) {
|
|
137
|
+
if (!this.subscribers.has(subscriber))
|
|
138
|
+
continue;
|
|
139
|
+
try {
|
|
140
|
+
batchSubscriber(events);
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
// Ignore subscriber errors.
|
|
122
144
|
}
|
|
123
145
|
}
|
|
124
146
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
jobId: String(event.jobId),
|
|
138
|
-
queue: event.queue,
|
|
139
|
-
error: String(err),
|
|
140
|
-
});
|
|
141
|
-
});
|
|
147
|
+
for (const event of events) {
|
|
148
|
+
if (hasSubscribers) {
|
|
149
|
+
for (const subscriber of this.subscribers) {
|
|
150
|
+
if (this.batchSubscribers.has(subscriber))
|
|
151
|
+
continue;
|
|
152
|
+
try {
|
|
153
|
+
subscriber(event);
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
// Ignore subscriber errors and continue with the ordered batch.
|
|
157
|
+
}
|
|
158
|
+
}
|
|
142
159
|
}
|
|
160
|
+
if (hasWaiters && event.eventType === "completed" /* EventType.Completed */) {
|
|
161
|
+
this.notifyCompletionWaiters(event);
|
|
162
|
+
}
|
|
163
|
+
if (hasWebhooks)
|
|
164
|
+
this.triggerWebhook(event);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
notifyCompletionWaiters(event) {
|
|
168
|
+
const jobKey = String(event.jobId);
|
|
169
|
+
const waiters = this.completionWaiters.get(jobKey);
|
|
170
|
+
if (!waiters)
|
|
171
|
+
return;
|
|
172
|
+
this.completionWaiters.delete(jobKey);
|
|
173
|
+
for (const waiter of waiters) {
|
|
174
|
+
if (!waiter.cancelled)
|
|
175
|
+
waiter.resolve();
|
|
143
176
|
}
|
|
144
177
|
}
|
|
178
|
+
triggerWebhook(event) {
|
|
179
|
+
const webhookEvent = this.mapEventToWebhook(event.eventType);
|
|
180
|
+
if (!webhookEvent)
|
|
181
|
+
return;
|
|
182
|
+
this.webhookManager
|
|
183
|
+
.trigger(webhookEvent, String(event.jobId), event.queue, {
|
|
184
|
+
data: event.data,
|
|
185
|
+
error: event.error,
|
|
186
|
+
})
|
|
187
|
+
.catch((err) => {
|
|
188
|
+
webhookLog.error('Webhook trigger failed', {
|
|
189
|
+
event: webhookEvent,
|
|
190
|
+
jobId: String(event.jobId),
|
|
191
|
+
queue: event.queue,
|
|
192
|
+
error: String(err),
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
}
|
|
145
196
|
/** Map internal event type to webhook event */
|
|
146
197
|
mapEventToWebhook(eventType) {
|
|
147
198
|
switch (eventType) {
|
|
@@ -2,10 +2,7 @@
|
|
|
2
2
|
import type { Job, JobId } from '../../domain/types/job';
|
|
3
3
|
import type { BatchContext, ExtractedJob, FinalizeContext } from '../types/ack';
|
|
4
4
|
export type { BatchContext, ExtractedJob, FinalizeContext } from '../types/ack';
|
|
5
|
-
/**
|
|
6
|
-
* Group job IDs by processing shard
|
|
7
|
-
* Returns Map<shardIndex, jobIds[]>
|
|
8
|
-
*/
|
|
5
|
+
/** Group job IDs by processing shard. */
|
|
9
6
|
export declare function groupByProcShard(jobIds: JobId[]): Map<number, JobId[]>;
|
|
10
7
|
/**
|
|
11
8
|
* Group items by processing shard (with results)
|
|
@@ -4,10 +4,30 @@ import { withWriteLock } from '../../shared/lock';
|
|
|
4
4
|
import { shardIndex, processingShardIndex } from '../../shared/hash';
|
|
5
5
|
import { throughputTracker } from '../throughputTracker';
|
|
6
6
|
import { commitRemovedCompletion } from '../dependencyCompletions';
|
|
7
|
-
/**
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
/** Batch only when no per-job durable result/removal ordering must be preserved. */
|
|
8
|
+
function persistCompletedBatch(extractedJobs, ctx, includeResults, now) {
|
|
9
|
+
const storage = ctx.storage;
|
|
10
|
+
if (!storage || extractedJobs.length === 0)
|
|
11
|
+
return false;
|
|
12
|
+
if (extractedJobs.some(({ job, removeOnComplete }) => job.removeOnComplete || removeOnComplete === true) ||
|
|
13
|
+
(includeResults && extractedJobs.some(({ result }) => result !== undefined))) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
storage.markCompletedBatch(extractedJobs.map(({ id: jobId, job }) => ({
|
|
18
|
+
jobId,
|
|
19
|
+
completedAt: now,
|
|
20
|
+
timeline: job.timeline.length < MAX_TIMELINE_ENTRIES
|
|
21
|
+
? [...job.timeline, { state: 'completed', timestamp: now }]
|
|
22
|
+
: job.timeline,
|
|
23
|
+
})));
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** Group job IDs by processing shard. */
|
|
11
31
|
export function groupByProcShard(jobIds) {
|
|
12
32
|
const byProcShard = new Map();
|
|
13
33
|
for (const jobId of jobIds) {
|
|
@@ -119,6 +139,7 @@ export function finalizeBatchAck(extractedJobs, ctx, includeResults) {
|
|
|
119
139
|
const jobCount = extractedJobs.length;
|
|
120
140
|
const needsBroadcast = ctx.needsBroadcast?.() ?? true;
|
|
121
141
|
const hasPendingDeps = ctx.hasPendingDeps?.() ?? true;
|
|
142
|
+
const completionBatchPersisted = persistCompletedBatch(extractedJobs, ctx, includeResults, now);
|
|
122
143
|
// Batch counter update
|
|
123
144
|
ctx.totalCompleted.value += BigInt(jobCount);
|
|
124
145
|
// Per-queue completed counter update
|
|
@@ -160,8 +181,9 @@ export function finalizeBatchAck(extractedJobs, ctx, includeResults) {
|
|
|
160
181
|
// 2. Update job index and store job data for completed listing
|
|
161
182
|
ctx.jobIndex.set(jobId, { type: 'completed', queueName: job.queue });
|
|
162
183
|
ctx.completedJobsData.set(jobId, job);
|
|
163
|
-
if (hasStorage)
|
|
184
|
+
if (hasStorage && !completionBatchPersisted) {
|
|
164
185
|
storage.markCompleted(jobId, now, job.timeline);
|
|
186
|
+
}
|
|
165
187
|
// 3. Mark as completed LAST - this is the signal other threads wait for
|
|
166
188
|
ctx.completedJobs.add(jobId);
|
|
167
189
|
}
|
|
@@ -180,15 +202,18 @@ export function finalizeBatchAck(extractedJobs, ctx, includeResults) {
|
|
|
180
202
|
}
|
|
181
203
|
// Broadcast events
|
|
182
204
|
if (needsBroadcast) {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
205
|
+
const events = extractedJobs.map(({ id: jobId, job, result }) => ({
|
|
206
|
+
eventType: 'completed',
|
|
207
|
+
queue: job.queue,
|
|
208
|
+
jobId,
|
|
209
|
+
timestamp: now,
|
|
210
|
+
data: includeResults ? result : undefined,
|
|
211
|
+
}));
|
|
212
|
+
if (ctx.broadcastBatch)
|
|
213
|
+
ctx.broadcastBatch(events);
|
|
214
|
+
else {
|
|
215
|
+
for (const event of events)
|
|
216
|
+
ctx.broadcast(event);
|
|
192
217
|
}
|
|
193
218
|
}
|
|
194
219
|
// Notify completions
|
|
@@ -29,6 +29,7 @@ function assertIdsAvailable(batch, ctx) {
|
|
|
29
29
|
function prepareJobs(batch, ctx, now) {
|
|
30
30
|
return batch.jobs.map((planned) => {
|
|
31
31
|
const job = createJob(planned.id, planned.queue, planned.input, now);
|
|
32
|
+
ctx.shards[shardIndex(planned.queue)].assignGroupFifoOrder(job);
|
|
32
33
|
job.timeline.push({ state: initialJobState(job, ctx, now), timestamp: now });
|
|
33
34
|
return job;
|
|
34
35
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { validateGroupId } from '../../domain/types/group';
|
|
1
2
|
import { normalizeJobPayload } from '../../domain/types/job';
|
|
2
3
|
import { validateFlowTopology } from './flowTopologyValidation';
|
|
3
4
|
const MAX_FLOW_JOBS = 10_000;
|
|
@@ -52,10 +53,9 @@ function validateOptions(input) {
|
|
|
52
53
|
throw new Error(`${name} must be a boolean`);
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
throw new Error(
|
|
58
|
-
}
|
|
56
|
+
const groupError = validateGroupId(input.groupId);
|
|
57
|
+
if (groupError)
|
|
58
|
+
throw new Error(groupError);
|
|
59
59
|
if (input.tags !== undefined &&
|
|
60
60
|
(!Array.isArray(input.tags) ||
|
|
61
61
|
input.tags.some((tag) => typeof tag !== 'string' || tag.length > 256))) {
|
|
@@ -26,6 +26,10 @@ export interface JobManagementContext {
|
|
|
26
26
|
eventsManager: EventsManager;
|
|
27
27
|
repeatChain?: Map<JobId, JobId>;
|
|
28
28
|
dependencyResults: DependencyResultTracker;
|
|
29
|
+
customIdMap: {
|
|
30
|
+
get(id: string): JobId | undefined;
|
|
31
|
+
delete(id: string): boolean;
|
|
32
|
+
};
|
|
29
33
|
depCompletions?: DependencyCompletionTracker;
|
|
30
34
|
maxDependencyCompletions: number;
|
|
31
35
|
}
|
|
@@ -75,7 +75,7 @@ export async function discardJob(jobId, ctx) {
|
|
|
75
75
|
const validJob = job;
|
|
76
76
|
const idx = shardIndex(validJob.queue);
|
|
77
77
|
const fromProcessing = location.type === 'processing';
|
|
78
|
-
|
|
78
|
+
await withWriteLock(ctx.shardLocks[idx], () => {
|
|
79
79
|
const shard = ctx.shards[idx];
|
|
80
80
|
if (fromProcessing) {
|
|
81
81
|
shard.releaseJobResources(validJob.queue, validJob.uniqueKey, validJob.groupId, validJob.id);
|
|
@@ -86,9 +86,14 @@ export async function discardJob(jobId, ctx) {
|
|
|
86
86
|
}
|
|
87
87
|
const dlqEntry = shard.addToDlq(validJob);
|
|
88
88
|
ctx.jobIndex.set(jobId, { type: 'dlq', queueName: validJob.queue });
|
|
89
|
-
|
|
89
|
+
// SQLite writes are synchronous. Keeping them in this critical section
|
|
90
|
+
// prevents a concurrent permanent removal from racing a late DLQ insert.
|
|
91
|
+
ctx.storage?.saveDlqEntry(dlqEntry);
|
|
92
|
+
ctx.storage?.deleteJob(jobId);
|
|
93
|
+
ctx.dependencyResults.releaseConsumer(jobId);
|
|
94
|
+
if (validJob.customId && ctx.customIdMap.get(validJob.customId) === jobId) {
|
|
95
|
+
ctx.customIdMap.delete(validJob.customId);
|
|
96
|
+
}
|
|
90
97
|
});
|
|
91
|
-
ctx.storage?.saveDlqEntry(entry);
|
|
92
|
-
ctx.storage?.deleteJob(jobId);
|
|
93
98
|
return true;
|
|
94
99
|
}
|
|
@@ -3,13 +3,18 @@
|
|
|
3
3
|
* Job pull logic with timeout support
|
|
4
4
|
*/
|
|
5
5
|
import type { Job } from '../../domain/types/job';
|
|
6
|
+
import { type GroupPullOptions } from '../../domain/types/group';
|
|
6
7
|
import { type PullContext } from './pullStateTransition';
|
|
7
8
|
export type { PullContext } from './pullStateTransition';
|
|
9
|
+
interface PullRequestOptions {
|
|
10
|
+
signal?: AbortSignal;
|
|
11
|
+
group?: GroupPullOptions;
|
|
12
|
+
}
|
|
8
13
|
/**
|
|
9
14
|
* Pull next job from queue
|
|
10
15
|
*/
|
|
11
|
-
export declare function pullJob(queue: string, timeoutMs: number, ctx: PullContext, signal?: AbortSignal): Promise<Job | null>;
|
|
16
|
+
export declare function pullJob(queue: string, timeoutMs: number, ctx: PullContext, signal?: AbortSignal, groupOptions?: GroupPullOptions): Promise<Job | null>;
|
|
12
17
|
/**
|
|
13
18
|
* Pull multiple jobs from queue
|
|
14
19
|
*/
|
|
15
|
-
export declare function pullJobBatch(queue: string, count: number, timeoutMs: number, ctx: PullContext,
|
|
20
|
+
export declare function pullJobBatch(queue: string, count: number, timeoutMs: number, ctx: PullContext, options?: PullRequestOptions): Promise<Job[]>;
|