@terreno/jobs 57.4.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.
Files changed (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +56 -0
  3. package/biome.jsonc +20 -0
  4. package/bunfig.toml +5 -0
  5. package/dist/activeJobExecution.d.ts +3 -0
  6. package/dist/activeJobExecution.js +29 -0
  7. package/dist/claimLock.d.ts +16 -0
  8. package/dist/claimLock.js +34 -0
  9. package/dist/dispatchCompensation.d.ts +3 -0
  10. package/dist/dispatchCompensation.js +89 -0
  11. package/dist/dispatchError.d.ts +10 -0
  12. package/dist/dispatchError.js +33 -0
  13. package/dist/index.d.ts +9 -0
  14. package/dist/index.js +15 -0
  15. package/dist/jobExecutor.d.ts +34 -0
  16. package/dist/jobExecutor.js +328 -0
  17. package/dist/jobsApp.d.ts +61 -0
  18. package/dist/jobsApp.js +308 -0
  19. package/dist/jobsService.d.ts +38 -0
  20. package/dist/jobsService.js +505 -0
  21. package/dist/modelTypes.d.ts +52 -0
  22. package/dist/modelTypes.js +4 -0
  23. package/dist/models/job.d.ts +2 -0
  24. package/dist/models/job.js +124 -0
  25. package/dist/models/jobSchedule.d.ts +2 -0
  26. package/dist/models/jobSchedule.js +48 -0
  27. package/dist/retryBackoff.d.ts +17 -0
  28. package/dist/retryBackoff.js +22 -0
  29. package/dist/routes/jobsAdmin.d.ts +15 -0
  30. package/dist/routes/jobsAdmin.js +596 -0
  31. package/dist/routes/jobsExecute.d.ts +12 -0
  32. package/dist/routes/jobsExecute.js +119 -0
  33. package/dist/runners/gcpCloudTasks.d.ts +78 -0
  34. package/dist/runners/gcpCloudTasks.js +256 -0
  35. package/dist/runners/mongoRunner.d.ts +14 -0
  36. package/dist/runners/mongoRunner.js +204 -0
  37. package/dist/runners/vercelQueues.d.ts +111 -0
  38. package/dist/runners/vercelQueues.js +326 -0
  39. package/dist/scheduleCron.d.ts +15 -0
  40. package/dist/scheduleCron.js +61 -0
  41. package/dist/scheduler.d.ts +8 -0
  42. package/dist/scheduler.js +178 -0
  43. package/dist/types.d.ts +64 -0
  44. package/dist/types.js +2 -0
  45. package/package.json +82 -0
  46. package/src/activeJobExecution.ts +28 -0
  47. package/src/claimLock.ts +37 -0
  48. package/src/dispatchCompensation.ts +39 -0
  49. package/src/dispatchError.ts +14 -0
  50. package/src/index.ts +24 -0
  51. package/src/jobExecutor.ts +333 -0
  52. package/src/jobsApp.ts +255 -0
  53. package/src/jobsService.ts +395 -0
  54. package/src/modelTypes.ts +78 -0
  55. package/src/models/job.ts +129 -0
  56. package/src/models/jobSchedule.ts +57 -0
  57. package/src/retryBackoff.ts +34 -0
  58. package/src/routes/jobsAdmin.ts +562 -0
  59. package/src/routes/jobsExecute.ts +95 -0
  60. package/src/runners/gcpCloudTasks.ts +290 -0
  61. package/src/runners/mongoRunner.ts +135 -0
  62. package/src/runners/vercelQueues.ts +394 -0
  63. package/src/scheduleCron.ts +65 -0
  64. package/src/scheduler.ts +112 -0
  65. package/src/tests/bunSetup.ts +9 -0
  66. package/src/tests/gcpCloudTasksRunner.test.ts +349 -0
  67. package/src/tests/jobModel.test.ts +62 -0
  68. package/src/tests/jobScheduleModel.test.ts +44 -0
  69. package/src/tests/jobsAdmin.test.ts +728 -0
  70. package/src/tests/jobsApp.test.ts +113 -0
  71. package/src/tests/jobsCustomRunner.test.ts +367 -0
  72. package/src/tests/jobsDelayIdempotency.test.ts +255 -0
  73. package/src/tests/jobsExecute.test.ts +640 -0
  74. package/src/tests/jobsRetry.test.ts +420 -0
  75. package/src/tests/jobsSchedule.test.ts +505 -0
  76. package/src/tests/jobsTracer.test.ts +165 -0
  77. package/src/tests/jobsWorkerLifecycle.test.ts +509 -0
  78. package/src/tests/packageExports.test.ts +24 -0
  79. package/src/tests/retryBackoff.test.ts +76 -0
  80. package/src/tests/scheduleCron.test.ts +87 -0
  81. package/src/tests/vercelQueuesRunner.test.ts +524 -0
  82. package/src/types.ts +74 -0
  83. package/tsconfig.json +33 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Flourish Health, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # @terreno/jobs
2
+
3
+ Durable background jobs for Terreno backends — Mongo-backed queues with pluggable
4
+ runners, retries, schedules, dead letters, and admin operations.
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ bun add @terreno/jobs
10
+ ```
11
+
12
+ Peer dependency: `mongoose ^8.0.0 || ^9.0.0`. Optional peers for cloud runners:
13
+ `@google-cloud/tasks`, `@vercel/queue`.
14
+
15
+ ## Quick start
16
+
17
+ ```typescript
18
+ import {JobsApp, MongoJobRunner, getJobsService} from "@terreno/jobs";
19
+ import {TerrenoApp} from "@terreno/api";
20
+ import {User} from "./models/user";
21
+
22
+ const jobsApp = new JobsApp({runner: new MongoJobRunner()});
23
+
24
+ jobsApp.define("my/task", {
25
+ handler: async (_payload, ctx) => {
26
+ ctx.log.info("running");
27
+ },
28
+ });
29
+
30
+ new TerrenoApp({userModel: User}).register(jobsApp).start();
31
+
32
+ await jobsApp.startWorker();
33
+ await getJobsService().enqueue({name: "my/task", payload: {}});
34
+ ```
35
+
36
+ `JobsApp.register()` does not start a worker. Call `startWorker()` from the API
37
+ process or a dedicated worker entrypoint.
38
+
39
+ ## What's included
40
+
41
+ - `JobsApp` — TerrenoPlugin for definitions, admin routes, and optional execute HTTP
42
+ - `MongoJobRunner` — default in-process poll loop over MongoDB
43
+ - `GcpCloudTasksRunner` — `@terreno/jobs/runners/gcpCloudTasks`
44
+ - `VercelQueuesRunner` — `@terreno/jobs/runners/vercelQueues`
45
+ - Admin list/detail, retry, requeue, cancel, stats, and schedules
46
+ - Retries with backoff, delayed enqueue, cron schedules, and dead-letter rows
47
+
48
+ ## Documentation
49
+
50
+ Full API reference: [docs/reference/jobs.md](https://github.com/flourishhealth/terreno/blob/master/docs/reference/jobs.md)
51
+
52
+ Operator guide: [docs/how-to/background-jobs.md](https://github.com/flourishhealth/terreno/blob/master/docs/how-to/background-jobs.md)
53
+
54
+ ## License and Contributing
55
+
56
+ Licensed under the [MIT License](https://github.com/FlourishHealth/terreno/blob/master/LICENSE). See [CONTRIBUTING.md](https://github.com/FlourishHealth/terreno/blob/master/CONTRIBUTING.md) for contribution guidelines.
package/biome.jsonc ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
3
+ "extends": ["../biome.jsonc"],
4
+ "files": {
5
+ "includes": [
6
+ "package.json",
7
+ "src/**/*.ts",
8
+ "src/**/*.tsx",
9
+ "!!**/node_modules",
10
+ "!!node_modules",
11
+ "!!**/dist",
12
+ "!!dist",
13
+ "!!**/build",
14
+ "!!build",
15
+ "!!**/coverage",
16
+ "!!coverage"
17
+ ]
18
+ },
19
+ "root": true
20
+ }
package/bunfig.toml ADDED
@@ -0,0 +1,5 @@
1
+ [test]
2
+ preload = ["./src/tests/bunSetup.ts"]
3
+ root = "./src"
4
+ coveragePathIgnorePatterns = ["**/dist/**", "**/*.test.ts", "**/tests/**", "**/node_modules/**", "../**"]
5
+ coverageThreshold = { line = 95, function = 95 }
@@ -0,0 +1,3 @@
1
+ export declare const beginActiveJobExecution: (jobId: string, parentSignal: AbortSignal) => AbortSignal;
2
+ export declare const endActiveJobExecution: (jobId: string) => void;
3
+ export declare const abortActiveJobExecution: (jobId: string) => boolean;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.abortActiveJobExecution = exports.endActiveJobExecution = exports.beginActiveJobExecution = void 0;
4
+ var activeExecutions = new Map();
5
+ var beginActiveJobExecution = function (jobId, parentSignal) {
6
+ var controller = new AbortController();
7
+ activeExecutions.set(jobId, controller);
8
+ if (parentSignal.aborted) {
9
+ controller.abort();
10
+ }
11
+ else {
12
+ parentSignal.addEventListener("abort", function () { return controller.abort(); }, { once: true });
13
+ }
14
+ return controller.signal;
15
+ };
16
+ exports.beginActiveJobExecution = beginActiveJobExecution;
17
+ var endActiveJobExecution = function (jobId) {
18
+ activeExecutions.delete(jobId);
19
+ };
20
+ exports.endActiveJobExecution = endActiveJobExecution;
21
+ var abortActiveJobExecution = function (jobId) {
22
+ var controller = activeExecutions.get(jobId);
23
+ if (!controller) {
24
+ return false;
25
+ }
26
+ controller.abort();
27
+ return true;
28
+ };
29
+ exports.abortActiveJobExecution = abortActiveJobExecution;
@@ -0,0 +1,16 @@
1
+ import type { JobDocument } from "./modelTypes";
2
+ /** @internal */
3
+ export declare const getWorkerId: () => string;
4
+ export interface JobClaimLock {
5
+ lockedAt: Date;
6
+ lockedBy: string;
7
+ }
8
+ export declare const createClaimLock: (lockedAt: Date) => JobClaimLock;
9
+ export declare const buildClaimOwnershipFilter: (jobId: JobDocument["_id"], claim: JobClaimLock) => {
10
+ _id: JobDocument["_id"];
11
+ lockedAt: Date;
12
+ lockedBy: string;
13
+ };
14
+ /** @internal */
15
+ export declare const hasWorkerIdPrefix: (lockedBy: string | undefined) => boolean;
16
+ export declare const isAbortError: (error: unknown) => boolean;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.isAbortError = exports.hasWorkerIdPrefix = exports.buildClaimOwnershipFilter = exports.createClaimLock = exports.getWorkerId = void 0;
7
+ var node_crypto_1 = require("node:crypto");
8
+ var node_os_1 = __importDefault(require("node:os"));
9
+ /** @internal */
10
+ var getWorkerId = function () { return "".concat(node_os_1.default.hostname(), ":").concat(process.pid); };
11
+ exports.getWorkerId = getWorkerId;
12
+ var createClaimLock = function (lockedAt) { return ({
13
+ lockedAt: lockedAt,
14
+ lockedBy: "".concat((0, exports.getWorkerId)(), ":").concat((0, node_crypto_1.randomUUID)()),
15
+ }); };
16
+ exports.createClaimLock = createClaimLock;
17
+ var buildClaimOwnershipFilter = function (jobId, claim) { return ({
18
+ _id: jobId,
19
+ lockedAt: claim.lockedAt,
20
+ lockedBy: claim.lockedBy,
21
+ }); };
22
+ exports.buildClaimOwnershipFilter = buildClaimOwnershipFilter;
23
+ /** @internal */
24
+ var hasWorkerIdPrefix = function (lockedBy) {
25
+ if (!lockedBy) {
26
+ return false;
27
+ }
28
+ return lockedBy.startsWith("".concat((0, exports.getWorkerId)(), ":"));
29
+ };
30
+ exports.hasWorkerIdPrefix = hasWorkerIdPrefix;
31
+ var isAbortError = function (error) {
32
+ return error instanceof Error && error.name === "AbortError";
33
+ };
34
+ exports.isAbortError = isAbortError;
@@ -0,0 +1,3 @@
1
+ import type { JobDocument } from "./modelTypes";
2
+ import type { JobRunner } from "./types";
3
+ export declare const dispatchJobToRunner: (runner: JobRunner, job: JobDocument) => Promise<void>;
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.dispatchJobToRunner = void 0;
40
+ var api_1 = require("@terreno/api");
41
+ var dispatchError_1 = require("./dispatchError");
42
+ var job_1 = require("./models/job");
43
+ var removeUntouchedPendingJob = function (jobId) { return __awaiter(void 0, void 0, void 0, function () {
44
+ var removed;
45
+ return __generator(this, function (_a) {
46
+ switch (_a.label) {
47
+ case 0: return [4 /*yield*/, job_1.Job.findOneAndDelete({
48
+ _id: jobId,
49
+ $and: [
50
+ { $or: [{ lockedAt: { $exists: false } }, { lockedAt: null }] },
51
+ { $or: [{ lockedBy: { $exists: false } }, { lockedBy: null }] },
52
+ ],
53
+ attemptCount: 0,
54
+ status: "pending",
55
+ })];
56
+ case 1:
57
+ removed = _a.sent();
58
+ return [2 /*return*/, removed !== null];
59
+ }
60
+ });
61
+ }); };
62
+ var dispatchJobToRunner = function (runner, job) { return __awaiter(void 0, void 0, void 0, function () {
63
+ var error_1, compensationSucceeded;
64
+ return __generator(this, function (_a) {
65
+ switch (_a.label) {
66
+ case 0:
67
+ _a.trys.push([0, 2, , 4]);
68
+ return [4 /*yield*/, runner.enqueue(job)];
69
+ case 1:
70
+ _a.sent();
71
+ return [3 /*break*/, 4];
72
+ case 2:
73
+ error_1 = _a.sent();
74
+ return [4 /*yield*/, removeUntouchedPendingJob(job._id)];
75
+ case 3:
76
+ compensationSucceeded = _a.sent();
77
+ if (!compensationSucceeded) {
78
+ api_1.logger.error("[jobs] Dispatch failed for job ".concat(job._id.toString(), " and compensation lost race \u2014 row was already claimed or mutated"));
79
+ }
80
+ throw new dispatchError_1.JobDispatchError({
81
+ cause: error_1,
82
+ compensationSucceeded: compensationSucceeded,
83
+ jobId: job._id.toString(),
84
+ });
85
+ case 4: return [2 /*return*/];
86
+ }
87
+ });
88
+ }); };
89
+ exports.dispatchJobToRunner = dispatchJobToRunner;
@@ -0,0 +1,10 @@
1
+ export declare class JobDispatchError extends Error {
2
+ readonly cause: unknown;
3
+ readonly compensationSucceeded: boolean;
4
+ readonly jobId: string;
5
+ constructor(options: {
6
+ cause: unknown;
7
+ compensationSucceeded: boolean;
8
+ jobId: string;
9
+ });
10
+ }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ var __extends = (this && this.__extends) || (function () {
3
+ var extendStatics = function (d, b) {
4
+ extendStatics = Object.setPrototypeOf ||
5
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
+ return extendStatics(d, b);
8
+ };
9
+ return function (d, b) {
10
+ if (typeof b !== "function" && b !== null)
11
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
+ extendStatics(d, b);
13
+ function __() { this.constructor = d; }
14
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
+ };
16
+ })();
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.JobDispatchError = void 0;
19
+ var JobDispatchError = /** @class */ (function (_super) {
20
+ __extends(JobDispatchError, _super);
21
+ function JobDispatchError(options) {
22
+ var _this = this;
23
+ var detail = options.cause instanceof Error ? options.cause.message : String(options.cause);
24
+ _this = _super.call(this, "Job dispatch failed for ".concat(options.jobId, ": ").concat(detail)) || this;
25
+ _this.name = "JobDispatchError";
26
+ _this.cause = options.cause;
27
+ _this.compensationSucceeded = options.compensationSucceeded;
28
+ _this.jobId = options.jobId;
29
+ return _this;
30
+ }
31
+ return JobDispatchError;
32
+ }(Error));
33
+ exports.JobDispatchError = JobDispatchError;
@@ -0,0 +1,9 @@
1
+ export type { JobsAppOptions } from "./jobsApp";
2
+ export { JobsApp } from "./jobsApp";
3
+ export { getJobsService, tryGetJobsService, unregisterJobsService } from "./jobsService";
4
+ export { Job } from "./models/job";
5
+ export { JobSchedule } from "./models/jobSchedule";
6
+ export type { JobAttempt, JobDocument, JobModel, JobScheduleDocument, JobScheduleModel, JobStatus, } from "./modelTypes";
7
+ export type { ExecuteAuthVerifier } from "./routes/jobsExecute";
8
+ export { MongoJobRunner } from "./runners/mongoRunner";
9
+ export type { EnqueueJobParams, JobDefinition, JobHandlerContext, JobRunner, JobRunnerStartOptions, JobScheduleDefinition, JobsRunnerHost, } from "./types";
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MongoJobRunner = exports.JobSchedule = exports.Job = exports.unregisterJobsService = exports.tryGetJobsService = exports.getJobsService = exports.JobsApp = void 0;
4
+ var jobsApp_1 = require("./jobsApp");
5
+ Object.defineProperty(exports, "JobsApp", { enumerable: true, get: function () { return jobsApp_1.JobsApp; } });
6
+ var jobsService_1 = require("./jobsService");
7
+ Object.defineProperty(exports, "getJobsService", { enumerable: true, get: function () { return jobsService_1.getJobsService; } });
8
+ Object.defineProperty(exports, "tryGetJobsService", { enumerable: true, get: function () { return jobsService_1.tryGetJobsService; } });
9
+ Object.defineProperty(exports, "unregisterJobsService", { enumerable: true, get: function () { return jobsService_1.unregisterJobsService; } });
10
+ var job_1 = require("./models/job");
11
+ Object.defineProperty(exports, "Job", { enumerable: true, get: function () { return job_1.Job; } });
12
+ var jobSchedule_1 = require("./models/jobSchedule");
13
+ Object.defineProperty(exports, "JobSchedule", { enumerable: true, get: function () { return jobSchedule_1.JobSchedule; } });
14
+ var mongoRunner_1 = require("./runners/mongoRunner");
15
+ Object.defineProperty(exports, "MongoJobRunner", { enumerable: true, get: function () { return mongoRunner_1.MongoJobRunner; } });
@@ -0,0 +1,34 @@
1
+ import { type JobClaimLock } from "./claimLock";
2
+ import type { JobDocument } from "./modelTypes";
3
+ import type { JobDefinition } from "./types";
4
+ export interface JobExecutionHost {
5
+ getDefinition(name: string): JobDefinition | undefined;
6
+ getLockTtlMs(): number;
7
+ }
8
+ export type ExecuteJobOutcome = {
9
+ job: JobDocument;
10
+ kind: "executed";
11
+ } | {
12
+ job: JobDocument;
13
+ kind: "noop";
14
+ } | {
15
+ kind: "conflict";
16
+ reason: "locked";
17
+ } | {
18
+ kind: "conflict";
19
+ reason: "not_due";
20
+ runAt: Date;
21
+ } | {
22
+ kind: "not_found";
23
+ };
24
+ export declare const runClaimedJob: ({ claim, host, job, signal, }: {
25
+ claim: JobClaimLock;
26
+ host: JobExecutionHost;
27
+ job: JobDocument;
28
+ signal: AbortSignal;
29
+ }) => Promise<JobDocument>;
30
+ export declare const executeJobById: ({ host, jobId, signal, }: {
31
+ host: JobExecutionHost;
32
+ jobId: string;
33
+ signal: AbortSignal;
34
+ }) => Promise<ExecuteJobOutcome>;