@shivaedev/jobs 0.30.0 → 0.32.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/CHANGELOG.md +50 -0
- package/README.md +88 -24
- package/dist/display.d.ts +14 -0
- package/dist/display.d.ts.map +1 -0
- package/dist/display.js +2 -0
- package/dist/display.js.map +1 -0
- package/dist/server/ClientDatabase.d.ts +21 -0
- package/dist/server/ClientDatabase.d.ts.map +1 -0
- package/dist/server/ClientDatabase.js +2 -0
- package/dist/server/ClientDatabase.js.map +1 -0
- package/dist/server/PgBoss.d.ts +2 -2
- package/dist/server/PgBoss.d.ts.map +1 -1
- package/dist/server/adapters/batchClockOffset.d.ts +2 -2
- package/dist/server/adapters/batchClockOffset.d.ts.map +1 -1
- package/dist/server/adapters/batchClockOffset.js +5 -4
- package/dist/server/adapters/batchClockOffset.js.map +1 -1
- package/dist/server/adapters/batchHandler.d.ts +5 -0
- package/dist/server/adapters/batchHandler.d.ts.map +1 -0
- package/dist/server/{internal → adapters}/batchHandler.js +6 -6
- package/dist/server/adapters/batchHandler.js.map +1 -0
- package/dist/server/adapters/clientCache.d.ts +10 -0
- package/dist/server/adapters/clientCache.d.ts.map +1 -0
- package/dist/server/{internal → adapters}/clientCache.js +5 -19
- package/dist/server/adapters/clientCache.js.map +1 -0
- package/dist/server/adapters/clientErrorLogger.js +1 -1
- package/dist/server/adapters/clientErrorLogger.js.map +1 -1
- package/dist/server/adapters/defaultClientFactory.d.ts +4 -0
- package/dist/server/adapters/defaultClientFactory.d.ts.map +1 -0
- package/dist/server/adapters/defaultClientFactory.js.map +1 -0
- package/dist/server/adapters/deferralCount.d.ts +3 -3
- package/dist/server/adapters/deferralCount.d.ts.map +1 -1
- package/dist/server/adapters/deferralCount.js +2 -2
- package/dist/server/adapters/deferralCount.js.map +1 -1
- package/dist/server/adapters/expireAttempt.d.ts +4 -0
- package/dist/server/adapters/expireAttempt.d.ts.map +1 -0
- package/dist/server/{internal → adapters}/expireAttempt.js +1 -1
- package/dist/server/{internal → adapters}/expireAttempt.js.map +1 -1
- package/dist/server/adapters/inspection.d.ts +5 -0
- package/dist/server/adapters/inspection.d.ts.map +1 -0
- package/dist/server/adapters/inspection.js +25 -0
- package/dist/server/adapters/inspection.js.map +1 -0
- package/dist/server/adapters/inspectionChanges.d.ts +7 -0
- package/dist/server/adapters/inspectionChanges.d.ts.map +1 -0
- package/dist/server/adapters/inspectionChanges.js +23 -0
- package/dist/server/adapters/inspectionChanges.js.map +1 -0
- package/dist/server/adapters/inspectionDeferrals.d.ts +10 -0
- package/dist/server/adapters/inspectionDeferrals.d.ts.map +1 -0
- package/dist/server/adapters/inspectionDeferrals.js +13 -0
- package/dist/server/adapters/inspectionDeferrals.js.map +1 -0
- package/dist/server/adapters/inspectionJobs.d.ts +50 -0
- package/dist/server/adapters/inspectionJobs.d.ts.map +1 -0
- package/dist/server/adapters/inspectionJobs.js +21 -0
- package/dist/server/adapters/inspectionJobs.js.map +1 -0
- package/dist/server/adapters/inspectionOperation.d.ts +3 -0
- package/dist/server/adapters/inspectionOperation.d.ts.map +1 -0
- package/dist/server/adapters/inspectionOperation.js +6 -0
- package/dist/server/adapters/inspectionOperation.js.map +1 -0
- package/dist/server/adapters/inspectionPlan.d.ts +3 -0
- package/dist/server/adapters/inspectionPlan.d.ts.map +1 -0
- package/dist/server/adapters/inspectionPlan.js +20 -0
- package/dist/server/adapters/inspectionPlan.js.map +1 -0
- package/dist/server/adapters/inspectionReads.d.ts +59 -0
- package/dist/server/adapters/inspectionReads.d.ts.map +1 -0
- package/dist/server/adapters/inspectionReads.js +44 -0
- package/dist/server/adapters/inspectionReads.js.map +1 -0
- package/dist/server/adapters/inspectionSnapshot.d.ts +6 -0
- package/dist/server/adapters/inspectionSnapshot.d.ts.map +1 -0
- package/dist/server/{internal/testingSnapshot.js → adapters/inspectionSnapshot.js} +10 -8
- package/dist/server/adapters/inspectionSnapshot.js.map +1 -0
- package/dist/server/adapters/installSchema.d.ts +1 -1
- package/dist/server/adapters/installSchema.d.ts.map +1 -1
- package/dist/server/adapters/installSchema.js +1 -1
- package/dist/server/adapters/installSchema.js.map +1 -1
- package/dist/server/adapters/jobEngine.d.ts +5 -0
- package/dist/server/adapters/jobEngine.d.ts.map +1 -0
- package/dist/server/adapters/jobEngine.js +46 -0
- package/dist/server/adapters/jobEngine.js.map +1 -0
- package/dist/server/adapters/lifecycle.d.ts +11 -0
- package/dist/server/adapters/lifecycle.d.ts.map +1 -0
- package/dist/server/adapters/lifecycle.js +48 -0
- package/dist/server/adapters/lifecycle.js.map +1 -0
- package/dist/server/adapters/listJobs.d.ts +5 -0
- package/dist/server/adapters/listJobs.d.ts.map +1 -0
- package/dist/server/adapters/listJobs.js +37 -0
- package/dist/server/adapters/listJobs.js.map +1 -0
- package/dist/server/adapters/payloadIdentity.d.ts +3 -0
- package/dist/server/adapters/payloadIdentity.d.ts.map +1 -0
- package/dist/server/adapters/payloadIdentity.js +14 -0
- package/dist/server/adapters/payloadIdentity.js.map +1 -0
- package/dist/server/adapters/queueAdministration.d.ts +4 -0
- package/dist/server/adapters/queueAdministration.d.ts.map +1 -0
- package/dist/server/adapters/queueAdministration.js +42 -0
- package/dist/server/adapters/queueAdministration.js.map +1 -0
- package/dist/server/{internal/testingSignal.d.ts → adapters/queueSignal.d.ts} +2 -2
- package/dist/server/adapters/queueSignal.d.ts.map +1 -0
- package/dist/server/{internal/testingSignal.js → adapters/queueSignal.js} +2 -2
- package/dist/server/adapters/queueSignal.js.map +1 -0
- package/dist/server/adapters/registerWorker.d.ts +5 -3
- package/dist/server/adapters/registerWorker.d.ts.map +1 -1
- package/dist/server/adapters/registerWorker.js +9 -6
- package/dist/server/adapters/registerWorker.js.map +1 -1
- package/dist/server/adapters/retireJobs.d.ts +3 -3
- package/dist/server/adapters/retireJobs.d.ts.map +1 -1
- package/dist/server/adapters/retireJobs.js +3 -3
- package/dist/server/adapters/retireJobs.js.map +1 -1
- package/dist/server/adapters/schemaIndexBuilds.d.ts +2 -2
- package/dist/server/adapters/schemaIndexBuilds.d.ts.map +1 -1
- package/dist/server/adapters/schemaIndexBuilds.js.map +1 -1
- package/dist/server/adapters/settleDeferral.d.ts +7 -0
- package/dist/server/adapters/settleDeferral.d.ts.map +1 -0
- package/dist/server/{internal → adapters}/settleDeferral.js +2 -2
- package/dist/server/adapters/settleDeferral.js.map +1 -0
- package/dist/server/adapters/testingClient.d.ts +13 -0
- package/dist/server/adapters/testingClient.d.ts.map +1 -0
- package/dist/server/{internal → adapters}/testingClient.js +27 -48
- package/dist/server/adapters/testingClient.js.map +1 -0
- package/dist/server/adapters/testingController.d.ts +79 -0
- package/dist/server/adapters/testingController.d.ts.map +1 -0
- package/dist/server/adapters/testingController.js +108 -0
- package/dist/server/adapters/testingController.js.map +1 -0
- package/dist/server/adapters/testingDueNow.d.ts +3 -3
- package/dist/server/adapters/testingDueNow.d.ts.map +1 -1
- package/dist/server/adapters/testingDueNow.js +2 -2
- package/dist/server/adapters/testingDueNow.js.map +1 -1
- package/dist/server/adapters/testingEngine.d.ts +5 -0
- package/dist/server/adapters/testingEngine.d.ts.map +1 -0
- package/dist/server/adapters/testingEngine.js +12 -0
- package/dist/server/adapters/testingEngine.js.map +1 -0
- package/dist/server/adapters/testingExpirations.d.ts +6 -4
- package/dist/server/adapters/testingExpirations.d.ts.map +1 -1
- package/dist/server/adapters/testingExpirations.js.map +1 -1
- package/dist/server/adapters/testingInspectionClient.d.ts +5 -0
- package/dist/server/adapters/testingInspectionClient.d.ts.map +1 -0
- package/dist/server/adapters/testingInspectionClient.js +52 -0
- package/dist/server/adapters/testingInspectionClient.js.map +1 -0
- package/dist/server/adapters/transactionDb.d.ts +2 -2
- package/dist/server/adapters/transactionDb.d.ts.map +1 -1
- package/dist/server/adapters/transactionDb.js.map +1 -1
- package/dist/server/client.d.ts +95 -18
- package/dist/server/client.d.ts.map +1 -1
- package/dist/server/clientOptions.d.ts +74 -0
- package/dist/server/clientOptions.d.ts.map +1 -0
- package/dist/server/clientOptions.js +2 -0
- package/dist/server/clientOptions.js.map +1 -0
- package/dist/server/defineSchedule.d.ts +1 -1
- package/dist/server/defineSchedule.d.ts.map +1 -1
- package/dist/server/defineSchedule.js +2 -1
- package/dist/server/defineSchedule.js.map +1 -1
- package/dist/server/definition.d.ts +29 -26
- package/dist/server/definition.d.ts.map +1 -1
- package/dist/server/definition.js +5 -2
- package/dist/server/definition.js.map +1 -1
- package/dist/server/engineClient.d.ts +21 -0
- package/dist/server/engineClient.d.ts.map +1 -0
- package/dist/server/engineClient.js +2 -0
- package/dist/server/engineClient.js.map +1 -0
- package/dist/server/enqueueOptions.d.ts +28 -0
- package/dist/server/enqueueOptions.d.ts.map +1 -0
- package/dist/server/enqueueOptions.js +2 -0
- package/dist/server/enqueueOptions.js.map +1 -0
- package/dist/server/error.d.ts +11 -1
- package/dist/server/error.d.ts.map +1 -1
- package/dist/server/error.js +8 -1
- package/dist/server/error.js.map +1 -1
- package/dist/server/health.d.ts +2 -2
- package/dist/server/health.d.ts.map +1 -1
- package/dist/server/inspection.d.ts +102 -0
- package/dist/server/inspection.d.ts.map +1 -0
- package/dist/server/inspection.js +30 -0
- package/dist/server/inspection.js.map +1 -0
- package/dist/server/internal/acquireClient.d.ts +11 -0
- package/dist/server/internal/acquireClient.d.ts.map +1 -0
- package/dist/server/internal/acquireClient.js +21 -0
- package/dist/server/internal/acquireClient.js.map +1 -0
- package/dist/server/internal/adapters/testingFetches.d.ts +2 -2
- package/dist/server/internal/adapters/testingFetches.d.ts.map +1 -1
- package/dist/server/internal/adapters/testingFetches.js.map +1 -1
- package/dist/server/internal/clientErrors.d.ts +1 -1
- package/dist/server/internal/clientErrors.d.ts.map +1 -1
- package/dist/server/internal/countsFor.d.ts +3 -3
- package/dist/server/internal/countsFor.d.ts.map +1 -1
- package/dist/server/internal/countsFor.js +2 -2
- package/dist/server/internal/countsFor.js.map +1 -1
- package/dist/server/internal/deadLetterResolutionPlan.js +1 -1
- package/dist/server/internal/deadLetterResolutionPlan.js.map +1 -1
- package/dist/server/internal/deadlineOf.d.ts +2 -2
- package/dist/server/internal/deadlineOf.d.ts.map +1 -1
- package/dist/server/internal/deadlineOf.js.map +1 -1
- package/dist/server/internal/deferrableAttempt.d.ts +4 -5
- package/dist/server/internal/deferrableAttempt.d.ts.map +1 -1
- package/dist/server/internal/deferrableAttempt.js +5 -14
- package/dist/server/internal/deferrableAttempt.js.map +1 -1
- package/dist/server/internal/deferral.d.ts +2 -4
- package/dist/server/internal/deferral.d.ts.map +1 -1
- package/dist/server/internal/deferral.js +0 -1
- package/dist/server/internal/deferral.js.map +1 -1
- package/dist/server/internal/deferralStorePlan.js +2 -2
- package/dist/server/internal/deferralStorePlan.js.map +1 -1
- package/dist/server/internal/definitionOptions.d.ts +7 -7
- package/dist/server/internal/definitionOptions.d.ts.map +1 -1
- package/dist/server/internal/engine.d.ts +25 -0
- package/dist/server/internal/engine.d.ts.map +1 -0
- package/dist/server/internal/engine.js +6 -0
- package/dist/server/internal/engine.js.map +1 -0
- package/dist/server/internal/enqueueFor.d.ts +2 -2
- package/dist/server/internal/enqueueFor.d.ts.map +1 -1
- package/dist/server/internal/enqueueFor.js +14 -4
- package/dist/server/internal/enqueueFor.js.map +1 -1
- package/dist/server/internal/ensureQueue.d.ts +2 -3
- package/dist/server/internal/ensureQueue.d.ts.map +1 -1
- package/dist/server/internal/ensureQueue.js +2 -2
- package/dist/server/internal/ensureQueue.js.map +1 -1
- package/dist/server/internal/healthFor.d.ts +3 -3
- package/dist/server/internal/healthFor.d.ts.map +1 -1
- package/dist/server/internal/healthFor.js +2 -2
- package/dist/server/internal/healthFor.js.map +1 -1
- package/dist/server/internal/jobControl.d.ts +9 -4
- package/dist/server/internal/jobControl.d.ts.map +1 -1
- package/dist/server/internal/jobControl.js +13 -40
- package/dist/server/internal/jobControl.js.map +1 -1
- package/dist/server/internal/jobListings.d.ts +16 -0
- package/dist/server/internal/jobListings.d.ts.map +1 -0
- package/dist/server/internal/jobListings.js +52 -0
- package/dist/server/internal/jobListings.js.map +1 -0
- package/dist/server/internal/jobStorePlans.d.ts.map +1 -1
- package/dist/server/internal/jobStorePlans.js +4 -3
- package/dist/server/internal/jobStorePlans.js.map +1 -1
- package/dist/server/internal/lifecycle.d.ts +11 -7
- package/dist/server/internal/lifecycle.d.ts.map +1 -1
- package/dist/server/internal/lifecycle.js +2 -49
- package/dist/server/internal/lifecycle.js.map +1 -1
- package/dist/server/internal/makeService.d.ts +5 -3
- package/dist/server/internal/makeService.d.ts.map +1 -1
- package/dist/server/internal/makeService.js +18 -13
- package/dist/server/internal/makeService.js.map +1 -1
- package/dist/server/internal/register.d.ts +5 -5
- package/dist/server/internal/register.d.ts.map +1 -1
- package/dist/server/internal/register.js +5 -9
- package/dist/server/internal/register.js.map +1 -1
- package/dist/server/internal/registerReleasedJobs.d.ts +4 -4
- package/dist/server/internal/registerReleasedJobs.d.ts.map +1 -1
- package/dist/server/internal/registerReleasedJobs.js +2 -2
- package/dist/server/internal/registerReleasedJobs.js.map +1 -1
- package/dist/server/internal/retryWake.d.ts +1 -1
- package/dist/server/internal/retryWake.d.ts.map +1 -1
- package/dist/server/internal/retryWake.js +2 -2
- package/dist/server/internal/retryWake.js.map +1 -1
- package/dist/server/internal/runQueueWorker.d.ts +4 -4
- package/dist/server/internal/runQueueWorker.d.ts.map +1 -1
- package/dist/server/internal/runQueueWorker.js +5 -5
- package/dist/server/internal/runQueueWorker.js.map +1 -1
- package/dist/server/internal/storedRows.d.ts +2 -2
- package/dist/server/internal/storedRows.d.ts.map +1 -1
- package/dist/server/internal/storedRows.js +2 -2
- package/dist/server/internal/storedRows.js.map +1 -1
- package/dist/server/internal/testingIdle.d.ts +4 -3
- package/dist/server/internal/testingIdle.d.ts.map +1 -1
- package/dist/server/internal/testingIdle.js +5 -25
- package/dist/server/internal/testingIdle.js.map +1 -1
- package/dist/server/internal/testingOperation.d.ts +5 -0
- package/dist/server/internal/testingOperation.d.ts.map +1 -0
- package/dist/server/internal/testingOperation.js +12 -0
- package/dist/server/internal/testingOperation.js.map +1 -0
- package/dist/server/internal/testingSchedules.d.ts +9 -6
- package/dist/server/internal/testingSchedules.d.ts.map +1 -1
- package/dist/server/internal/testingSchedules.js +14 -9
- package/dist/server/internal/testingSchedules.js.map +1 -1
- package/dist/server/internal/testingWaits.d.ts +12 -8
- package/dist/server/internal/testingWaits.d.ts.map +1 -1
- package/dist/server/internal/testingWaits.js +6 -7
- package/dist/server/internal/testingWaits.js.map +1 -1
- package/dist/server/internal/tracing.d.ts +2 -2
- package/dist/server/internal/tracing.d.ts.map +1 -1
- package/dist/server/internal/tracing.js.map +1 -1
- package/dist/server/internal/validateQueueNames.d.ts +2 -2
- package/dist/server/internal/validateQueueNames.d.ts.map +1 -1
- package/dist/server/internal/validateQueueNames.js +1 -1
- package/dist/server/internal/validateQueueNames.js.map +1 -1
- package/dist/server/internal/waitForBatchExpiry.d.ts +4 -4
- package/dist/server/internal/waitForBatchExpiry.d.ts.map +1 -1
- package/dist/server/internal/waitForBatchExpiry.js +1 -1
- package/dist/server/internal/waitForBatchExpiry.js.map +1 -1
- package/dist/server/job.d.ts +42 -0
- package/dist/server/job.d.ts.map +1 -0
- package/dist/server/job.js +2 -0
- package/dist/server/job.js.map +1 -0
- package/dist/server/jobModule.d.ts +6 -4
- package/dist/server/jobModule.d.ts.map +1 -1
- package/dist/server/jobModule.js +7 -5
- package/dist/server/jobModule.js.map +1 -1
- package/dist/server/queueOptions.d.ts +19 -0
- package/dist/server/queueOptions.d.ts.map +1 -0
- package/dist/server/queueOptions.js +2 -0
- package/dist/server/queueOptions.js.map +1 -0
- package/dist/server/readJobFailure.d.ts +5 -0
- package/dist/server/readJobFailure.d.ts.map +1 -0
- package/dist/server/readJobFailure.js +8 -0
- package/dist/server/readJobFailure.js.map +1 -0
- package/dist/server/schema.d.ts +1 -1
- package/dist/server/schema.d.ts.map +1 -1
- package/dist/server/schema.js +23 -7
- package/dist/server/schema.js.map +1 -1
- package/dist/server/service.d.ts +17 -12
- package/dist/server/service.d.ts.map +1 -1
- package/dist/server/service.js +19 -27
- package/dist/server/service.js.map +1 -1
- package/dist/server/testing.d.ts +63 -67
- package/dist/server/testing.d.ts.map +1 -1
- package/dist/server/testing.js +5 -97
- package/dist/server/testing.js.map +1 -1
- package/dist/server/workerOptions.d.ts +25 -0
- package/dist/server/workerOptions.d.ts.map +1 -0
- package/dist/server/workerOptions.js +2 -0
- package/dist/server/workerOptions.js.map +1 -0
- package/package.json +11 -16
- package/src/display.ts +12 -0
- package/src/server/ClientDatabase.ts +7 -0
- package/src/server/PgBoss.ts +2 -2
- package/src/server/adapters/batchClockOffset.ts +8 -5
- package/src/server/{internal → adapters}/batchHandler.ts +13 -13
- package/src/server/{internal → adapters}/clientCache.ts +10 -22
- package/src/server/adapters/clientErrorLogger.ts +1 -1
- package/src/server/{defaultClientFactory.ts → adapters/defaultClientFactory.ts} +4 -2
- package/src/server/adapters/deferralCount.ts +5 -5
- package/src/server/{internal → adapters}/expireAttempt.ts +4 -3
- package/src/server/adapters/inspection.ts +31 -0
- package/src/server/adapters/inspectionChanges.ts +31 -0
- package/src/server/adapters/inspectionDeferrals.ts +20 -0
- package/src/server/adapters/inspectionJobs.ts +28 -0
- package/src/server/adapters/inspectionOperation.ts +6 -0
- package/src/server/adapters/inspectionPlan.ts +21 -0
- package/src/server/adapters/inspectionReads.ts +55 -0
- package/src/server/{internal/testingSnapshot.ts → adapters/inspectionSnapshot.ts} +16 -18
- package/src/server/adapters/installSchema.ts +2 -2
- package/src/server/adapters/jobEngine.ts +55 -0
- package/src/server/adapters/lifecycle.ts +67 -0
- package/src/server/adapters/listJobs.ts +43 -0
- package/src/server/adapters/payloadIdentity.ts +15 -0
- package/src/server/adapters/queueAdministration.ts +47 -0
- package/src/server/{internal/testingSignal.ts → adapters/queueSignal.ts} +1 -1
- package/src/server/adapters/registerWorker.ts +17 -12
- package/src/server/adapters/retireJobs.ts +5 -5
- package/src/server/adapters/schemaIndexBuilds.ts +2 -2
- package/src/server/{internal → adapters}/settleDeferral.ts +5 -5
- package/src/server/{internal → adapters}/testingClient.ts +24 -40
- package/src/server/adapters/testingController.ts +125 -0
- package/src/server/adapters/testingDueNow.ts +5 -5
- package/src/server/adapters/testingEngine.ts +15 -0
- package/src/server/adapters/testingExpirations.ts +6 -4
- package/src/server/adapters/testingInspectionClient.ts +70 -0
- package/src/server/adapters/transactionDb.ts +2 -2
- package/src/server/client.ts +86 -30
- package/src/server/clientOptions.ts +80 -0
- package/src/server/defineSchedule.ts +3 -2
- package/src/server/definition.ts +38 -29
- package/src/server/engineClient.ts +22 -0
- package/src/server/enqueueOptions.ts +25 -0
- package/src/server/error.ts +18 -2
- package/src/server/health.ts +2 -2
- package/src/server/inspection.ts +50 -0
- package/src/server/internal/acquireClient.ts +26 -0
- package/src/server/internal/adapters/testingFetches.ts +2 -2
- package/src/server/internal/clientErrors.ts +1 -1
- package/src/server/internal/countsFor.ts +5 -5
- package/src/server/internal/deadLetterResolutionPlan.ts +1 -1
- package/src/server/internal/deadlineOf.ts +2 -2
- package/src/server/internal/deferrableAttempt.ts +5 -22
- package/src/server/internal/deferral.ts +2 -4
- package/src/server/internal/deferralStorePlan.ts +2 -2
- package/src/server/internal/definitionOptions.ts +1 -1
- package/src/server/internal/engine.ts +35 -0
- package/src/server/internal/enqueueFor.ts +19 -6
- package/src/server/internal/ensureQueue.ts +5 -6
- package/src/server/internal/healthFor.ts +4 -4
- package/src/server/internal/jobControl.ts +15 -50
- package/src/server/internal/jobListings.ts +85 -0
- package/src/server/internal/jobStorePlans.ts +4 -3
- package/src/server/internal/lifecycle.ts +14 -55
- package/src/server/internal/makeService.ts +24 -15
- package/src/server/internal/register.ts +8 -12
- package/src/server/internal/registerReleasedJobs.ts +5 -5
- package/src/server/internal/retryWake.ts +3 -3
- package/src/server/internal/runQueueWorker.ts +8 -8
- package/src/server/internal/storedRows.ts +3 -3
- package/src/server/internal/testingIdle.ts +8 -31
- package/src/server/internal/testingOperation.ts +18 -0
- package/src/server/internal/testingSchedules.ts +29 -17
- package/src/server/internal/testingWaits.ts +16 -16
- package/src/server/internal/tracing.ts +2 -2
- package/src/server/internal/validateQueueNames.ts +2 -2
- package/src/server/internal/waitForBatchExpiry.ts +4 -4
- package/src/server/job.ts +42 -0
- package/src/server/jobModule.ts +19 -7
- package/src/server/queueOptions.ts +20 -0
- package/src/server/readJobFailure.ts +12 -0
- package/src/server/schema.ts +23 -7
- package/src/server/service.ts +43 -44
- package/src/server/testing.ts +4 -117
- package/src/server/workerOptions.ts +28 -0
- package/dist/server/defaultClientFactory.d.ts +0 -3
- package/dist/server/defaultClientFactory.d.ts.map +0 -1
- package/dist/server/defaultClientFactory.js.map +0 -1
- package/dist/server/internal/batchHandler.d.ts +0 -5
- package/dist/server/internal/batchHandler.d.ts.map +0 -1
- package/dist/server/internal/batchHandler.js.map +0 -1
- package/dist/server/internal/clientCache.d.ts +0 -8
- package/dist/server/internal/clientCache.d.ts.map +0 -1
- package/dist/server/internal/clientCache.js.map +0 -1
- package/dist/server/internal/expireAttempt.d.ts +0 -3
- package/dist/server/internal/expireAttempt.d.ts.map +0 -1
- package/dist/server/internal/listJobs.d.ts +0 -5
- package/dist/server/internal/listJobs.d.ts.map +0 -1
- package/dist/server/internal/listJobs.js +0 -75
- package/dist/server/internal/listJobs.js.map +0 -1
- package/dist/server/internal/observeTestingSettlements.d.ts +0 -6
- package/dist/server/internal/observeTestingSettlements.d.ts.map +0 -1
- package/dist/server/internal/observeTestingSettlements.js +0 -35
- package/dist/server/internal/observeTestingSettlements.js.map +0 -1
- package/dist/server/internal/settleDeferral.d.ts +0 -7
- package/dist/server/internal/settleDeferral.d.ts.map +0 -1
- package/dist/server/internal/settleDeferral.js.map +0 -1
- package/dist/server/internal/testingClient.d.ts +0 -13
- package/dist/server/internal/testingClient.d.ts.map +0 -1
- package/dist/server/internal/testingClient.js.map +0 -1
- package/dist/server/internal/testingDeferrals.d.ts +0 -10
- package/dist/server/internal/testingDeferrals.d.ts.map +0 -1
- package/dist/server/internal/testingDeferrals.js +0 -15
- package/dist/server/internal/testingDeferrals.js.map +0 -1
- package/dist/server/internal/testingReadout.d.ts +0 -44
- package/dist/server/internal/testingReadout.d.ts.map +0 -1
- package/dist/server/internal/testingReadout.js +0 -13
- package/dist/server/internal/testingReadout.js.map +0 -1
- package/dist/server/internal/testingRegistrations.d.ts +0 -4
- package/dist/server/internal/testingRegistrations.d.ts.map +0 -1
- package/dist/server/internal/testingRegistrations.js +0 -8
- package/dist/server/internal/testingRegistrations.js.map +0 -1
- package/dist/server/internal/testingSignal.d.ts.map +0 -1
- package/dist/server/internal/testingSignal.js.map +0 -1
- package/dist/server/internal/testingSnapshot.d.ts +0 -6
- package/dist/server/internal/testingSnapshot.d.ts.map +0 -1
- package/dist/server/internal/testingSnapshot.js.map +0 -1
- package/src/server/internal/listJobs.ts +0 -116
- package/src/server/internal/observeTestingSettlements.ts +0 -36
- package/src/server/internal/testingDeferrals.ts +0 -22
- package/src/server/internal/testingReadout.ts +0 -19
- package/src/server/internal/testingRegistrations.ts +0 -10
- /package/dist/server/{defaultClientFactory.js → adapters/defaultClientFactory.js} +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { isDeepStrictEqual } from "node:util";
|
|
2
|
-
import type {
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
2
|
+
import type { ClientOptions } from "#server/clientOptions.ts";
|
|
3
|
+
import { PgBossClientOptionsError } from "#server/error.ts";
|
|
4
|
+
import type { StartingClient } from "./lifecycle.ts";
|
|
5
5
|
|
|
6
6
|
interface CachedClient {
|
|
7
|
-
readonly client:
|
|
8
|
-
readonly constructorOptions:
|
|
7
|
+
readonly client: StartingClient;
|
|
8
|
+
readonly constructorOptions: ClientOptions;
|
|
9
9
|
references: number;
|
|
10
10
|
}
|
|
11
11
|
|
|
@@ -23,13 +23,13 @@ function isCachedClient(value: unknown): value is CachedClient {
|
|
|
23
23
|
return (
|
|
24
24
|
typeof value === "object"
|
|
25
25
|
&& value !== null
|
|
26
|
-
&& Reflect.get(value, "client")
|
|
26
|
+
&& typeof Reflect.get(value, "client") === "object"
|
|
27
27
|
&& typeof Reflect.get(value, "constructorOptions") === "object"
|
|
28
28
|
&& typeof Reflect.get(value, "references") === "number"
|
|
29
29
|
);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
export
|
|
32
|
+
export function acquireCachedClient(key: string | symbol, constructorOptions: ClientOptions, start: () => StartingClient) {
|
|
33
33
|
const existing = entryFor(key);
|
|
34
34
|
if (existing !== undefined) {
|
|
35
35
|
const options = [...new Set([...Object.keys(existing.constructorOptions), ...Object.keys(constructorOptions)])]
|
|
@@ -39,27 +39,15 @@ export async function acquireCachedClient(key: string | symbol, constructorOptio
|
|
|
39
39
|
throw new PgBossClientOptionsError({ key, options });
|
|
40
40
|
}
|
|
41
41
|
existing.references += 1;
|
|
42
|
-
|
|
43
|
-
return { client: await existing.client, reused: true };
|
|
44
|
-
} catch (error) {
|
|
45
|
-
existing.references -= 1;
|
|
46
|
-
throw error;
|
|
47
|
-
}
|
|
42
|
+
return { ...existing.client, reused: true };
|
|
48
43
|
}
|
|
49
44
|
const settings = { ...constructorOptions };
|
|
50
45
|
const entry: CachedClient = { client: start(), constructorOptions: settings, references: 1 };
|
|
51
46
|
clients.set(key, entry);
|
|
52
|
-
|
|
53
|
-
return { client: await entry.client, reused: false };
|
|
54
|
-
} catch (error) {
|
|
55
|
-
if (clients.get(key) === entry) {
|
|
56
|
-
clients.delete(key);
|
|
57
|
-
}
|
|
58
|
-
throw error;
|
|
59
|
-
}
|
|
47
|
+
return { ...entry.client, reused: false };
|
|
60
48
|
}
|
|
61
49
|
|
|
62
|
-
export function releaseCachedClient(key: string | symbol):
|
|
50
|
+
export function releaseCachedClient(key: string | symbol): StartingClient | undefined {
|
|
63
51
|
const entry = entryFor(key);
|
|
64
52
|
if (entry === undefined) {
|
|
65
53
|
return;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
-
import { logClientError } from "#internal/clientErrors.ts";
|
|
2
|
+
import { logClientError } from "#server/internal/clientErrors.ts";
|
|
3
3
|
|
|
4
4
|
export const clientErrorLogger = Effect.fnUntraced(function* () {
|
|
5
5
|
const run = Effect.runForkWith(yield* Effect.context<never>());
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Socket } from "node:net";
|
|
2
|
-
import {
|
|
2
|
+
import { PgBoss } from "pg-boss";
|
|
3
|
+
import type { ClientOptions } from "#server/clientOptions.ts";
|
|
4
|
+
import type { EngineClient } from "#server/engineClient.ts";
|
|
3
5
|
|
|
4
|
-
export function defaultClientFactory(options:
|
|
6
|
+
export function defaultClientFactory(options: ClientOptions): EngineClient {
|
|
5
7
|
const disconnected = new Set<Promise<void>>();
|
|
6
8
|
const config = {
|
|
7
9
|
...options,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Effect, Schema } from "effect";
|
|
2
|
-
import type {
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import type { PgBossClient } from "#server/client.ts";
|
|
3
|
+
import { toPgBossError } from "#server/error.ts";
|
|
4
|
+
import { quotedSchema } from "#server/internal/storedRows.ts";
|
|
5
|
+
import type { WorkerJob } from "#server/job.ts";
|
|
6
6
|
|
|
7
7
|
const Count = Schema.Struct({ count: Schema.NumberFromString });
|
|
8
8
|
|
|
9
|
-
export const deferralCount = Effect.fnUntraced(function* (client: PgBossClient, schema: string, job:
|
|
9
|
+
export const deferralCount = Effect.fnUntraced(function* (client: PgBossClient, schema: string, job: WorkerJob<unknown>) {
|
|
10
10
|
const quoted = quotedSchema(schema);
|
|
11
11
|
return yield* Effect.tryPromise({
|
|
12
12
|
catch: (error) => toPgBossError("settle", error, job.name),
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
1
|
+
import type { EngineClient } from "#server/engineClient.ts";
|
|
2
|
+
import type { JobAttempt } from "#server/internal/engine.ts";
|
|
3
|
+
import { quotedSchema } from "#server/internal/storedRows.ts";
|
|
3
4
|
|
|
4
|
-
export async function expireAttempt(client:
|
|
5
|
+
export async function expireAttempt(client: EngineClient, schema: string, job: JobAttempt, cause: "expiry" | "heartbeat" = "expiry"): Promise<void> {
|
|
5
6
|
if ((await client.schemaVersion()) !== 46) {
|
|
6
7
|
throw new Error("Testing expiry requires pg-boss schema version 46");
|
|
7
8
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { jobEngine } from "#server/adapters/jobEngine.ts";
|
|
3
|
+
import type { PgBossClient } from "#server/client.ts";
|
|
4
|
+
import type { PgBossInspectionService } from "#server/inspection.ts";
|
|
5
|
+
import { countsFor } from "#server/internal/countsFor.ts";
|
|
6
|
+
import { JobEngine } from "#server/internal/engine.ts";
|
|
7
|
+
import { healthFor } from "#server/internal/healthFor.ts";
|
|
8
|
+
import { jobControl } from "#server/internal/jobControl.ts";
|
|
9
|
+
import { jobListings } from "#server/internal/jobListings.ts";
|
|
10
|
+
import { inspectionChanges } from "./inspectionChanges.ts";
|
|
11
|
+
import { inspectionReads } from "./inspectionReads.ts";
|
|
12
|
+
|
|
13
|
+
export function inspection(client: PgBossClient, schema = "pgboss"): Effect.Effect<PgBossInspectionService> {
|
|
14
|
+
const engine = jobEngine(client, schema);
|
|
15
|
+
return Effect.gen(function* () {
|
|
16
|
+
const listings = yield* jobListings;
|
|
17
|
+
const { getJob } = yield* jobControl;
|
|
18
|
+
return {
|
|
19
|
+
...inspectionReads(client, schema),
|
|
20
|
+
...listings,
|
|
21
|
+
changes: (queue?: { readonly name: string }) => inspectionChanges(client, schema, queue?.name),
|
|
22
|
+
counts: (queue: { readonly name: string }) => countsFor(client, schema, queue.name),
|
|
23
|
+
getJob,
|
|
24
|
+
health: (queues: readonly { readonly name: string }[]) =>
|
|
25
|
+
healthFor(
|
|
26
|
+
client,
|
|
27
|
+
queues.map((queue) => queue.name),
|
|
28
|
+
),
|
|
29
|
+
};
|
|
30
|
+
}).pipe(Effect.provideService(JobEngine, engine));
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { inspectionChannel } from "#server/adapters/inspectionPlan.ts";
|
|
3
|
+
import type { PgBossClient } from "#server/client.ts";
|
|
4
|
+
import { toPgBossError } from "#server/error.ts";
|
|
5
|
+
import { queueSignal } from "./queueSignal.ts";
|
|
6
|
+
|
|
7
|
+
export const inspectionChanges = Effect.fnUntraced(function* (client: PgBossClient, schema: string, queue?: string) {
|
|
8
|
+
const signal = queueSignal();
|
|
9
|
+
yield* Effect.acquireRelease(
|
|
10
|
+
Effect.tryPromise({
|
|
11
|
+
catch: (error) => toPgBossError("inspect", error, queue),
|
|
12
|
+
try: () => {
|
|
13
|
+
const db = client.getDb?.();
|
|
14
|
+
if (db?.listen === undefined) {
|
|
15
|
+
throw new TypeError("This pg-boss client does not support listen");
|
|
16
|
+
}
|
|
17
|
+
return db.listen(
|
|
18
|
+
inspectionChannel(schema),
|
|
19
|
+
(name) => {
|
|
20
|
+
if (queue === undefined || name === queue) {
|
|
21
|
+
signal.changed();
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
signal.changed,
|
|
25
|
+
);
|
|
26
|
+
},
|
|
27
|
+
}),
|
|
28
|
+
(listener) => Effect.promise(() => listener.close()),
|
|
29
|
+
);
|
|
30
|
+
return { revision: signal.revision, waitForChange: signal.waitForChange };
|
|
31
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { DateTime, Effect } from "effect";
|
|
2
|
+
import type { PgBossClient } from "#server/client.ts";
|
|
3
|
+
import type { QueueDefinition } from "#server/definition.ts";
|
|
4
|
+
import { deferralOf } from "#server/internal/deferral.ts";
|
|
5
|
+
import { inspectionJobs } from "./inspectionJobs.ts";
|
|
6
|
+
|
|
7
|
+
export function inspectionDeferrals(client: PgBossClient) {
|
|
8
|
+
const { storedJobs } = inspectionJobs(client);
|
|
9
|
+
return {
|
|
10
|
+
deferred: (queue: Pick<QueueDefinition, "name">) =>
|
|
11
|
+
storedJobs(queue).pipe(
|
|
12
|
+
Effect.map((jobs) =>
|
|
13
|
+
jobs.flatMap((job) => {
|
|
14
|
+
const deferral = job.state === "retry" && job.startedOn === null ? deferralOf(job) : undefined;
|
|
15
|
+
return deferral === undefined ? [] : [{ at: DateTime.makeUnsafe(job.startAfter), reason: deferral.reason }];
|
|
16
|
+
}),
|
|
17
|
+
),
|
|
18
|
+
),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Effect, type Schema } from "effect";
|
|
2
|
+
import type { JobReadOptions, PgBossClient } from "#server/client.ts";
|
|
3
|
+
import type { JobPayloadSchema } from "#server/definition.ts";
|
|
4
|
+
import { toPgBossError } from "#server/error.ts";
|
|
5
|
+
import { decodeStoredData } from "#server/internal/storedRows.ts";
|
|
6
|
+
|
|
7
|
+
export function inspectionJobs(client: PgBossClient) {
|
|
8
|
+
function storedJobs(queue: { readonly name: string }, options?: JobReadOptions) {
|
|
9
|
+
return Effect.tryPromise({
|
|
10
|
+
catch: (error) => toPgBossError("inspect", error, queue.name),
|
|
11
|
+
try: () => {
|
|
12
|
+
if (client.findJobs === undefined) {
|
|
13
|
+
throw new TypeError("This pg-boss client does not support findJobs");
|
|
14
|
+
}
|
|
15
|
+
return client.findJobs(queue.name, options);
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function jobs<TName extends string, TPayload extends JobPayloadSchema | typeof Schema.Null>(
|
|
20
|
+
queue: { readonly name: TName; readonly schema: TPayload },
|
|
21
|
+
options?: JobReadOptions,
|
|
22
|
+
) {
|
|
23
|
+
return storedJobs(queue, options).pipe(
|
|
24
|
+
Effect.flatMap((rows) => Effect.forEach(rows, (job) => decodeStoredData(queue, job.data).pipe(Effect.map((data) => ({ ...job, data }))))),
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
return { jobs, storedJobs };
|
|
28
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { toPgBossError } from "#server/error.ts";
|
|
3
|
+
|
|
4
|
+
export function inspectionOperation<A>(run: () => Promise<A>, queue?: string) {
|
|
5
|
+
return Effect.tryPromise({ catch: (error) => toPgBossError("inspect", error, queue), try: run });
|
|
6
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { quotedSchema } from "#server/internal/storedRows.ts";
|
|
2
|
+
|
|
3
|
+
export function inspectionChannel(schema: string): string {
|
|
4
|
+
return `jobs:${schema}`;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function inspectionPlan(schema: string): string {
|
|
8
|
+
const quoted = quotedSchema(schema);
|
|
9
|
+
const channel = inspectionChannel(schema).replaceAll("'", "''");
|
|
10
|
+
const body = `BEGIN
|
|
11
|
+
CREATE OR REPLACE FUNCTION ${quoted}.effect_job_changed() RETURNS trigger LANGUAGE plpgsql AS $body$
|
|
12
|
+
BEGIN
|
|
13
|
+
PERFORM pg_notify('${channel}', COALESCE(NEW.name, OLD.name));
|
|
14
|
+
RETURN NULL;
|
|
15
|
+
END
|
|
16
|
+
$body$;
|
|
17
|
+
CREATE OR REPLACE TRIGGER effect_job_changed AFTER INSERT OR UPDATE OR DELETE ON ${quoted}.job
|
|
18
|
+
FOR EACH ROW EXECUTE FUNCTION ${quoted}.effect_job_changed();
|
|
19
|
+
END`;
|
|
20
|
+
return `DO '${body.replaceAll("'", "''")}'`;
|
|
21
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
import { inspectionDeferrals } from "#server/adapters/inspectionDeferrals.ts";
|
|
3
|
+
import { inspectionJobs } from "#server/adapters/inspectionJobs.ts";
|
|
4
|
+
import { inspectionOperation } from "#server/adapters/inspectionOperation.ts";
|
|
5
|
+
import { inspectionSnapshot } from "#server/adapters/inspectionSnapshot.ts";
|
|
6
|
+
import type { PgBossClient } from "#server/client.ts";
|
|
7
|
+
import type { QueueDefinition } from "#server/definition.ts";
|
|
8
|
+
import { quotedSchema } from "#server/internal/storedRows.ts";
|
|
9
|
+
|
|
10
|
+
const Busy = Schema.Struct({ busy: Schema.Boolean });
|
|
11
|
+
export function inspectionReads(client: PgBossClient, schema: string) {
|
|
12
|
+
const quoted = quotedSchema(schema);
|
|
13
|
+
function query(text: string, values?: unknown[]) {
|
|
14
|
+
const db = client.getDb?.();
|
|
15
|
+
if (db === undefined) {
|
|
16
|
+
throw new TypeError("This pg-boss client does not support getDb");
|
|
17
|
+
}
|
|
18
|
+
return db.executeSql(text, values);
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
...inspectionDeferrals(client),
|
|
22
|
+
busy: (queues: readonly Pick<QueueDefinition, "name">[]) =>
|
|
23
|
+
inspectionOperation(async () => {
|
|
24
|
+
const { rows } = await query(
|
|
25
|
+
`/* jobs inspection busy */ SELECT EXISTS (
|
|
26
|
+
SELECT 1 FROM ${quoted}.job WHERE name = ANY($1::text[]) AND (
|
|
27
|
+
(state < 'active' AND NOT blocked AND start_after <= ${quoted}.job_now()) OR state = 'active'
|
|
28
|
+
)
|
|
29
|
+
) AS busy`,
|
|
30
|
+
[queues.map(({ name }) => name)],
|
|
31
|
+
);
|
|
32
|
+
return Schema.decodeUnknownSync(Busy)(rows[0]).busy;
|
|
33
|
+
}),
|
|
34
|
+
...inspectionJobs(client),
|
|
35
|
+
queue: (queue: Pick<QueueDefinition, "name">) => inspectionOperation(() => client.getQueue(queue.name), queue.name),
|
|
36
|
+
schedules: (name?: string, key?: string) =>
|
|
37
|
+
inspectionOperation(() => {
|
|
38
|
+
if (client.getSchedules === undefined) {
|
|
39
|
+
throw new TypeError("This pg-boss client does not support getSchedules");
|
|
40
|
+
}
|
|
41
|
+
return client.getSchedules(name, key);
|
|
42
|
+
}),
|
|
43
|
+
schemaVersion: () =>
|
|
44
|
+
inspectionOperation(() => {
|
|
45
|
+
if (client.schemaVersion === undefined) {
|
|
46
|
+
throw new TypeError("This pg-boss client does not support schemaVersion");
|
|
47
|
+
}
|
|
48
|
+
return client.schemaVersion();
|
|
49
|
+
}),
|
|
50
|
+
snapshot: inspectionSnapshot(
|
|
51
|
+
() => client,
|
|
52
|
+
() => schema,
|
|
53
|
+
),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Effect, Schema } from "effect";
|
|
2
|
-
import
|
|
3
|
-
import type {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
2
|
+
import { inspectionOperation } from "#server/adapters/inspectionOperation.ts";
|
|
3
|
+
import type { PgBossClient } from "#server/client.ts";
|
|
4
|
+
import type { PgBossError, PgBossPayloadError } from "#server/error.ts";
|
|
5
|
+
import type { SnapshotQueue, UnfinishedJob } from "#server/inspection.ts";
|
|
6
|
+
import { decodeStoredData, quotedSchema } from "#server/internal/storedRows.ts";
|
|
7
7
|
|
|
8
8
|
const Rows = Schema.Array(
|
|
9
9
|
Schema.Struct({
|
|
@@ -15,29 +15,27 @@ const Rows = Schema.Array(
|
|
|
15
15
|
}),
|
|
16
16
|
);
|
|
17
17
|
|
|
18
|
-
export function
|
|
18
|
+
export function inspectionSnapshot(client: () => PgBossClient, schema: () => string) {
|
|
19
19
|
return <const TQueues extends readonly SnapshotQueue[]>(
|
|
20
20
|
queues: TQueues,
|
|
21
|
-
): Effect.Effect<
|
|
22
|
-
readonly UnfinishedJob<TQueues[number]>[],
|
|
23
|
-
PgBossPayloadError | PgBossTestingError,
|
|
24
|
-
TQueues[number]["schema"]["DecodingServices"]
|
|
25
|
-
> => {
|
|
21
|
+
): Effect.Effect<readonly UnfinishedJob<TQueues[number]>[], PgBossPayloadError | PgBossError, TQueues[number]["schema"]["DecodingServices"]> => {
|
|
26
22
|
const byName = new Map<string, TQueues[number]>(queues.map((queue) => [queue.name, queue]));
|
|
27
|
-
return
|
|
23
|
+
return inspectionOperation(async () => {
|
|
28
24
|
const quoted = quotedSchema(schema());
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
const db = client().getDb?.();
|
|
26
|
+
if (db === undefined) {
|
|
27
|
+
throw new TypeError("This pg-boss client does not support getDb");
|
|
28
|
+
}
|
|
29
|
+
const { rows } = await db.executeSql(
|
|
30
|
+
`SELECT id, name AS queue, data, start_after AS "startAfter",
|
|
33
31
|
CASE WHEN state = 'retry' AND started_on IS NULL AND start_after > ${quoted}.job_now()
|
|
34
32
|
AND output ? 'jobDeferral'
|
|
35
33
|
THEN 'deferred' ELSE state::text END AS state
|
|
36
34
|
FROM ${quoted}.job
|
|
37
35
|
WHERE name = ANY($1::text[]) AND state IN ('created', 'retry', 'active', 'failed')
|
|
38
36
|
ORDER BY created_on, id`,
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
[[...byName.keys()]],
|
|
38
|
+
);
|
|
41
39
|
return Schema.decodeUnknownPromise(Rows)(rows);
|
|
42
40
|
}).pipe(
|
|
43
41
|
Effect.flatMap((rows) =>
|
|
@@ -3,8 +3,8 @@ import { SqlClient } from "effect/sql";
|
|
|
3
3
|
import type { Connection } from "effect/sql/SqlConnection";
|
|
4
4
|
import { getConstructionPlans, getMigrationPlans, PgBoss } from "pg-boss";
|
|
5
5
|
import pgBossPackage from "pg-boss/package.json" with { type: "json" };
|
|
6
|
-
import { jobStorePlans } from "#internal/jobStorePlans.ts";
|
|
7
|
-
import type { PgBossSchemaOptions } from "#schema.ts";
|
|
6
|
+
import { jobStorePlans } from "#server/internal/jobStorePlans.ts";
|
|
7
|
+
import type { PgBossSchemaOptions } from "#server/schema.ts";
|
|
8
8
|
import { runSchemaPlan } from "./runSchemaPlan.ts";
|
|
9
9
|
import { resumeSchemaIndexes } from "./schemaIndexBuilds.ts";
|
|
10
10
|
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type Context, Effect } from "effect";
|
|
2
|
+
import type { PgBossClient } from "#server/client.ts";
|
|
3
|
+
import { toPgBossError } from "#server/error.ts";
|
|
4
|
+
import type { JobEngine } from "#server/internal/engine.ts";
|
|
5
|
+
import { listJobs } from "./listJobs.ts";
|
|
6
|
+
import { queueAdministration } from "./queueAdministration.ts";
|
|
7
|
+
import { settleDeferral } from "./settleDeferral.ts";
|
|
8
|
+
|
|
9
|
+
export function jobEngine(client: PgBossClient, schema = "pgboss"): Context.Service.Shape<typeof JobEngine> {
|
|
10
|
+
return {
|
|
11
|
+
...queueAdministration(client),
|
|
12
|
+
getJob: (queue, id) =>
|
|
13
|
+
Effect.tryPromise({
|
|
14
|
+
catch: (error) => toPgBossError("getJob", error, queue),
|
|
15
|
+
try: async () => {
|
|
16
|
+
if (client.findJobs === undefined) {
|
|
17
|
+
throw new TypeError("This pg-boss client does not support findJobs");
|
|
18
|
+
}
|
|
19
|
+
return (await client.findJobs(queue, { id }))[0];
|
|
20
|
+
},
|
|
21
|
+
}),
|
|
22
|
+
listJobs: listJobs(client, schema),
|
|
23
|
+
retry: (queue, id) =>
|
|
24
|
+
Effect.tryPromise({
|
|
25
|
+
catch: (error) => toPgBossError("retry", error, queue),
|
|
26
|
+
try: async () => {
|
|
27
|
+
if (client.findJobs === undefined || client.retry === undefined || client.update === undefined) {
|
|
28
|
+
throw new TypeError("This pg-boss client does not support findJobs, retry and update");
|
|
29
|
+
}
|
|
30
|
+
const job = (await client.findJobs(queue, { id }))[0];
|
|
31
|
+
if (job?.state !== "failed" && job?.state !== "retry") {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (job.state === "failed") {
|
|
35
|
+
await client.retry(queue, id);
|
|
36
|
+
}
|
|
37
|
+
await client.update(queue, undefined, { id, startAfter: 0 });
|
|
38
|
+
},
|
|
39
|
+
}),
|
|
40
|
+
settleDeferral: (job, at, reason, maxDeferrals) =>
|
|
41
|
+
Effect.tryPromise({
|
|
42
|
+
catch: (error) => toPgBossError("settle", error, job.name),
|
|
43
|
+
try: () => settleDeferral(client, schema, job, at, reason, maxDeferrals),
|
|
44
|
+
}).pipe(
|
|
45
|
+
Effect.tap((settled) =>
|
|
46
|
+
Effect.sync(() => {
|
|
47
|
+
if (!settled.claimed || settled.deferred) {
|
|
48
|
+
// Native batch settlement must not match a sibling's new claim at the unchanged retry count.
|
|
49
|
+
job.retryCount = Number.MAX_SAFE_INTEGER;
|
|
50
|
+
}
|
|
51
|
+
}),
|
|
52
|
+
),
|
|
53
|
+
),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { type Context, Effect, Exit, Scope } from "effect";
|
|
2
|
+
import type { PgBossClient } from "#server/client.ts";
|
|
3
|
+
import type { StopOptions } from "#server/clientOptions.ts";
|
|
4
|
+
import { PgBossClientOptionsError, toPgBossError } from "#server/error.ts";
|
|
5
|
+
import { observeClientErrors } from "#server/internal/clientErrors.ts";
|
|
6
|
+
import { jobStorePlans } from "#server/internal/jobStorePlans.ts";
|
|
7
|
+
import type { AcquireClientOptions, ClientEngine } from "#server/internal/lifecycle.ts";
|
|
8
|
+
import { acquireCachedClient, releaseCachedClient } from "./clientCache.ts";
|
|
9
|
+
import { defaultClientFactory } from "./defaultClientFactory.ts";
|
|
10
|
+
|
|
11
|
+
export interface StartingClient {
|
|
12
|
+
readonly client: PgBossClient;
|
|
13
|
+
readonly ready: Promise<void>;
|
|
14
|
+
readonly stop: (options?: StopOptions) => Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function startClient(options: AcquireClientOptions, report: (error: Error) => void): StartingClient {
|
|
18
|
+
const client = (options.clientFactory ?? defaultClientFactory)(options.constructor);
|
|
19
|
+
observeClientErrors(client, report);
|
|
20
|
+
let closing = false;
|
|
21
|
+
const ready = (async () => {
|
|
22
|
+
await client.start();
|
|
23
|
+
if (!closing && options.constructor.migrate !== false && client.getDb !== undefined) {
|
|
24
|
+
for (const plan of jobStorePlans(options.constructor.schema ?? "pgboss")) {
|
|
25
|
+
await client.getDb().executeSql(plan);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
})();
|
|
29
|
+
return {
|
|
30
|
+
client,
|
|
31
|
+
ready,
|
|
32
|
+
stop: (settings) => {
|
|
33
|
+
closing = true;
|
|
34
|
+
return client.stop(settings);
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const acquire = Effect.fnUntraced(function* (options: AcquireClientOptions, report: (error: Error) => void, stop?: StopOptions) {
|
|
40
|
+
const scope = yield* Scope.fork(yield* Scope.Scope);
|
|
41
|
+
return yield* Effect.gen(function* () {
|
|
42
|
+
const lease = yield* Effect.acquireRelease(
|
|
43
|
+
Effect.try({
|
|
44
|
+
catch: (error) => (error instanceof PgBossClientOptionsError ? error : toPgBossError("start", error)),
|
|
45
|
+
try: () =>
|
|
46
|
+
options.clientCacheKey === undefined
|
|
47
|
+
? { ...startClient(options, report), reused: false }
|
|
48
|
+
: acquireCachedClient(options.clientCacheKey, options.constructor, () => startClient(options, report)),
|
|
49
|
+
}),
|
|
50
|
+
(acquired) =>
|
|
51
|
+
Effect.tryPromise({
|
|
52
|
+
catch: (error) => toPgBossError("stop", error),
|
|
53
|
+
try: async () => {
|
|
54
|
+
const client = options.clientCacheKey === undefined ? acquired : releaseCachedClient(options.clientCacheKey);
|
|
55
|
+
await client?.stop(stop);
|
|
56
|
+
},
|
|
57
|
+
}).pipe(Effect.catch(Effect.logError)),
|
|
58
|
+
);
|
|
59
|
+
yield* Effect.tryPromise({ catch: (error) => toPgBossError("start", error), try: () => lease.ready });
|
|
60
|
+
return { ...(options.clientCacheKey === undefined ? {} : { cacheKey: options.clientCacheKey }), client: lease.client, reused: lease.reused };
|
|
61
|
+
}).pipe(
|
|
62
|
+
Effect.provideService(Scope.Scope, scope),
|
|
63
|
+
Effect.onError((cause) => Scope.close(scope, Exit.failCause(cause))),
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
export const clientEngine: Context.Service.Shape<typeof ClientEngine> = { acquire };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type Context, Effect } from "effect";
|
|
2
|
+
import type { PgBossClient } from "#server/client.ts";
|
|
3
|
+
import { toPgBossError } from "#server/error.ts";
|
|
4
|
+
import { deadLetterQueueName } from "#server/health.ts";
|
|
5
|
+
import type { JobEngine } from "#server/internal/engine.ts";
|
|
6
|
+
import { quotedSchema } from "#server/internal/storedRows.ts";
|
|
7
|
+
|
|
8
|
+
export function listJobs(client: PgBossClient, schema: string): Context.Service.Shape<typeof JobEngine>["listJobs"] {
|
|
9
|
+
return (listing, queue, after, limit) =>
|
|
10
|
+
Effect.tryPromise({
|
|
11
|
+
catch: (error) => toPgBossError(listing, error, queue),
|
|
12
|
+
try: async () => {
|
|
13
|
+
if (client.getDb === undefined) {
|
|
14
|
+
throw new TypeError("This pg-boss client does not support getDb");
|
|
15
|
+
}
|
|
16
|
+
const quoted = quotedSchema(schema);
|
|
17
|
+
const { rows: storedRows } = await client.getDb().executeSql(
|
|
18
|
+
`SELECT
|
|
19
|
+
id,
|
|
20
|
+
name AS queue,
|
|
21
|
+
state,
|
|
22
|
+
retry_count AS "retryCount",
|
|
23
|
+
retry_limit AS "retryLimit",
|
|
24
|
+
created_on AS "createdOn",
|
|
25
|
+
started_on AS "startedOn",
|
|
26
|
+
completed_on AS "completedOn",
|
|
27
|
+
output,
|
|
28
|
+
data,
|
|
29
|
+
source_id AS "sourceId",
|
|
30
|
+
source_output AS "sourceOutput",
|
|
31
|
+
to_json(created_on) #>> '{}' AS "cursorAt"
|
|
32
|
+
FROM ${quoted}.job
|
|
33
|
+
WHERE name = $1
|
|
34
|
+
${listing === "failedJobs" ? "AND state = 'failed'" : ""}
|
|
35
|
+
AND ($2::timestamptz IS NULL OR (created_on, id) < ($2::timestamptz, $3::uuid))
|
|
36
|
+
ORDER BY created_on DESC, id DESC
|
|
37
|
+
LIMIT $4`,
|
|
38
|
+
[listing === "failedJobs" ? queue : deadLetterQueueName(queue), after?.[0] ?? null, after?.[1] ?? null, limit + 1],
|
|
39
|
+
);
|
|
40
|
+
return storedRows;
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
export function payloadKey(parts: readonly string[], payload: object): string {
|
|
4
|
+
return JSON.stringify(parts.map((part) => [part, typeof Reflect.get(payload, part), String(Reflect.get(payload, part))]));
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function payloadJobId(queue: string, parts: readonly string[], payload: object): string {
|
|
8
|
+
const bytes = createHash("sha256")
|
|
9
|
+
.update(JSON.stringify([queue, payloadKey(parts, payload)]))
|
|
10
|
+
.digest();
|
|
11
|
+
bytes.writeUInt8((bytes.readUInt8(6) & 0x0f) | 0x80, 6);
|
|
12
|
+
bytes.writeUInt8((bytes.readUInt8(8) & 0x3f) | 0x80, 8);
|
|
13
|
+
const hex = bytes.subarray(0, 16).toString("hex");
|
|
14
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
15
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import type { PgBossClient } from "#server/client.ts";
|
|
3
|
+
import { PgBossNotFoundError, toPgBossError } from "#server/error.ts";
|
|
4
|
+
import type { PgBossService } from "#server/service.ts";
|
|
5
|
+
|
|
6
|
+
export function queueAdministration(client: PgBossClient): Pick<PgBossService, "deleteQueue" | "refreshQueueStats" | "unschedule"> {
|
|
7
|
+
return {
|
|
8
|
+
deleteQueue: (queue) =>
|
|
9
|
+
Effect.tryPromise({
|
|
10
|
+
catch: (error) => (error instanceof PgBossNotFoundError ? error : toPgBossError("deleteQueue", error, queue.name)),
|
|
11
|
+
try: async () => {
|
|
12
|
+
if (client.deleteQueue === undefined) {
|
|
13
|
+
throw new TypeError("This pg-boss client does not support deleteQueue");
|
|
14
|
+
}
|
|
15
|
+
if ((await client.getQueue(queue.name)) === null) {
|
|
16
|
+
throw new PgBossNotFoundError({ operation: "deleteQueue", queue: queue.name });
|
|
17
|
+
}
|
|
18
|
+
await client.offWork(queue.name);
|
|
19
|
+
await client.deleteQueue(queue.name);
|
|
20
|
+
},
|
|
21
|
+
}),
|
|
22
|
+
refreshQueueStats: (queue) =>
|
|
23
|
+
Effect.tryPromise({
|
|
24
|
+
catch: (error) => toPgBossError("refreshQueueStats", error, queue?.name),
|
|
25
|
+
try: async () => {
|
|
26
|
+
if (client.supervise === undefined) {
|
|
27
|
+
throw new TypeError("This pg-boss client does not support supervise");
|
|
28
|
+
}
|
|
29
|
+
await client.supervise(queue?.name);
|
|
30
|
+
},
|
|
31
|
+
}),
|
|
32
|
+
unschedule: (schedule) =>
|
|
33
|
+
Effect.tryPromise({
|
|
34
|
+
catch: (error) => (error instanceof PgBossNotFoundError ? error : toPgBossError("unschedule", error, schedule.name)),
|
|
35
|
+
try: async () => {
|
|
36
|
+
if (client.getSchedule === undefined || client.unschedule === undefined) {
|
|
37
|
+
throw new TypeError("This pg-boss client does not support getSchedule and unschedule");
|
|
38
|
+
}
|
|
39
|
+
const key = schedule.scheduleOptions.key ?? "";
|
|
40
|
+
if ((await client.getSchedule(schedule.name, key)) === null) {
|
|
41
|
+
throw new PgBossNotFoundError({ key, operation: "unschedule", queue: schedule.name });
|
|
42
|
+
}
|
|
43
|
+
await client.unschedule(schedule.name, key);
|
|
44
|
+
},
|
|
45
|
+
}),
|
|
46
|
+
};
|
|
47
|
+
}
|