@10x-media/jobs 0.1.0-beta.0 → 0.1.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/README.md +13 -10
- package/dist/exports/types.d.ts +1 -1
- package/dist/{index-CYsbNe4q.d.ts → index-LgqeiXr2.d.ts} +58 -32
- package/dist/index.d.ts +1 -1
- package/dist/index.js +251 -105
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# @10x-media/jobs
|
|
2
2
|
|
|
3
|
+
## 0.1.0-beta.2
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Fix a batch of functional and security issues found in the jobs plugin review:
|
|
8
|
+
|
|
9
|
+
- Sweeper processes jobs oldest-first via `sort: 'updatedAt'` (item 5)
|
|
10
|
+
- `acquireOrSteal` treats `leaseExpiresAt: null` as stealable, preventing dead-lock on first-boot rows (item 6)
|
|
11
|
+
- `start()` is a no-op when a drain is already in progress, preventing loop restart during shutdown (item 7)
|
|
12
|
+
- Signal handler exits with code 1 on drain timeout, 0 on clean drain (item 8)
|
|
13
|
+
- `runControlEndpoint` returns 400 for non-finite `?limit=` values (item 9)
|
|
14
|
+
- Drain loop checks the deadline after each poll sleep to avoid overrunning the budget (item 10)
|
|
15
|
+
- Leadership is released immediately after stopping loops, before the poll-wait phase (item 11)
|
|
16
|
+
- Cron secret comparison uses `crypto.timingSafeEqual` to prevent timing attacks (item 12)
|
|
17
|
+
- `applyResume` / `PauseStore.resume` accept `{ all: true }` to reset both global and per-queue pause state (item 13)
|
|
18
|
+
- `stop()` removed from the public `Worker` type; accessible via `WorkerTestHandle` cast for tests (item 14)
|
|
19
|
+
- KV-stored pause state is validated on read; corrupt or missing values fall back to empty state (item 16)
|
|
20
|
+
- `config.jobs.access.run` is composed with the plugin's built-in checker (both must pass) instead of replacing it; the same composed checker also guards the plugin's own `/queue-run` and `/queue-sweep` endpoints, so a stricter `jobs.access.run` cannot be bypassed through them (item 17)
|
|
21
|
+
- `LeaseStore.release` returns `{ ok: boolean }`; `leaderController` drops local leading state after any `release()`, since an unconfirmed release means the node no longer owns the lease (item 18)
|
|
22
|
+
- `renew` filter includes `leaseExpiresAt >= now`; on failed renew while leading, the controller falls through to `acquireOrSteal` with a fence bump (item 19)
|
|
23
|
+
- `createWorker` throws when signal handlers are already installed, enforcing the one-worker-per-process constraint (item 21)
|
|
24
|
+
- `createWorker` defaults `pauseStore` to `createPauseStore(payload)`, eliminating the footgun where preset-enabled queue control was silently ignored (item 22)
|
|
25
|
+
- `sweepCycle` re-ticks the sweeper leadership before acting so the check is always fresh (item 23)
|
|
26
|
+
- `stampClaim` guards against double-claiming: a second owner cannot claim a job already held by a different node (item 24)
|
|
27
|
+
- `/queue-status` reports the seven canonical job states (`queued`, `scheduled`, `retrying`, `processing`, `succeeded`, `failed`, `cancelled`) plus an orthogonal `recovered` count (`recoveryAttempts > 0`, when reliability is enabled) (item 25, breaking change)
|
|
28
|
+
- In-flight job count is now process-local (incremented/decremented in `withHeartbeat`) instead of a DB query; on drain, `requeueStragglers` runs only when the wall-clock budget is exceeded, so a just-completed job is never spuriously requeued (genuinely orphaned claims are recovered by the sweeper) (item 26)
|
|
29
|
+
|
|
30
|
+
## 0.1.0-beta.1
|
|
31
|
+
|
|
32
|
+
### Minor Changes
|
|
33
|
+
|
|
34
|
+
- Opt-in layers accept `true`: pass `reliability: true` or `queueControl: true` to enable a layer with its defaults, matching Payload's `false`/`true`/object option form. Empty objects and tuned objects still work.
|
|
35
|
+
|
|
3
36
|
## 0.1.0-beta.0
|
|
4
37
|
|
|
5
38
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -38,8 +38,8 @@ export default buildConfig({
|
|
|
38
38
|
| Option | Type | Default | Description |
|
|
39
39
|
|---|---|---|---|
|
|
40
40
|
| `disabled` | `boolean` | `false` | When `true`, returns the incoming config unchanged. Useful for toggling the plugin per environment. |
|
|
41
|
-
| `reliability` | `ReliabilityOptions \|
|
|
42
|
-
| `queueControl` | `QueueControlOptions \|
|
|
41
|
+
| `reliability` | `ReliabilityOptions \| boolean` | off | Job leases, the orphan sweeper, leader election, and serverless staleness. Opt in with `true` (defaults) or a tuned object. |
|
|
42
|
+
| `queueControl` | `QueueControlOptions \| boolean` | off | Cluster-wide pause/resume, hardened run/sweep/status endpoints, and access guards. Opt in with `true` (defaults) or a tuned object. |
|
|
43
43
|
|
|
44
44
|
<!-- Add new options to this table as you build them. -->
|
|
45
45
|
|
|
@@ -52,9 +52,9 @@ The plugin ships four opt-in layers. You add only the ones your deployment needs
|
|
|
52
52
|
| Layer | What it adds | How to enable |
|
|
53
53
|
|---|---|---|
|
|
54
54
|
| Observability | The jobs ops dashboard (status, queue health, error and log panels) and i18n. | Always on (just adding `jobs()`). |
|
|
55
|
-
| Reliability | Job leases, an orphan sweeper, leader election, serverless staleness. | `reliability:
|
|
55
|
+
| Reliability | Job leases, an orphan sweeper, leader election, serverless staleness. | `reliability: true` (or a tuned `ReliabilityOptions`). |
|
|
56
56
|
| Execution | A standalone worker (`createWorker`) that runs jobs everywhere and schedules/sweeps only while holding the leader lease, with a graceful SIGTERM drain. | Run the worker entrypoint as its own process. |
|
|
57
|
-
| Queue control | Cluster-wide pause/resume plus hardened `/api/payload-jobs/queue-run`, `/queue-sweep`, and `/queue-status` endpoints with access guards. | `queueControl:
|
|
57
|
+
| Queue control | Cluster-wide pause/resume plus hardened `/api/payload-jobs/queue-run`, `/queue-sweep`, and `/queue-status` endpoints with access guards. | `queueControl: true` (or a tuned `QueueControlOptions`). |
|
|
58
58
|
|
|
59
59
|
Every layer is opt-in. The observability dashboard is always present once the plugin is installed. The other three you turn on as your topology demands.
|
|
60
60
|
|
|
@@ -64,7 +64,7 @@ Three facts shape every topology below.
|
|
|
64
64
|
|
|
65
65
|
2. **The worker is a separate process, not your web server.** The execution layer (`createWorker`) is meant to run as its own long-lived process (a worker container, a separate Vercel-incompatible service). Your Next.js / Payload web server handles HTTP. The worker boots its own Payload instance against the same database and owns the run/schedule/sweep loops. The only topology that does not run a worker process is serverless, which drives everything from cron-hit endpoints instead.
|
|
66
66
|
|
|
67
|
-
3. **Completed jobs are deleted, not kept.** Payload's `jobs.deleteJobOnComplete` defaults to `true` in v3.85, so a job that finishes successfully is removed from the queue.
|
|
67
|
+
3. **Completed jobs are deleted, not kept.** Payload's `jobs.deleteJobOnComplete` defaults to `true` in v3.85, so a job that finishes successfully is removed from the queue. With the default, the dashboard and `/queue-status` counts reflect the live states (`queued`, `scheduled`, `retrying`, `processing`, `failed`, `cancelled`), since succeeded jobs are gone. Set `jobs.deleteJobOnComplete: false` in `buildConfig` to keep completed jobs for auditing; the `succeeded` count then reflects them.
|
|
68
68
|
|
|
69
69
|
Pick a preset:
|
|
70
70
|
|
|
@@ -132,6 +132,8 @@ console.log(JSON.stringify({ crons: vercelCrons() }, null, 2))
|
|
|
132
132
|
- `/api/payload-jobs/queue-run` runs due jobs (pause-aware, mirrors the native run params). `?allQueues=true` runs every queue, `?queue=<name>` runs one, `?limit=<n>` caps jobs per invocation, `?disableScheduling=true` skips schedule handling.
|
|
133
133
|
- `/api/payload-jobs/queue-sweep` runs one orphan sweep (a single cron invocation, so no leader election). Requires reliability to be enabled.
|
|
134
134
|
|
|
135
|
+
**CSRF note.** Both `queue-run` and `queue-sweep` are state-mutating operations served over GET. A crafted `<img>` or link in a document opened by a logged-in admin can trigger them silently (CSRF). The serverless preset uses Vercel Cron, which sends GET requests only, so switching to POST is not feasible without breaking the Vercel cron flow. For deployments where browser sessions are involved, override `access` to require an `Authorization: Bearer` token (`cronSecretAccess`) rather than relying on the session cookie (`loggedInAccess`).
|
|
136
|
+
|
|
135
137
|
**Vercel limits.** Match your plan to a cron cadence and a function duration:
|
|
136
138
|
|
|
137
139
|
- **Hobby**: crons run at most **once per day** and functions cap at **300s**. That is unusable for real job processing. Use Hobby only for a toy or a demo.
|
|
@@ -234,7 +236,7 @@ Set `JOBS_SCHEDULER=1` on exactly one replica (or run a single dedicated schedul
|
|
|
234
236
|
|
|
235
237
|
**Graceful shutdown is a hard requirement under multi-node.** When an orchestrator rolls or scales down a replica, it sends SIGTERM, then SIGKILLs after a grace period. The worker's drain requeues its in-flight job (so another replica picks it up) and releases its leases, but only if it is given time to finish.
|
|
236
238
|
|
|
237
|
-
- The orchestrator grace period
|
|
239
|
+
- The orchestrator grace period must be set to `drainTimeoutMs + pollIntervalMs + 5s` to be safe. In Docker Compose set `stop_grace_period`; in Kubernetes set `terminationGracePeriodSeconds`. The actual shutdown time is `drainTimeoutMs` plus up to one `pollIntervalMs` (drain loop overrun) plus the `releaseLeadership` DB roundtrip plus `payload.destroy()` latency, which can be significant if the DB connection pool is busy. If the grace period is shorter, the orchestrator SIGKILLs a still-draining worker and you lose the clean requeue.
|
|
238
240
|
- The container `CMD` must be **exec form** (`CMD ["node", "dist/worker.js"]`, not `CMD node dist/worker.js`). Shell form runs Node as a child of `/bin/sh`, which does not forward SIGTERM, so the worker never drains and is hard-killed every time.
|
|
239
241
|
|
|
240
242
|
```yaml
|
|
@@ -242,8 +244,8 @@ services:
|
|
|
242
244
|
worker:
|
|
243
245
|
build: .
|
|
244
246
|
command: ['node', 'dist/worker.js'] # exec form: Node receives SIGTERM
|
|
245
|
-
#
|
|
246
|
-
stop_grace_period:
|
|
247
|
+
# drainTimeoutMs (30s) + pollIntervalMs (0.5s) + 5s buffer = 36s; round up to 40s.
|
|
248
|
+
stop_grace_period: 40s
|
|
247
249
|
deploy:
|
|
248
250
|
replicas: 3
|
|
249
251
|
environment:
|
|
@@ -252,7 +254,7 @@ services:
|
|
|
252
254
|
depends_on: [db]
|
|
253
255
|
```
|
|
254
256
|
|
|
255
|
-
The Kubernetes equivalent: an exec-form `command` in the pod spec and `terminationGracePeriodSeconds:
|
|
257
|
+
The Kubernetes equivalent: an exec-form `command` in the pod spec and `terminationGracePeriodSeconds: 40` (`drainTimeoutMs + pollIntervalMs + 5s` buffer).
|
|
256
258
|
|
|
257
259
|
### The worker entrypoint
|
|
258
260
|
|
|
@@ -296,7 +298,8 @@ Notes:
|
|
|
296
298
|
|
|
297
299
|
- `resolveReliabilityOptions` fully defaults your `ReliabilityOptions`. It returns `null` when reliability is off (passed `false` or `undefined`), which the worker cannot run with, hence the guard.
|
|
298
300
|
- Pass the same reliability tuning you give the plugin (share a constant between `payload.config.ts` and `worker.ts`) so the lease TTLs match across the cluster.
|
|
299
|
-
- `createWorker` registers SIGTERM and SIGINT handlers automatically (`installSignals` defaults to `true`). On signal it drains in-flight jobs (within `drainTimeoutMs`), requeues any straggler, releases leases, destroys the Payload instance, and exits 0. Keep your orchestrator grace period
|
|
301
|
+
- `createWorker` registers SIGTERM and SIGINT handlers automatically (`installSignals` defaults to `true`). On signal it drains in-flight jobs (within `drainTimeoutMs`), requeues any straggler, releases leases, destroys the Payload instance, and exits **0** on clean drain or **1** if the drain timed out (jobs were requeued). Keep your orchestrator grace period at `drainTimeoutMs + pollIntervalMs + 5s` (see Multi-node above).
|
|
302
|
+
- Only one worker with `installSignals: true` may exist per process. Creating a second one throws. Use `installSignals: false` for additional workers in the same process (e.g. test helpers).
|
|
300
303
|
- Run it with `node --import tsx worker.ts` in development, or compile it and run `node dist/worker.js` in production.
|
|
301
304
|
|
|
302
305
|
### CI-optional e2e recipes
|
package/dist/exports/types.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Q as JobsPluginOptions, Z as JobsOptions } from "../index-
|
|
1
|
+
import { Q as JobsPluginOptions, Z as JobsOptions } from "../index-LgqeiXr2.js";
|
|
2
2
|
export type { JobsOptions, JobsPluginOptions, JobsPluginOptions as PluginOptions };
|
|
@@ -36,7 +36,11 @@ type QueueControlOptions = {
|
|
|
36
36
|
type ReliabilityOptions = {
|
|
37
37
|
/** How long a worker's claim is valid before the sweeper may reclaim it. Default 300000 (5 min). */jobLeaseTtlMs?: number; /** How often a running worker renews its job lease. Default jobLeaseTtlMs / 3. */
|
|
38
38
|
heartbeatIntervalMs?: number; /** How often the sweeper scans for orphaned jobs. Default 60000. */
|
|
39
|
-
sweepIntervalMs?: number;
|
|
39
|
+
sweepIntervalMs?: number;
|
|
40
|
+
/**
|
|
41
|
+
* How many times the sweeper requeues a job before dead-lettering it. Default 3.
|
|
42
|
+
* Number of sweeper requeues after the original attempt; total executions = maxRecoveries + 1.
|
|
43
|
+
*/
|
|
40
44
|
maxRecoveries?: number; /** How long a leadership lease (scheduler/sweeper) is valid. Default 30000. */
|
|
41
45
|
leaderLeaseTtlMs?: number; /** A stable id for this node/process. Defaults to a generated value at runtime. */
|
|
42
46
|
leaderId?: string;
|
|
@@ -49,8 +53,8 @@ type ReliabilityOptions = {
|
|
|
49
53
|
maxDurationMs: number;
|
|
50
54
|
};
|
|
51
55
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
56
|
+
* Throws at plugin registration when set without `jobs.enableConcurrencyControl: true`.
|
|
57
|
+
* Requires Payload's `enableConcurrencyControl` for app-level mutual exclusion under multi-node.
|
|
54
58
|
*/
|
|
55
59
|
requireConcurrencyControl?: boolean;
|
|
56
60
|
};
|
|
@@ -66,7 +70,7 @@ type ResolvedReliabilityOptions = {
|
|
|
66
70
|
requireConcurrencyControl: boolean;
|
|
67
71
|
};
|
|
68
72
|
/** Resolve user reliability options to a fully-defaulted object, or `null` when disabled. */
|
|
69
|
-
declare const resolveReliabilityOptions: (options: ReliabilityOptions |
|
|
73
|
+
declare const resolveReliabilityOptions: (options: ReliabilityOptions | boolean | undefined) => ResolvedReliabilityOptions | null;
|
|
70
74
|
//#endregion
|
|
71
75
|
//#region src/options.d.ts
|
|
72
76
|
/** Improvements applied to Payload's built-in `payload-jobs` collection. */
|
|
@@ -104,11 +108,16 @@ type JobsPluginOptions = JobsOptions & {
|
|
|
104
108
|
/** Disable the plugin entirely (incoming config returned untouched). */disabled?: boolean;
|
|
105
109
|
/**
|
|
106
110
|
* Reliability layer: stuck-job recovery, a heartbeat lease, and multi-node
|
|
107
|
-
* leader election.
|
|
108
|
-
* and a `payload-jobs-locks`
|
|
111
|
+
* leader election. Off by default; pass `true` for defaults or an object to
|
|
112
|
+
* tune it. It adds fields to `payload-jobs` and a `payload-jobs-locks`
|
|
113
|
+
* collection, so adopters run one `migrate:create`.
|
|
114
|
+
*/
|
|
115
|
+
reliability?: boolean | ReliabilityOptions;
|
|
116
|
+
/**
|
|
117
|
+
* Queue control: pause/resume, a status endpoint, and a hardened run endpoint.
|
|
118
|
+
* Off by default; pass `true` for defaults or an object to tune it.
|
|
109
119
|
*/
|
|
110
|
-
|
|
111
|
-
queueControl?: false | QueueControlOptions;
|
|
120
|
+
queueControl?: boolean | QueueControlOptions;
|
|
112
121
|
};
|
|
113
122
|
//#endregion
|
|
114
123
|
//#region src/execution/autoRunConfig.d.ts
|
|
@@ -185,15 +194,16 @@ type PauseState = {
|
|
|
185
194
|
/** A durable, cluster-wide pause store backed by `payload.kv`. */
|
|
186
195
|
type PauseStore = {
|
|
187
196
|
pause: (queue?: string) => Promise<void>;
|
|
188
|
-
|
|
197
|
+
/**
|
|
198
|
+
* Resume a named queue, clear the global flag, or reset everything.
|
|
199
|
+
* Pass `{ all: true }` to reset both layers at once (equivalent to `emptyPauseState()`).
|
|
200
|
+
*/
|
|
201
|
+
resume: (queueOrOpts?: string | {
|
|
202
|
+
all: true;
|
|
203
|
+
}) => Promise<void>;
|
|
189
204
|
getState: () => Promise<PauseState>;
|
|
190
205
|
isPaused: (queue: string) => Promise<boolean>;
|
|
191
206
|
};
|
|
192
|
-
/**
|
|
193
|
-
* Build the pause store over `payload.kv` (always available, durable, cluster-wide).
|
|
194
|
-
* Pause and resume read-modify-write the single state value; this is last-writer-wins
|
|
195
|
-
* (kv has no atomic compare-and-set), which is acceptable for rare admin actions.
|
|
196
|
-
*/
|
|
197
207
|
declare const createPauseStore: (payload: Payload) => PauseStore;
|
|
198
208
|
//#endregion
|
|
199
209
|
//#region src/reliability/locksCollection.d.ts
|
|
@@ -227,8 +237,7 @@ type Worker = {
|
|
|
227
237
|
* Gracefully drain and shut down (removes signal handlers, stops loops, requeues,
|
|
228
238
|
* releases, destroys). Idempotent: repeated calls return the same in-flight drain.
|
|
229
239
|
*/
|
|
230
|
-
drain: () => Promise<DrainResult>; /**
|
|
231
|
-
stop: () => void; /** Whether this node currently holds the given leadership role. */
|
|
240
|
+
drain: () => Promise<DrainResult>; /** Whether this node currently holds the given leadership role. */
|
|
232
241
|
isLeader: (role: LeaderRole) => boolean;
|
|
233
242
|
};
|
|
234
243
|
/**
|
|
@@ -307,36 +316,51 @@ declare const vercelCrons: (options?: {
|
|
|
307
316
|
}) => VercelCron[];
|
|
308
317
|
//#endregion
|
|
309
318
|
//#region src/queueControl/queueHealth.d.ts
|
|
310
|
-
/** Per-queue health
|
|
319
|
+
/** Per-queue health: the seven canonical job states plus the orthogonal recovered count. */
|
|
311
320
|
type QueueHealth = {
|
|
312
|
-
queue: string;
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
321
|
+
queue: string; /** Jobs waiting to run (no prior attempts, no future schedule). */
|
|
322
|
+
queued: number; /** Jobs scheduled in the future (`waitUntil > now`). */
|
|
323
|
+
scheduled: number; /** Jobs being retried after at least one failure. */
|
|
324
|
+
retrying: number; /** Jobs currently executing. */
|
|
325
|
+
processing: number; /** Jobs that completed successfully. */
|
|
326
|
+
succeeded: number; /** Jobs that completed with an unrecoverable error. */
|
|
327
|
+
failed: number; /** Jobs cancelled by the application. */
|
|
328
|
+
cancelled: number;
|
|
329
|
+
/**
|
|
330
|
+
* Jobs recovered at least once (`recoveryAttempts > 0`). Orthogonal to the seven states
|
|
331
|
+
* above: a recovered job may currently be retrying, succeeded, or failed. 0 unless
|
|
332
|
+
* reliability is enabled and `includeRecovered` is set.
|
|
333
|
+
*/
|
|
316
334
|
recovered: number;
|
|
317
335
|
lastScheduledRun: string | null;
|
|
318
336
|
};
|
|
319
337
|
type QueueHealthReport = {
|
|
320
338
|
totals: {
|
|
321
|
-
|
|
339
|
+
queued: number;
|
|
340
|
+
scheduled: number;
|
|
341
|
+
retrying: number;
|
|
322
342
|
processing: number;
|
|
343
|
+
succeeded: number;
|
|
323
344
|
failed: number;
|
|
345
|
+
cancelled: number;
|
|
324
346
|
recovered: number;
|
|
325
347
|
};
|
|
326
|
-
|
|
348
|
+
oldestQueuedAgeMs: number | null;
|
|
327
349
|
queues: QueueHealth[];
|
|
328
350
|
};
|
|
329
351
|
type GetQueueHealthOptions = {
|
|
330
352
|
/** Queues to break out per-queue. Default ['default']. */queues?: string[]; /** Include the recovered count (requires the reliability `recoveryAttempts` field). */
|
|
331
|
-
includeRecovered?: boolean; /** Reference time for
|
|
353
|
+
includeRecovered?: boolean; /** Reference time for age and scheduled comparisons. Default now. */
|
|
332
354
|
now?: Date;
|
|
333
355
|
};
|
|
334
356
|
/**
|
|
335
|
-
* Aggregate queue health via `payload.count
|
|
336
|
-
*
|
|
337
|
-
*
|
|
338
|
-
*
|
|
339
|
-
*
|
|
357
|
+
* Aggregate queue health via `payload.count`: the seven canonical states
|
|
358
|
+
* (queued, scheduled, retrying, processing, succeeded, failed, cancelled) plus an
|
|
359
|
+
* orthogonal `recovered` count (recoveryAttempts > 0) when `includeRecovered` is set.
|
|
360
|
+
* Reuses `statusWhere` from `deriveJobStatus` so the predicates are consistent
|
|
361
|
+
* with what the UI and individual job reads report. The stats global is read
|
|
362
|
+
* through `payload.db.findGlobal` inside a try/catch because that call throws
|
|
363
|
+
* when the global does not exist (no schedule has run yet).
|
|
340
364
|
*/
|
|
341
365
|
declare const getQueueHealth: (payload: Payload, options?: GetQueueHealthOptions) => Promise<QueueHealthReport>;
|
|
342
366
|
//#endregion
|
|
@@ -448,8 +472,10 @@ interface LeaseStore {
|
|
|
448
472
|
acquireOrSteal: (role: LeaderRole, owner: string, ttlMs: number, now: Date) => Promise<LeaseResult>;
|
|
449
473
|
/** Renew `role` if `owner` still holds it at `now`. Does not bump the fence token. */
|
|
450
474
|
renew: (role: LeaderRole, owner: string, ttlMs: number, now: Date) => Promise<LeaseResult>;
|
|
451
|
-
/** Release `role` if `owner` holds it (graceful handoff: clears owner and expiry). */
|
|
452
|
-
release: (role: LeaderRole, owner: string) => Promise<
|
|
475
|
+
/** Release `role` if `owner` holds it (graceful handoff: clears owner and expiry). Returns ok:false if the row did not match. */
|
|
476
|
+
release: (role: LeaderRole, owner: string) => Promise<{
|
|
477
|
+
ok: boolean;
|
|
478
|
+
}>;
|
|
453
479
|
/** Read the current lease row (diagnostics and tests). */
|
|
454
480
|
read: (role: LeaderRole) => Promise<LeaseRecord | null>;
|
|
455
481
|
}
|
|
@@ -527,4 +553,4 @@ declare module 'payload' {
|
|
|
527
553
|
declare const jobs: (options: JobsPluginOptions) => import("payload").Plugin;
|
|
528
554
|
//#endregion
|
|
529
555
|
export { ReliabilityOptions as $, singleNodePreset as A, LeaderRole as B, QueueHealth as C, VercelCron as D, TopologyPreset as E, CreateWorkerArgs as F, DrainOptions as G, createPauseStore as H, Worker as I, AutoRunConfigOptions as J, DrainResult as K, createWorker as L, JobStatus as M, JobStatusInput as N, multiNodePreset as O, deriveJobStatus as P, JobsPluginOptions as Q, JOBS_LOCKS_SLUG as R, GetQueueHealthOptions as S, getQueueHealth as T, PauseState as U, PauseStore as V, DrainDeps as W, autoRunConfig as X, AutoRunQueueConfig as Y, JobsOptions as Z, JobLeaseStore as _, RecoveryDecision as a, loggedInAccess as at, IdempotencyStore as b, createLeaderController as c, LeaseStore as d, ResolvedReliabilityOptions as et, createLeaseStore as f, JobLeaseRow as g, JobLeaseResult as h, runSweep as i, cronSecretAccess as it, vercelCrons as j, serverlessPreset as k, LeaseRecord as l, JobId as m, RunSweepArgs as n, QueueControlOptions as nt, decideRecovery as o, DeadLetterArgs as p, drainWorker as q, SweepResult as r, JobAccess as rt, LeaderController as s, jobs as t, resolveReliabilityOptions as tt, LeaseResult as u, StampResult as v, QueueHealthReport as w, withIdempotencyKey as x, createJobLeaseStore as y, LEADER_ROLES as z };
|
|
530
|
-
//# sourceMappingURL=index-
|
|
556
|
+
//# sourceMappingURL=index-LgqeiXr2.d.ts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as ReliabilityOptions, A as singleNodePreset, B as LeaderRole, C as QueueHealth, D as VercelCron, E as TopologyPreset, F as CreateWorkerArgs, G as DrainOptions, H as createPauseStore, I as Worker, J as AutoRunConfigOptions, K as DrainResult, L as createWorker, M as JobStatus, N as JobStatusInput, O as multiNodePreset, P as deriveJobStatus, Q as JobsPluginOptions, R as JOBS_LOCKS_SLUG, S as GetQueueHealthOptions, T as getQueueHealth, U as PauseState, V as PauseStore, W as DrainDeps, X as autoRunConfig, Y as AutoRunQueueConfig, Z as JobsOptions, _ as JobLeaseStore, a as RecoveryDecision, at as loggedInAccess, b as IdempotencyStore, c as createLeaderController, d as LeaseStore, et as ResolvedReliabilityOptions, f as createLeaseStore, g as JobLeaseRow, h as JobLeaseResult, i as runSweep, it as cronSecretAccess, j as vercelCrons, k as serverlessPreset, l as LeaseRecord, m as JobId, n as RunSweepArgs, nt as QueueControlOptions, o as decideRecovery, p as DeadLetterArgs, q as drainWorker, r as SweepResult, rt as JobAccess, s as LeaderController, t as jobs, tt as resolveReliabilityOptions, u as LeaseResult, v as StampResult, w as QueueHealthReport, x as withIdempotencyKey, y as createJobLeaseStore, z as LEADER_ROLES } from "./index-
|
|
1
|
+
import { $ as ReliabilityOptions, A as singleNodePreset, B as LeaderRole, C as QueueHealth, D as VercelCron, E as TopologyPreset, F as CreateWorkerArgs, G as DrainOptions, H as createPauseStore, I as Worker, J as AutoRunConfigOptions, K as DrainResult, L as createWorker, M as JobStatus, N as JobStatusInput, O as multiNodePreset, P as deriveJobStatus, Q as JobsPluginOptions, R as JOBS_LOCKS_SLUG, S as GetQueueHealthOptions, T as getQueueHealth, U as PauseState, V as PauseStore, W as DrainDeps, X as autoRunConfig, Y as AutoRunQueueConfig, Z as JobsOptions, _ as JobLeaseStore, a as RecoveryDecision, at as loggedInAccess, b as IdempotencyStore, c as createLeaderController, d as LeaseStore, et as ResolvedReliabilityOptions, f as createLeaseStore, g as JobLeaseRow, h as JobLeaseResult, i as runSweep, it as cronSecretAccess, j as vercelCrons, k as serverlessPreset, l as LeaseRecord, m as JobId, n as RunSweepArgs, nt as QueueControlOptions, o as decideRecovery, p as DeadLetterArgs, q as drainWorker, r as SweepResult, rt as JobAccess, s as LeaderController, t as jobs, tt as resolveReliabilityOptions, u as LeaseResult, v as StampResult, w as QueueHealthReport, x as withIdempotencyKey, y as createJobLeaseStore, z as LEADER_ROLES } from "./index-LgqeiXr2.js";
|
|
2
2
|
export { type AutoRunConfigOptions, type AutoRunQueueConfig, type CreateWorkerArgs, type DeadLetterArgs, type DrainDeps, type DrainOptions, type DrainResult, type GetQueueHealthOptions, type IdempotencyStore, JOBS_LOCKS_SLUG, type JobAccess, type JobId, type JobLeaseResult, type JobLeaseRow, type JobLeaseStore, type JobStatus, type JobStatusInput, type JobsOptions, type JobsPluginOptions, type JobsPluginOptions as PluginOptions, LEADER_ROLES, type LeaderController, type LeaderRole, type LeaseRecord, type LeaseResult, type LeaseStore, type PauseState, type PauseStore, type QueueControlOptions, type QueueHealth, type QueueHealthReport, type RecoveryDecision, type ReliabilityOptions, type ResolvedReliabilityOptions, type RunSweepArgs, type StampResult, type SweepResult, type TopologyPreset, type VercelCron, type Worker, autoRunConfig, createJobLeaseStore, createLeaderController, createLeaseStore, createPauseStore, createWorker, cronSecretAccess, decideRecovery, deriveJobStatus, drainWorker, getQueueHealth, jobs, loggedInAccess, multiNodePreset, resolveReliabilityOptions, runSweep, serverlessPreset, singleNodePreset, vercelCrons, withIdempotencyKey };
|