bunqueue 2.8.60 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -76
- package/dist/application/background/dlq.js +2 -0
- package/dist/application/contextFactory.js +5 -0
- package/dist/application/dlqManager.d.ts +10 -0
- package/dist/application/dlqManager.js +47 -9
- 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/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/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/cli/commands/server.js +1 -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/runtime/configuration.d.ts +4 -0
- package/dist/client/queue/runtime/configuration.js +8 -0
- package/dist/client/worker/runtime/execution.js +3 -8
- package/dist/client/worker/runtime/polling.d.ts +1 -0
- package/dist/client/worker/runtime/polling.js +9 -0
- 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/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/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.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 +18 -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 +74 -65
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { buildRepeatSuccessor } from '../../../application/repeatJobs';
|
|
2
|
+
import { createJob, generateJobId, MAX_TIMELINE_ENTRIES, } from '../../../domain/types/job';
|
|
3
|
+
import { admitPostgresJob } from './admission';
|
|
4
|
+
import { decodePostgresJob, encodePostgresValue } from './codec';
|
|
5
|
+
import { databaseNow, recordPostgresEvent } from './context';
|
|
6
|
+
import { planPostgresDependencyCompletion } from './dependencyPromotion';
|
|
7
|
+
import { clearPostgresParentFlowFailures } from './flowFailures';
|
|
8
|
+
import { runPostgresTransactionWithRetry } from './transactionRetry';
|
|
9
|
+
import { tryLockPostgresRepeatQueues } from './queueLifecycle';
|
|
10
|
+
async function lockActiveJob(tx, ctx, id) {
|
|
11
|
+
const rows = await tx `
|
|
12
|
+
SELECT * FROM bunqueue_jobs
|
|
13
|
+
WHERE namespace = ${ctx.config.namespace} AND id = ${String(id)}
|
|
14
|
+
FOR UPDATE
|
|
15
|
+
`;
|
|
16
|
+
return rows[0] ?? null;
|
|
17
|
+
}
|
|
18
|
+
function notApplied(row) {
|
|
19
|
+
return {
|
|
20
|
+
applied: false,
|
|
21
|
+
alreadyFinalized: row?.state === 'completed' || row?.state === 'failed',
|
|
22
|
+
job: row ? decodePostgresJob(row).job : null,
|
|
23
|
+
state: row?.state ?? null,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
async function deleteLiveJob(tx, ctx, id) {
|
|
27
|
+
await tx `
|
|
28
|
+
DELETE FROM bunqueue_job_logs
|
|
29
|
+
WHERE namespace = ${ctx.config.namespace} AND job_id = ${String(id)}
|
|
30
|
+
`;
|
|
31
|
+
await tx `
|
|
32
|
+
DELETE FROM bunqueue_dependencies
|
|
33
|
+
WHERE namespace = ${ctx.config.namespace} AND job_id = ${String(id)}
|
|
34
|
+
`;
|
|
35
|
+
await tx `
|
|
36
|
+
DELETE FROM bunqueue_jobs
|
|
37
|
+
WHERE namespace = ${ctx.config.namespace} AND id = ${String(id)}
|
|
38
|
+
`;
|
|
39
|
+
}
|
|
40
|
+
export async function completePostgresJob(ctx, id, token, result, removeOnComplete = false) {
|
|
41
|
+
return await runPostgresTransactionWithRetry(ctx, async (tx) => {
|
|
42
|
+
const dependencyCompletion = await planPostgresDependencyCompletion(tx, ctx, [id]);
|
|
43
|
+
const row = await lockActiveJob(tx, ctx, id);
|
|
44
|
+
const now = await databaseNow(tx);
|
|
45
|
+
if (row?.state !== 'active' ||
|
|
46
|
+
row.lease_token !== token ||
|
|
47
|
+
Number(row.lease_until ?? 0) <= now) {
|
|
48
|
+
return notApplied(row);
|
|
49
|
+
}
|
|
50
|
+
const job = decodePostgresJob(row).job;
|
|
51
|
+
job.completedAt = now;
|
|
52
|
+
job.progress = 100;
|
|
53
|
+
if (job.timeline.length < MAX_TIMELINE_ENTRIES) {
|
|
54
|
+
job.timeline.push({ state: 'completed', timestamp: now });
|
|
55
|
+
}
|
|
56
|
+
const resultPayload = encodePostgresValue(result);
|
|
57
|
+
await clearPostgresParentFlowFailures(tx, ctx, id);
|
|
58
|
+
await tx `
|
|
59
|
+
INSERT INTO bunqueue_completions (namespace, job_id, queue, completed_at, result)
|
|
60
|
+
VALUES (${ctx.config.namespace}, ${String(id)}, ${job.queue}, ${now}, ${resultPayload})
|
|
61
|
+
ON CONFLICT (namespace, job_id) DO UPDATE SET
|
|
62
|
+
queue = excluded.queue, completed_at = excluded.completed_at, result = excluded.result
|
|
63
|
+
`;
|
|
64
|
+
const removed = job.removeOnComplete || removeOnComplete;
|
|
65
|
+
if (removed) {
|
|
66
|
+
await deleteLiveJob(tx, ctx, id);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
await tx `
|
|
70
|
+
UPDATE bunqueue_jobs
|
|
71
|
+
SET payload = ${encodePostgresValue(job)}, state = 'completed', completed_at = ${now},
|
|
72
|
+
result = ${resultPayload}, lease_owner = NULL, lease_token = NULL,
|
|
73
|
+
lease_broker_id = NULL, lease_broker_session_id = NULL,
|
|
74
|
+
lease_until = NULL, dlq_retry_state = NULL,
|
|
75
|
+
version = version + 1
|
|
76
|
+
WHERE namespace = ${ctx.config.namespace} AND id = ${String(id)}
|
|
77
|
+
`;
|
|
78
|
+
}
|
|
79
|
+
await recordPostgresEvent(tx, ctx, {
|
|
80
|
+
queue: job.queue,
|
|
81
|
+
type: 'completed',
|
|
82
|
+
jobId: id,
|
|
83
|
+
occurredAt: now,
|
|
84
|
+
job,
|
|
85
|
+
state: 'completed',
|
|
86
|
+
result,
|
|
87
|
+
removed,
|
|
88
|
+
dlqEntry: null,
|
|
89
|
+
dlqRetryState: null,
|
|
90
|
+
});
|
|
91
|
+
await dependencyCompletion.promote(now);
|
|
92
|
+
const shouldRepeat = job.repeat !== null &&
|
|
93
|
+
(job.repeat.limit === undefined || job.repeat.count < job.repeat.limit);
|
|
94
|
+
const successorInput = shouldRepeat ? buildRepeatSuccessor(job, now) : null;
|
|
95
|
+
if (successorInput) {
|
|
96
|
+
if (!(await tryLockPostgresRepeatQueues(tx, ctx, [job.queue]))) {
|
|
97
|
+
throw new Error(`Queue ${job.queue} is being obliterated; retry completion`);
|
|
98
|
+
}
|
|
99
|
+
const successor = createJob(generateJobId(), job.queue, successorInput, now);
|
|
100
|
+
const admitted = await admitPostgresJob(tx, ctx, successor, {
|
|
101
|
+
linkParent: false,
|
|
102
|
+
queueLifecycleLocksHeld: true,
|
|
103
|
+
});
|
|
104
|
+
await tx `
|
|
105
|
+
INSERT INTO bunqueue_repeat_links (namespace, original_id, successor_id)
|
|
106
|
+
VALUES (${ctx.config.namespace}, ${String(job.id)}, ${String(admitted.job.id)})
|
|
107
|
+
ON CONFLICT (namespace, original_id) DO UPDATE SET successor_id = excluded.successor_id
|
|
108
|
+
`;
|
|
109
|
+
}
|
|
110
|
+
return { applied: true, alreadyFinalized: false, job, state: 'completed' };
|
|
111
|
+
});
|
|
112
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type JobId } from '../../../domain/types/job';
|
|
2
|
+
import type { PostgresContext } from './context';
|
|
3
|
+
import type { PostgresReadSql } from './context';
|
|
4
|
+
import type { PostgresCompletionResult } from './types';
|
|
5
|
+
export declare function getPostgresCompletionResult(ctx: PostgresContext, id: JobId): Promise<{
|
|
6
|
+
found: boolean;
|
|
7
|
+
result: unknown;
|
|
8
|
+
}>;
|
|
9
|
+
export declare function loadPostgresCompletionResults(ctx: PostgresContext, queue?: string, sql?: PostgresReadSql): Promise<PostgresCompletionResult[]>;
|
|
10
|
+
export declare function getPostgresChildrenValues(ctx: PostgresContext, parentId: JobId): Promise<Record<string, unknown>>;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { jobId } from '../../../domain/types/job';
|
|
2
|
+
import { decodePostgresValue } from './codec';
|
|
3
|
+
const LIVE_CONSUMER_STATES = [
|
|
4
|
+
'waiting',
|
|
5
|
+
'prioritized',
|
|
6
|
+
'delayed',
|
|
7
|
+
'waiting-children',
|
|
8
|
+
'active',
|
|
9
|
+
];
|
|
10
|
+
export async function getPostgresCompletionResult(ctx, id) {
|
|
11
|
+
const rows = await ctx.sql `
|
|
12
|
+
SELECT result FROM bunqueue_completions
|
|
13
|
+
WHERE namespace = ${ctx.config.namespace} AND job_id = ${String(id)}
|
|
14
|
+
`;
|
|
15
|
+
if (!rows[0])
|
|
16
|
+
return { found: false, result: undefined };
|
|
17
|
+
return {
|
|
18
|
+
found: true,
|
|
19
|
+
result: decodePostgresValue(rows[0].result, null, `postgresCompletion:${String(id)}`),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
async function loadCompletionRows(ctx, queue, sql = ctx.sql) {
|
|
23
|
+
const queueFilter = queue === undefined ? null : queue;
|
|
24
|
+
return await sql `
|
|
25
|
+
WITH pinned AS MATERIALIZED (
|
|
26
|
+
SELECT DISTINCT dependency.dependency_id AS job_id
|
|
27
|
+
FROM bunqueue_dependencies AS dependency
|
|
28
|
+
JOIN bunqueue_jobs AS consumer
|
|
29
|
+
ON consumer.namespace = dependency.namespace AND consumer.id = dependency.job_id
|
|
30
|
+
WHERE dependency.namespace = ${ctx.config.namespace}
|
|
31
|
+
AND consumer.state = ANY(${ctx.sql.array([...LIVE_CONSUMER_STATES], 'TEXT')})
|
|
32
|
+
), recent AS MATERIALIZED (
|
|
33
|
+
SELECT completion.job_id, completion.queue, completion.result,
|
|
34
|
+
FALSE AS pinned, completion.completed_at
|
|
35
|
+
FROM bunqueue_completions AS completion
|
|
36
|
+
WHERE completion.namespace = ${ctx.config.namespace}
|
|
37
|
+
AND (${queueFilter}::text IS NULL OR completion.queue = ${queueFilter})
|
|
38
|
+
AND NOT EXISTS (
|
|
39
|
+
SELECT 1 FROM pinned WHERE pinned.job_id = completion.job_id
|
|
40
|
+
)
|
|
41
|
+
ORDER BY completion.completed_at DESC, completion.job_id DESC
|
|
42
|
+
LIMIT ${ctx.config.maxJobResults}
|
|
43
|
+
)
|
|
44
|
+
SELECT completion.job_id, completion.queue, completion.result, TRUE AS pinned
|
|
45
|
+
FROM bunqueue_completions AS completion
|
|
46
|
+
JOIN pinned ON pinned.job_id = completion.job_id
|
|
47
|
+
WHERE completion.namespace = ${ctx.config.namespace}
|
|
48
|
+
AND (${queueFilter}::text IS NULL OR completion.queue = ${queueFilter})
|
|
49
|
+
UNION ALL
|
|
50
|
+
SELECT recent.job_id, recent.queue, recent.result, recent.pinned
|
|
51
|
+
FROM recent
|
|
52
|
+
ORDER BY job_id
|
|
53
|
+
`;
|
|
54
|
+
}
|
|
55
|
+
export async function loadPostgresCompletionResults(ctx, queue, sql = ctx.sql) {
|
|
56
|
+
const rows = await loadCompletionRows(ctx, queue, sql);
|
|
57
|
+
return rows.map((row) => ({
|
|
58
|
+
jobId: jobId(row.job_id),
|
|
59
|
+
queue: row.queue,
|
|
60
|
+
result: decodePostgresValue(row.result, null, `postgresCompletion:${row.job_id}`),
|
|
61
|
+
pinned: row.pinned,
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
export async function getPostgresChildrenValues(ctx, parentId) {
|
|
65
|
+
const parents = await ctx.sql `
|
|
66
|
+
SELECT payload FROM bunqueue_jobs
|
|
67
|
+
WHERE namespace = ${ctx.config.namespace} AND id = ${String(parentId)}
|
|
68
|
+
`;
|
|
69
|
+
if (!parents[0])
|
|
70
|
+
return {};
|
|
71
|
+
const parent = decodePostgresValue(parents[0].payload, null, `postgresChildrenParent:${String(parentId)}`);
|
|
72
|
+
const childIds = [
|
|
73
|
+
...new Set([...(parent?.childrenIds ?? []), ...(parent?.dependsOn ?? [])].map(String)),
|
|
74
|
+
];
|
|
75
|
+
if (childIds.length === 0)
|
|
76
|
+
return {};
|
|
77
|
+
const rows = await ctx.sql `
|
|
78
|
+
SELECT job_id, queue, result FROM bunqueue_completions
|
|
79
|
+
WHERE namespace = ${ctx.config.namespace}
|
|
80
|
+
AND job_id = ANY(${ctx.sql.array(childIds, 'TEXT')})
|
|
81
|
+
ORDER BY job_id
|
|
82
|
+
`;
|
|
83
|
+
return Object.fromEntries(rows.map((row) => [
|
|
84
|
+
`${row.queue}:${row.job_id}`,
|
|
85
|
+
decodePostgresValue(row.result, null, `postgresChildResult:${row.job_id}`),
|
|
86
|
+
]));
|
|
87
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { SQL } from 'bun';
|
|
2
|
+
export function createPostgresConnection(config) {
|
|
3
|
+
return new SQL(config.url, {
|
|
4
|
+
max: config.poolSize,
|
|
5
|
+
connectionTimeout: 10,
|
|
6
|
+
idleTimeout: 30,
|
|
7
|
+
maxLifetime: 3600,
|
|
8
|
+
connection: {
|
|
9
|
+
application_name: `bunqueue:${config.brokerId}`.slice(0, 63),
|
|
10
|
+
statement_timeout: config.statementTimeoutMs,
|
|
11
|
+
lock_timeout: config.lockTimeoutMs,
|
|
12
|
+
idle_in_transaction_session_timeout: config.idleTransactionTimeoutMs,
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { SQL, TransactionSQL } from 'bun';
|
|
2
|
+
import type { DlqEntry, DlqRetryState } from '../../../domain/types/dlq';
|
|
3
|
+
import type { Job, JobId } from '../../../domain/types/job';
|
|
4
|
+
import type { PostgresJobState, ResolvedPostgresStorageConfig } from './types';
|
|
5
|
+
export type PostgresReadSql = SQL | TransactionSQL;
|
|
6
|
+
export interface PostgresContext {
|
|
7
|
+
readonly sql: SQL;
|
|
8
|
+
readonly config: ResolvedPostgresStorageConfig;
|
|
9
|
+
readonly postCommitMaintenance?: (subsystem: string, operation: () => Promise<unknown>) => Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
/** Run work that follows an already committed transition without changing its outcome. */
|
|
12
|
+
export declare function runPostgresPostCommitMaintenance(ctx: PostgresContext, subsystem: string, operation: () => Promise<unknown>): Promise<void>;
|
|
13
|
+
export declare function databaseNowSql(): string;
|
|
14
|
+
export declare function databaseNow(tx: SQL | TransactionSQL): Promise<number>;
|
|
15
|
+
export interface RecordPostgresEventInput {
|
|
16
|
+
readonly queue: string;
|
|
17
|
+
readonly type: string;
|
|
18
|
+
readonly jobId: JobId;
|
|
19
|
+
readonly occurredAt: number;
|
|
20
|
+
readonly job?: Job;
|
|
21
|
+
readonly state?: PostgresJobState;
|
|
22
|
+
readonly result?: unknown;
|
|
23
|
+
readonly error?: string;
|
|
24
|
+
readonly removed?: boolean;
|
|
25
|
+
readonly dlqEntry?: DlqEntry | null;
|
|
26
|
+
readonly dlqRetryState?: DlqRetryState | null;
|
|
27
|
+
}
|
|
28
|
+
export declare function recordPostgresEvent(tx: TransactionSQL, ctx: PostgresContext, input: RecordPostgresEventInput): Promise<number>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { eventPayload } from './codec';
|
|
2
|
+
import { recordPostgresEventPruneWatermarks, summarizePostgresPrunedEvents, } from './eventPruneWatermarks';
|
|
3
|
+
import { prunePostgresQueueEvents, tryLockPostgresEventRetention } from './eventRetention';
|
|
4
|
+
import { POSTGRES_EVENT_CHANNEL } from './schema';
|
|
5
|
+
import { recordPostgresMetricAdditions } from './metricWrites';
|
|
6
|
+
/** Run work that follows an already committed transition without changing its outcome. */
|
|
7
|
+
export async function runPostgresPostCommitMaintenance(ctx, subsystem, operation) {
|
|
8
|
+
if (ctx.postCommitMaintenance) {
|
|
9
|
+
await ctx.postCommitMaintenance(subsystem, operation);
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
await operation();
|
|
13
|
+
}
|
|
14
|
+
export function databaseNowSql() {
|
|
15
|
+
return 'floor(extract(epoch from clock_timestamp()) * 1000)::bigint';
|
|
16
|
+
}
|
|
17
|
+
export async function databaseNow(tx) {
|
|
18
|
+
const [row] = await tx `
|
|
19
|
+
SELECT floor(extract(epoch from clock_timestamp()) * 1000)::bigint AS now
|
|
20
|
+
`;
|
|
21
|
+
return Number(row.now);
|
|
22
|
+
}
|
|
23
|
+
export async function recordPostgresEvent(tx, ctx, input) {
|
|
24
|
+
const payload = eventPayload({
|
|
25
|
+
...(input.job && { job: input.job }),
|
|
26
|
+
...(input.state && { state: input.state }),
|
|
27
|
+
...(Object.hasOwn(input, 'result') && { result: input.result }),
|
|
28
|
+
...(input.error !== undefined && { error: input.error }),
|
|
29
|
+
...(input.removed !== undefined && { removed: input.removed }),
|
|
30
|
+
...(Object.hasOwn(input, 'dlqEntry') && { dlqEntry: input.dlqEntry }),
|
|
31
|
+
...(Object.hasOwn(input, 'dlqRetryState') && { dlqRetryState: input.dlqRetryState }),
|
|
32
|
+
});
|
|
33
|
+
const [row] = await tx `
|
|
34
|
+
INSERT INTO bunqueue_events
|
|
35
|
+
(namespace, queue, event_type, job_id, occurred_at, payload)
|
|
36
|
+
VALUES
|
|
37
|
+
(${ctx.config.namespace}, ${input.queue}, ${input.type}, ${String(input.jobId)},
|
|
38
|
+
${input.occurredAt}, ${payload})
|
|
39
|
+
RETURNING id
|
|
40
|
+
`;
|
|
41
|
+
const eventId = Number(row.id);
|
|
42
|
+
const eventLimit = ctx.config.maxQueueEvents;
|
|
43
|
+
const retentionLockAcquired = await tryLockPostgresEventRetention(tx, ctx, input.queue);
|
|
44
|
+
const pruned = retentionLockAcquired
|
|
45
|
+
? await prunePostgresQueueEvents(tx, ctx, input.queue, eventLimit)
|
|
46
|
+
: [];
|
|
47
|
+
const prune = summarizePostgresPrunedEvents(pruned);
|
|
48
|
+
const { prunedThrough } = prune;
|
|
49
|
+
if (prunedThrough > 0) {
|
|
50
|
+
await recordPostgresEventPruneWatermarks(tx, ctx, [
|
|
51
|
+
{ queue: input.queue, sourceEventId: eventId, ...prune },
|
|
52
|
+
]);
|
|
53
|
+
}
|
|
54
|
+
const metricType = input.type === 'completed'
|
|
55
|
+
? 'completed'
|
|
56
|
+
: input.type === 'failed' && input.state === 'failed'
|
|
57
|
+
? 'failed'
|
|
58
|
+
: null;
|
|
59
|
+
if (metricType) {
|
|
60
|
+
await recordPostgresMetricAdditions(tx, ctx, metricType, [{ queue: input.queue, count: 1 }], input.occurredAt);
|
|
61
|
+
}
|
|
62
|
+
await tx.notify(POSTGRES_EVENT_CHANNEL, JSON.stringify({
|
|
63
|
+
namespace: ctx.config.namespace,
|
|
64
|
+
queue: input.queue,
|
|
65
|
+
brokerId: ctx.config.brokerId,
|
|
66
|
+
eventId,
|
|
67
|
+
eventStartId: eventId,
|
|
68
|
+
eventEndId: eventId,
|
|
69
|
+
invalidateQueue: input.type.startsWith('queue-'),
|
|
70
|
+
...(prunedThrough > 0 && { prunedThrough }),
|
|
71
|
+
...(!retentionLockAcquired && { retentionRequested: true }),
|
|
72
|
+
}));
|
|
73
|
+
return eventId;
|
|
74
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type DlqConfig } from '../../../domain/types/dlq';
|
|
2
|
+
import { type StallConfig } from '../../../domain/types/stall';
|
|
3
|
+
import { type PostgresContext, type PostgresReadSql } from './context';
|
|
4
|
+
import type { PostgresQueueState } from './types';
|
|
5
|
+
export interface PostgresQueueStateRow {
|
|
6
|
+
queue: string;
|
|
7
|
+
paused: boolean;
|
|
8
|
+
rate_limit: number | null;
|
|
9
|
+
rate_duration_ms: number | string | bigint | null;
|
|
10
|
+
rate_window_started_at: number | string | bigint | null;
|
|
11
|
+
rate_expires_at: number | string | bigint | null;
|
|
12
|
+
rate_count: number;
|
|
13
|
+
concurrency_limit: number | null;
|
|
14
|
+
stall_config: Uint8Array | null;
|
|
15
|
+
dlq_config: Uint8Array | null;
|
|
16
|
+
}
|
|
17
|
+
export declare function decodePostgresQueueState(queue: string, row?: PostgresQueueStateRow): PostgresQueueState;
|
|
18
|
+
export declare function getPostgresQueueState(ctx: PostgresContext, queue: string, sql?: PostgresReadSql): Promise<PostgresQueueState>;
|
|
19
|
+
export declare function setPostgresPaused(ctx: PostgresContext, queue: string, paused: boolean): Promise<void>;
|
|
20
|
+
export declare function setPostgresRateLimit(ctx: PostgresContext, queue: string, limit: number | null, durationMs: number | null, ttlMs?: number | null): Promise<void>;
|
|
21
|
+
export declare function setPostgresConcurrency(ctx: PostgresContext, queue: string, limit: number | null): Promise<void>;
|
|
22
|
+
export declare function setPostgresStallConfig(ctx: PostgresContext, queue: string, config: StallConfig): Promise<void>;
|
|
23
|
+
export declare function setPostgresDlqConfig(ctx: PostgresContext, queue: string, config: DlqConfig): Promise<void>;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { DEFAULT_DLQ_CONFIG } from '../../../domain/types/dlq';
|
|
2
|
+
import { jobId } from '../../../domain/types/job';
|
|
3
|
+
import { DEFAULT_STALL_CONFIG } from '../../../domain/types/stall';
|
|
4
|
+
import { decodePostgresValue, encodePostgresValue } from './codec';
|
|
5
|
+
import { enforcePostgresDlqLimit } from './dlqLifecycle';
|
|
6
|
+
import { databaseNow, recordPostgresEvent, } from './context';
|
|
7
|
+
import { normalizePostgresRateLimit } from './rateLimit';
|
|
8
|
+
function optionalNumber(value) {
|
|
9
|
+
return value === null || value === undefined ? null : Number(value);
|
|
10
|
+
}
|
|
11
|
+
export function decodePostgresQueueState(queue, row) {
|
|
12
|
+
return {
|
|
13
|
+
queue,
|
|
14
|
+
paused: row?.paused ?? false,
|
|
15
|
+
rateLimit: row?.rate_limit ?? null,
|
|
16
|
+
rateDurationMs: optionalNumber(row?.rate_duration_ms),
|
|
17
|
+
rateWindowStartedAt: optionalNumber(row?.rate_window_started_at),
|
|
18
|
+
rateExpiresAt: optionalNumber(row?.rate_expires_at),
|
|
19
|
+
rateCount: row?.rate_count ?? 0,
|
|
20
|
+
concurrencyLimit: row?.concurrency_limit ?? null,
|
|
21
|
+
stallConfig: decodePostgresValue(row?.stall_config ?? null, DEFAULT_STALL_CONFIG, 'stallConfig'),
|
|
22
|
+
dlqConfig: decodePostgresValue(row?.dlq_config ?? null, DEFAULT_DLQ_CONFIG, 'dlqConfig'),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
async function recordQueueInvalidation(tx, ctx, queue, type, occurredAt) {
|
|
26
|
+
await recordPostgresEvent(tx, ctx, {
|
|
27
|
+
queue,
|
|
28
|
+
type,
|
|
29
|
+
jobId: jobId(`__queue__:${queue}`),
|
|
30
|
+
occurredAt: occurredAt ?? (await databaseNow(tx)),
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
export async function getPostgresQueueState(ctx, queue, sql = ctx.sql) {
|
|
34
|
+
const rows = await sql `
|
|
35
|
+
SELECT queue, paused, rate_limit, rate_duration_ms, rate_window_started_at, rate_expires_at,
|
|
36
|
+
rate_count, concurrency_limit, stall_config, dlq_config
|
|
37
|
+
FROM bunqueue_queue_state
|
|
38
|
+
WHERE namespace = ${ctx.config.namespace} AND queue = ${queue}
|
|
39
|
+
`;
|
|
40
|
+
return decodePostgresQueueState(queue, rows[0]);
|
|
41
|
+
}
|
|
42
|
+
export async function setPostgresPaused(ctx, queue, paused) {
|
|
43
|
+
await ctx.sql.begin(async (tx) => {
|
|
44
|
+
await tx `
|
|
45
|
+
INSERT INTO bunqueue_queue_state (namespace, queue, paused)
|
|
46
|
+
VALUES (${ctx.config.namespace}, ${queue}, ${paused})
|
|
47
|
+
ON CONFLICT (namespace, queue) DO UPDATE SET paused = excluded.paused
|
|
48
|
+
`;
|
|
49
|
+
await recordQueueInvalidation(tx, ctx, queue, paused ? 'queue-paused' : 'queue-resumed');
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
export async function setPostgresRateLimit(ctx, queue, limit, durationMs, ttlMs) {
|
|
53
|
+
const normalized = normalizePostgresRateLimit(durationMs, ttlMs);
|
|
54
|
+
await ctx.sql.begin(async (tx) => {
|
|
55
|
+
const now = await databaseNow(tx);
|
|
56
|
+
const rateExpiresAt = limit !== null && normalized.ttlMs !== null ? now + normalized.ttlMs : null;
|
|
57
|
+
await tx `
|
|
58
|
+
INSERT INTO bunqueue_queue_state
|
|
59
|
+
(namespace, queue, rate_limit, rate_duration_ms, rate_window_started_at,
|
|
60
|
+
rate_expires_at, rate_count)
|
|
61
|
+
VALUES
|
|
62
|
+
(${ctx.config.namespace}, ${queue}, ${limit}, ${normalized.durationMs}, ${now},
|
|
63
|
+
${rateExpiresAt}, 0)
|
|
64
|
+
ON CONFLICT (namespace, queue) DO UPDATE SET
|
|
65
|
+
rate_limit = excluded.rate_limit,
|
|
66
|
+
rate_duration_ms = excluded.rate_duration_ms,
|
|
67
|
+
rate_window_started_at = excluded.rate_window_started_at,
|
|
68
|
+
rate_expires_at = excluded.rate_expires_at,
|
|
69
|
+
rate_count = 0
|
|
70
|
+
`;
|
|
71
|
+
await recordQueueInvalidation(tx, ctx, queue, 'queue-rate-limit-changed', now);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
export async function setPostgresConcurrency(ctx, queue, limit) {
|
|
75
|
+
await ctx.sql.begin(async (tx) => {
|
|
76
|
+
await tx `
|
|
77
|
+
INSERT INTO bunqueue_queue_state (namespace, queue, concurrency_limit)
|
|
78
|
+
VALUES (${ctx.config.namespace}, ${queue}, ${limit})
|
|
79
|
+
ON CONFLICT (namespace, queue) DO UPDATE SET concurrency_limit = excluded.concurrency_limit
|
|
80
|
+
`;
|
|
81
|
+
await recordQueueInvalidation(tx, ctx, queue, 'queue-concurrency-changed');
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
export async function setPostgresStallConfig(ctx, queue, config) {
|
|
85
|
+
await ctx.sql.begin(async (tx) => {
|
|
86
|
+
await tx `
|
|
87
|
+
INSERT INTO bunqueue_queue_state (namespace, queue, stall_config)
|
|
88
|
+
VALUES (${ctx.config.namespace}, ${queue}, ${encodePostgresValue(config)})
|
|
89
|
+
ON CONFLICT (namespace, queue) DO UPDATE SET stall_config = excluded.stall_config
|
|
90
|
+
`;
|
|
91
|
+
await recordQueueInvalidation(tx, ctx, queue, 'queue-stall-config-changed');
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
export async function setPostgresDlqConfig(ctx, queue, config) {
|
|
95
|
+
await ctx.sql.begin(async (tx) => {
|
|
96
|
+
const now = await databaseNow(tx);
|
|
97
|
+
await tx `
|
|
98
|
+
INSERT INTO bunqueue_queue_state (namespace, queue, dlq_config)
|
|
99
|
+
VALUES (${ctx.config.namespace}, ${queue}, ${encodePostgresValue(config)})
|
|
100
|
+
ON CONFLICT (namespace, queue) DO UPDATE SET dlq_config = excluded.dlq_config
|
|
101
|
+
`;
|
|
102
|
+
await recordQueueInvalidation(tx, ctx, queue, 'queue-dlq-config-changed', now);
|
|
103
|
+
});
|
|
104
|
+
await enforcePostgresDlqLimit(ctx, queue, config.maxEntries);
|
|
105
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type CronJob, type CronJobInput } from '../../../domain/types/cron';
|
|
2
|
+
import { type PostgresContext, type PostgresReadSql } from './context';
|
|
3
|
+
export interface PostgresCronRow {
|
|
4
|
+
name: string;
|
|
5
|
+
payload: Uint8Array;
|
|
6
|
+
next_run: number | string | bigint;
|
|
7
|
+
executions: number;
|
|
8
|
+
max_limit: number | null;
|
|
9
|
+
}
|
|
10
|
+
export declare function decodePostgresCron(row: PostgresCronRow): CronJob;
|
|
11
|
+
export declare function upsertPostgresCron(ctx: PostgresContext, input: CronJobInput): Promise<CronJob>;
|
|
12
|
+
export declare function getPostgresCron(ctx: PostgresContext, name: string): Promise<CronJob | undefined>;
|
|
13
|
+
export declare function listPostgresCrons(ctx: PostgresContext, sql?: PostgresReadSql): Promise<CronJob[]>;
|
|
14
|
+
export declare function removePostgresCron(ctx: PostgresContext, name: string): Promise<boolean>;
|
|
15
|
+
/** Recalculate missed rows only on the oldest live broker for this namespace. */
|
|
16
|
+
export declare function reconcilePostgresCronsOnStartup(ctx: PostgresContext): Promise<number>;
|
|
17
|
+
/** Advance and enqueue each due cron once under PostgreSQL row locks. */
|
|
18
|
+
export declare function processPostgresCrons(ctx: PostgresContext, limit?: number): Promise<number>;
|