@10x-media/jobs 0.1.0-beta.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.
@@ -0,0 +1,530 @@
1
+ import { JobsConfig, Payload, PayloadComponent, PayloadRequest } from "payload";
2
+
3
+ //#region src/plugin/resolve.d.ts
4
+ /**
5
+ * A customization point: pass a value to replace our default, or a function to
6
+ * transform it. The function form receives the default so callers can compose
7
+ * (extend, filter, reorder) instead of rewriting from scratch.
8
+ */
9
+ type Override<T> = ((defaults: T) => T) | T;
10
+ //#endregion
11
+ //#region src/queueControl/access.d.ts
12
+ /** A jobs access checker (matches Payload's `jobs.access.run` shape). */
13
+ type JobAccess = (args: {
14
+ req: PayloadRequest;
15
+ }) => boolean | Promise<boolean>;
16
+ type CronSecretAccessOptions = {
17
+ /** Env var holding the shared secret. Default `CRON_SECRET`. */envVar?: string;
18
+ };
19
+ /** The default endpoint guard: logged-in users only (safer than Payload's open default). */
20
+ declare const loggedInAccess: JobAccess;
21
+ /**
22
+ * An access checker for serverless cron triggers: a logged-in user passes, otherwise
23
+ * the request must carry `Authorization: Bearer ${process.env[envVar]}`. Payload ships
24
+ * no built-in secret check, so this implements the canonical Vercel-cron pattern.
25
+ */
26
+ declare const cronSecretAccess: (options?: CronSecretAccessOptions) => JobAccess;
27
+ //#endregion
28
+ //#region src/queueControl/options.d.ts
29
+ type QueueControlOptions = {
30
+ /** Gate the queue-control endpoints (and the native run endpoint). Default: logged-in users only. */access?: JobAccess; /** Queues to report per-queue health for. Default ['default']. */
31
+ queues?: string[];
32
+ };
33
+ //#endregion
34
+ //#region src/reliability/options.d.ts
35
+ /** Tuning for the jobs reliability layer. All durations are milliseconds. */
36
+ type ReliabilityOptions = {
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
+ heartbeatIntervalMs?: number; /** How often the sweeper scans for orphaned jobs. Default 60000. */
39
+ sweepIntervalMs?: number; /** How many times the sweeper requeues a job before dead-lettering it. Default 3. */
40
+ maxRecoveries?: number; /** How long a leadership lease (scheduler/sweeper) is valid. Default 30000. */
41
+ leaderLeaseTtlMs?: number; /** A stable id for this node/process. Defaults to a generated value at runtime. */
42
+ leaderId?: string;
43
+ /**
44
+ * Serverless mode: when set, job staleness derives from this platform hard-kill
45
+ * duration instead of a heartbeat (heartbeats are meaningless when the function
46
+ * is killed at maxDuration with no SIGTERM).
47
+ */
48
+ serverless?: {
49
+ maxDurationMs: number;
50
+ };
51
+ /**
52
+ * Recommend (true) Payload's `enableConcurrencyControl` for app-level mutual
53
+ * exclusion under multi-node. Documentation-facing; consumed in a later plan.
54
+ */
55
+ requireConcurrencyControl?: boolean;
56
+ };
57
+ /** Reliability options with every value resolved. `null` means reliability is off. */
58
+ type ResolvedReliabilityOptions = {
59
+ jobLeaseTtlMs: number;
60
+ heartbeatIntervalMs: number;
61
+ sweepIntervalMs: number;
62
+ maxRecoveries: number;
63
+ leaderLeaseTtlMs: number;
64
+ leaderId: string | null;
65
+ serverlessMaxDurationMs: number | null;
66
+ requireConcurrencyControl: boolean;
67
+ };
68
+ /** Resolve user reliability options to a fully-defaulted object, or `null` when disabled. */
69
+ declare const resolveReliabilityOptions: (options: ReliabilityOptions | false | undefined) => ResolvedReliabilityOptions | null;
70
+ //#endregion
71
+ //#region src/options.d.ts
72
+ /** Improvements applied to Payload's built-in `payload-jobs` collection. */
73
+ type JobsOptions = {
74
+ /** Show the jobs collection in the admin. Defaults to visible (un-hidden). */hidden?: boolean; /** List columns for the jobs collection; replace or transform our defaults. */
75
+ defaultColumns?: Override<string[]>;
76
+ /**
77
+ * Treat an existing job as a read-only record (default `true`): execution-state
78
+ * fields are surfaced in the header and locked, inputs are editable only on
79
+ * Create. Set `false` to leave every field editable. Never disables Create.
80
+ */
81
+ readOnlyRecord?: boolean;
82
+ /**
83
+ * Per-field list-cell overrides, keyed by job field name. `false` keeps
84
+ * Payload's default cell; a component replaces it.
85
+ */
86
+ cells?: Record<string, PayloadComponent | false>; /** The derived Status column. `false` removes it; a component replaces our status cell. */
87
+ status?: PayloadComponent | false;
88
+ /**
89
+ * Components rendered between the search bar and the table. `false` removes our
90
+ * queue-health bar; an array replaces it.
91
+ */
92
+ beforeListTable?: PayloadComponent[] | false;
93
+ /**
94
+ * Per-status cap for the queue-health bar: counts above it render as `${cap}+`.
95
+ * Defaults to 100; `false` shows the exact count.
96
+ */
97
+ healthBarCap?: false | number;
98
+ };
99
+ /**
100
+ * Options for the jobs plugin. Improves the built-in `payload-jobs` collection;
101
+ * set `disabled` to leave the incoming config untouched.
102
+ */
103
+ type JobsPluginOptions = JobsOptions & {
104
+ /** Disable the plugin entirely (incoming config returned untouched). */disabled?: boolean;
105
+ /**
106
+ * Reliability layer: stuck-job recovery, a heartbeat lease, and multi-node
107
+ * leader election. Opt-in (default off) because it adds fields to `payload-jobs`
108
+ * and a `payload-jobs-locks` collection, so adopters run one `migrate:create`.
109
+ */
110
+ reliability?: false | ReliabilityOptions; /** Queue-control: pause/resume, a status endpoint, and a hardened run endpoint. Default off. */
111
+ queueControl?: false | QueueControlOptions;
112
+ };
113
+ //#endregion
114
+ //#region src/execution/autoRunConfig.d.ts
115
+ /**
116
+ * Payload's per-cron autoRun config. Payload 3.85.0 does not re-export the
117
+ * `AutorunCronConfig` type from its package root, so derive it from the array branch of
118
+ * the publicly exported `JobsConfig['autoRun']` (which Payload types as that element).
119
+ */
120
+ type AutorunCronConfig = Extract<NonNullable<JobsConfig['autoRun']>, unknown[]>[number];
121
+ /** One logical queue's autoRun cadence. */
122
+ type AutoRunQueueConfig = {
123
+ queue: string; /** Cron cadence for this queue. Default every minute. */
124
+ cron?: string; /** Max jobs claimed per tick. Default 10. */
125
+ limit?: number;
126
+ };
127
+ type AutoRunConfigOptions = {
128
+ /** One entry per logical queue. Default a single `default` queue. */queues?: AutoRunQueueConfig[]; /** Suppress per-run info logging. Default true. */
129
+ silent?: boolean;
130
+ /**
131
+ * Disable native auto-scheduling on these crons. Default false. Set true when a
132
+ * `createWorker` owns scheduling (multi-node), so the cron only runs jobs.
133
+ */
134
+ disableScheduling?: boolean;
135
+ };
136
+ /**
137
+ * Build a production `jobs.autoRun` array: one Croner config per queue, silent by
138
+ * default, with Payload's own `protect: true` preventing overlap. This is the simple
139
+ * single-node and serverless-adjacent path where native autoRun safely handles both
140
+ * scheduling and running in one process. Multi-node deployments use `createWorker`
141
+ * instead, because native autoRun cannot gate scheduling to one elected leader (its
142
+ * only dynamic lever, `shouldAutoRun`, permanently stops the cron rather than pausing).
143
+ */
144
+ declare const autoRunConfig: (options?: AutoRunConfigOptions) => AutorunCronConfig[];
145
+ //#endregion
146
+ //#region src/execution/drain.d.ts
147
+ type DrainDeps = {
148
+ /** Stop the worker's interval loops (stop claiming new jobs). */stopLoops: () => void; /** Count this node's in-flight jobs (processing and claimed by it). */
149
+ countInFlight: () => Promise<number>; /** Requeue this node's remaining in-flight jobs. Returns how many were released. */
150
+ requeueStragglers: () => Promise<number>; /** Release the held scheduler and sweeper leadership leases. */
151
+ releaseLeadership: () => Promise<void>; /** Destroy the Payload instance (stops crons, closes the DB). */
152
+ destroy: () => Promise<void>; /** Wall-clock milliseconds (real in production, virtual in tests). */
153
+ now: () => number; /** Wait `ms` (real in production, virtual in tests). */
154
+ sleep: (ms: number) => Promise<void>;
155
+ logger?: {
156
+ info?: (m: string) => void;
157
+ };
158
+ };
159
+ type DrainOptions = {
160
+ /** Max wall-clock time to await in-flight jobs before requeuing stragglers. */drainTimeoutMs: number; /** How often to re-count in-flight jobs while draining. */
161
+ pollIntervalMs: number;
162
+ };
163
+ type DrainResult = {
164
+ inFlightAtStart: number;
165
+ remaining: number;
166
+ requeued: number;
167
+ timedOut: boolean;
168
+ };
169
+ /**
170
+ * Run the graceful-drain sequence: stop claiming, await this node's in-flight jobs up
171
+ * to a wall-clock budget, requeue any stragglers, release leadership, and destroy. The
172
+ * clock (`now`/`sleep`) is injected so tests drive it deterministically without real
173
+ * waiting. Always releases leadership and destroys, even when nothing was in flight.
174
+ */
175
+ declare const drainWorker: (deps: DrainDeps, options: DrainOptions) => Promise<DrainResult>;
176
+ //#endregion
177
+ //#region src/queueControl/pauseState.d.ts
178
+ /** Cluster-wide pause state: a global pause plus a set of paused queue names. */
179
+ type PauseState = {
180
+ global: boolean;
181
+ queues: string[];
182
+ };
183
+ //#endregion
184
+ //#region src/queueControl/pauseStore.d.ts
185
+ /** A durable, cluster-wide pause store backed by `payload.kv`. */
186
+ type PauseStore = {
187
+ pause: (queue?: string) => Promise<void>;
188
+ resume: (queue?: string) => Promise<void>;
189
+ getState: () => Promise<PauseState>;
190
+ isPaused: (queue: string) => Promise<boolean>;
191
+ };
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
+ declare const createPauseStore: (payload: Payload) => PauseStore;
198
+ //#endregion
199
+ //#region src/reliability/locksCollection.d.ts
200
+ /** Slug of the plugin-owned leases collection. Table name: payload_jobs_locks. */
201
+ declare const JOBS_LOCKS_SLUG = "payload-jobs-locks";
202
+ /** The two singleton leadership roles. */
203
+ declare const LEADER_ROLES: readonly ["scheduler", "sweeper"];
204
+ type LeaderRole = (typeof LEADER_ROLES)[number];
205
+ //#endregion
206
+ //#region src/execution/worker.d.ts
207
+ type CreateWorkerArgs = {
208
+ payload: Payload;
209
+ reliability: ResolvedReliabilityOptions; /** Queues to run. Omit (or empty) to run all queues. */
210
+ queues?: string[]; /** When provided, the run loop honors cluster-wide pause/resume. */
211
+ pauseStore?: PauseStore; /** How often this node claims and runs jobs. Default 2000. */
212
+ runIntervalMs?: number; /** How often leadership is advanced and scheduling runs (leader only). Default leaderLeaseTtlMs / 3. */
213
+ maintenanceIntervalMs?: number; /** Max jobs per run tick. Default 10. */
214
+ runLimit?: number; /** Wall-clock budget to await in-flight jobs on drain. Default 30000. */
215
+ drainTimeoutMs?: number; /** How often the drain re-counts in-flight jobs. Default 500. */
216
+ pollIntervalMs?: number; /** Register SIGTERM/SIGINT handlers that drain then exit. Default true. */
217
+ installSignals?: boolean; /** Which signals to drain on. Default ['SIGTERM', 'SIGINT']. */
218
+ signals?: NodeJS.Signals[]; /** Injectable for tests: destroy (default payload.destroy), exit, wall clock. */
219
+ destroy?: () => Promise<void>;
220
+ exit?: (code: number) => void;
221
+ now?: () => number;
222
+ sleep?: (ms: number) => Promise<void>;
223
+ };
224
+ type Worker = {
225
+ /** Start the run, maintenance, and sweep loops. */start: () => void;
226
+ /**
227
+ * Gracefully drain and shut down (removes signal handlers, stops loops, requeues,
228
+ * releases, destroys). Idempotent: repeated calls return the same in-flight drain.
229
+ */
230
+ drain: () => Promise<DrainResult>; /** Stop the loops and remove signal handlers WITHOUT draining (test teardown). */
231
+ stop: () => void; /** Whether this node currently holds the given leadership role. */
232
+ isLeader: (role: LeaderRole) => boolean;
233
+ };
234
+ /**
235
+ * A plugin-driven worker: runs jobs on every node, schedules and sweeps only while
236
+ * holding the corresponding leadership lease, and drains gracefully on SIGTERM/SIGINT.
237
+ * It owns its own timers (never Payload's autoRun cron), because Payload's
238
+ * `shouldAutoRun` gate permanently stops a cron and cannot follow dynamic leadership.
239
+ * Leadership timestamps use Payload's swappable `getCurrentDate()`; the drain budget
240
+ * uses the injected wall clock.
241
+ */
242
+ declare const createWorker: (args: CreateWorkerArgs) => Worker;
243
+ //#endregion
244
+ //#region src/jobs/deriveJobStatus.d.ts
245
+ /** The seven derived job states, by precedence (see `deriveJobStatus`). */
246
+ type JobStatus = 'cancelled' | 'failed' | 'queued' | 'retrying' | 'running' | 'scheduled' | 'succeeded';
247
+ /** The subset of `payload-jobs` fields a status is derived from. */
248
+ interface JobStatusInput {
249
+ completedAt?: null | string;
250
+ error?: unknown;
251
+ hasError?: boolean | null;
252
+ processing?: boolean | null;
253
+ totalTried?: null | number;
254
+ waitUntil?: null | string;
255
+ }
256
+ /**
257
+ * Collapse a job's raw fields into one status. Payload has no status field; the
258
+ * state lives across `processing`, `hasError`, `error.cancelled`, `completedAt`,
259
+ * `waitUntil`, and `totalTried`. Order matters: the first matching rule wins.
260
+ */
261
+ declare const deriveJobStatus: (job: JobStatusInput, now?: number) => JobStatus;
262
+ //#endregion
263
+ //#region src/presets/presets.d.ts
264
+ /** The option groups a topology preset configures. */
265
+ type TopologyPreset = {
266
+ reliability: ReliabilityOptions;
267
+ queueControl: QueueControlOptions;
268
+ };
269
+ /**
270
+ * Single-node Docker: one serial claimer, so claim races are moot. Reliability and
271
+ * queue control on with defaults; the sweeper runs from the in-process worker.
272
+ */
273
+ declare const singleNodePreset: () => TopologyPreset;
274
+ /**
275
+ * Multi-node Docker: leader-elected scheduling and sweeping (the default). Pass a
276
+ * stable `leaderId` per node if you do not want the generated hostname:pid identity.
277
+ */
278
+ declare const multiNodePreset: (options?: {
279
+ leaderId?: string;
280
+ }) => TopologyPreset;
281
+ /**
282
+ * Serverless (Vercel): no long-running worker, so staleness derives from the platform
283
+ * hard-kill duration (the function maxDuration) rather than a heartbeat, and the run
284
+ * and sweep endpoints are guarded by the cron secret. Drive them with Vercel Cron
285
+ * (see `vercelCrons`).
286
+ */
287
+ declare const serverlessPreset: (options: {
288
+ maxDurationMs: number;
289
+ cronSecretEnvVar?: string;
290
+ }) => TopologyPreset;
291
+ /** A `vercel.json` `crons` entry. */
292
+ type VercelCron = {
293
+ path: string;
294
+ schedule: string;
295
+ };
296
+ /**
297
+ * Build the `vercel.json` `crons` array: one entry hitting the hardened run endpoint
298
+ * (all queues) and one hitting the sweep endpoint. Defaults to every minute (Vercel
299
+ * Pro). Vercel sends the `CRON_SECRET` as a Bearer token, which `cronSecretAccess`
300
+ * checks.
301
+ */
302
+ declare const vercelCrons: (options?: {
303
+ runPath?: string;
304
+ sweepPath?: string;
305
+ runSchedule?: string;
306
+ sweepSchedule?: string;
307
+ }) => VercelCron[];
308
+ //#endregion
309
+ //#region src/queueControl/queueHealth.d.ts
310
+ /** Per-queue health counts plus the last scheduled run. */
311
+ type QueueHealth = {
312
+ queue: string;
313
+ pending: number;
314
+ processing: number;
315
+ failed: number;
316
+ recovered: number;
317
+ lastScheduledRun: string | null;
318
+ };
319
+ type QueueHealthReport = {
320
+ totals: {
321
+ pending: number;
322
+ processing: number;
323
+ failed: number;
324
+ recovered: number;
325
+ };
326
+ oldestPendingAgeMs: number | null;
327
+ queues: QueueHealth[];
328
+ };
329
+ type GetQueueHealthOptions = {
330
+ /** 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 the oldest-pending age. Default now. */
332
+ now?: Date;
333
+ };
334
+ /**
335
+ * Aggregate queue health via `payload.count` per state (pending, processing, failed,
336
+ * and, when reliability is on, recovered), plus the oldest-pending age and the last
337
+ * scheduled run per queue. Reuses Payload's own run-selector predicates. The stats
338
+ * global is read through `payload.db.findGlobal` inside a try/catch because that call
339
+ * throws when the global does not exist (no schedule has run).
340
+ */
341
+ declare const getQueueHealth: (payload: Payload, options?: GetQueueHealthOptions) => Promise<QueueHealthReport>;
342
+ //#endregion
343
+ //#region src/reliability/concurrencyContract.d.ts
344
+ /** A minimal store for at-most-once side-effect guarding, keyed by a stable idempotency key. */
345
+ interface IdempotencyStore {
346
+ /** True if `key` was already marked done. */
347
+ has: (key: string) => Promise<boolean>;
348
+ /** Mark `key` done. Ideally written in the same transaction as the side effect. */
349
+ mark: (key: string) => Promise<void>;
350
+ }
351
+ /**
352
+ * Wrap a job handler so its side effect runs at most once per idempotency key, even
353
+ * when at-least-once delivery re-runs the job. The race this guards is not only
354
+ * redelivery: when the sweeper requeues a job whose lease expired while it was still
355
+ * running, the original execution cannot be aborted (Payload exposes no AbortSignal),
356
+ * so a second worker can run the handler concurrently with the first. Key on the
357
+ * stable unit of work, never the job id, so both executions resolve to the same key.
358
+ * The check and the mark are the caller's to make transactional (Payload's queue and
359
+ * the app data share one database, which makes that natural); this helper only
360
+ * sequences them around the handler. A skipped run returns `{ output: {} }`.
361
+ */
362
+ declare const withIdempotencyKey: <A>(handler: (args: A) => Promise<unknown>, idem: {
363
+ keyFor: (args: A) => string;
364
+ store: IdempotencyStore;
365
+ }) => ((args: A) => Promise<unknown>);
366
+ //#endregion
367
+ //#region src/reliability/jobLeaseStore.d.ts
368
+ /** A Payload job id: a string on Mongo (ObjectId), a number on Postgres (serial). */
369
+ type JobId = number | string;
370
+ /** The result of a stamp (returns the new claim-generation fence token). */
371
+ type StampResult = {
372
+ ok: boolean;
373
+ fenceToken: number;
374
+ };
375
+ /** The result of a renew/requeue/dead-letter attempt. */
376
+ type JobLeaseResult = {
377
+ ok: boolean;
378
+ };
379
+ /** The lease-relevant columns of one `payload-jobs` row (diagnostics and tests). */
380
+ type JobLeaseRow = {
381
+ processing: boolean;
382
+ leaseExpiresAt: Date | null;
383
+ claimedBy: string | null;
384
+ fenceToken: number;
385
+ recoveryAttempts: number;
386
+ updatedAt: Date;
387
+ };
388
+ /** Arguments for dead-lettering, grouped to stay within the 3-parameter lint cap. */
389
+ type DeadLetterArgs = {
390
+ jobId: JobId;
391
+ now: Date;
392
+ fallbackMs: number;
393
+ error: Record<string, unknown>;
394
+ };
395
+ /**
396
+ * A fenced lease over a single `payload-jobs` row. Every write is one atomic
397
+ * conditional update at the database (Mongo single-document `findOneAndUpdate`, or
398
+ * Postgres `UPDATE ... WHERE <guard> RETURNING`), so two contenders never both win.
399
+ * Sibling to the Plan 1 locks `LeaseStore`; implemented per adapter because Payload's
400
+ * `db.updateOne` drops the `where` predicate when an `id` is given.
401
+ */
402
+ interface JobLeaseStore {
403
+ /** Stamp a freshly-claimed job (guarded on `processing = true`); bumps the fence token. */
404
+ stampClaim: (jobId: JobId, owner: string, ttlMs: number, now: Date) => Promise<StampResult>;
405
+ /** Extend the lease iff this owner's fence token still matches. */
406
+ renew: (jobId: JobId, fenceToken: number, ttlMs: number, now: Date) => Promise<JobLeaseResult>;
407
+ /** Requeue a stale orphan (guarded on `processing = true` AND stale); increments recoveryAttempts. */
408
+ requeue: (jobId: JobId, now: Date, fallbackMs: number) => Promise<JobLeaseResult>;
409
+ /** Dead-letter a stale orphan at the recovery cap (same guard). */
410
+ deadLetter: (args: DeadLetterArgs) => Promise<JobLeaseResult>;
411
+ /**
412
+ * Requeue every in-flight job currently claimed by `owner`, in one bulk write, for
413
+ * graceful drain. Sets `processing: false`, clears the lease, increments
414
+ * recoveryAttempts, and bumps the fence token so a revived worker's renew fails.
415
+ * Returns how many rows were released. Unlike `requeue`, it does not require the
416
+ * lease to be stale (the node owns these claims and is shutting down).
417
+ */
418
+ releaseAllClaims: (owner: string) => Promise<{
419
+ released: number;
420
+ }>;
421
+ /** Read the lease columns of a job row. */
422
+ read: (jobId: JobId) => Promise<JobLeaseRow | null>;
423
+ }
424
+ /** Build the job-lease store for the running adapter. Throws for an unsupported adapter. */
425
+ declare const createJobLeaseStore: (payload: Payload) => JobLeaseStore;
426
+ //#endregion
427
+ //#region src/reliability/leaseStore.d.ts
428
+ /** The current state of one leadership lease row. */
429
+ type LeaseRecord = {
430
+ role: LeaderRole;
431
+ owner: string | null;
432
+ leaseExpiresAt: Date | null;
433
+ fenceToken: number;
434
+ };
435
+ /** The outcome of an acquire/renew attempt. */
436
+ type LeaseResult = {
437
+ /** Whether this caller now holds (or still holds) the lease. */ok: boolean; /** The fence token after the attempt (monotonic; only meaningful when ok). */
438
+ fenceToken: number;
439
+ };
440
+ /**
441
+ * A distributed lease over the `payload-jobs-locks` rows. Every method is a single
442
+ * atomic conditional write at the database, so two contenders never both win.
443
+ * Implemented per adapter because Payload's `db.updateOne` drops the `where`
444
+ * predicate when an `id` is given (validated), so it cannot express a compare-and-set.
445
+ */
446
+ interface LeaseStore {
447
+ /** Acquire `role` if free or expired at `now`. Bumps the fence token on success. */
448
+ acquireOrSteal: (role: LeaderRole, owner: string, ttlMs: number, now: Date) => Promise<LeaseResult>;
449
+ /** Renew `role` if `owner` still holds it at `now`. Does not bump the fence token. */
450
+ 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<void>;
453
+ /** Read the current lease row (diagnostics and tests). */
454
+ read: (role: LeaderRole) => Promise<LeaseRecord | null>;
455
+ }
456
+ /** Build the lease store for the running adapter. Throws for an unsupported adapter. */
457
+ declare const createLeaseStore: (payload: Payload) => LeaseStore;
458
+ //#endregion
459
+ //#region src/reliability/leaderController.d.ts
460
+ type LeaderController = {
461
+ /** Drive one acquire/renew cycle at `now`. Safe to call repeatedly. */tick: (now: Date) => Promise<void>; /** Whether this controller currently holds leadership. */
462
+ isLeader: () => boolean; /** The fence token of the held lease, or 0 when not leading. */
463
+ fenceToken: () => number; /** Relinquish leadership now (graceful handoff). */
464
+ release: () => Promise<void>;
465
+ };
466
+ type LeaderControllerArgs = {
467
+ store: LeaseStore;
468
+ role: LeaderRole;
469
+ ownerId: string;
470
+ ttlMs: number;
471
+ };
472
+ /**
473
+ * Turns a lease into leadership. On each `tick`: if not leading, try to acquire/steal;
474
+ * if leading, renew. A failed renew (the lease was stolen while this node was paused
475
+ * past expiry) drops leadership immediately, so a zombie never keeps acting. No timer
476
+ * lives here; a caller schedules `tick` at `ttlMs / 3`.
477
+ */
478
+ declare const createLeaderController: (args: LeaderControllerArgs) => LeaderController;
479
+ //#endregion
480
+ //#region src/reliability/recoveryDecision.d.ts
481
+ /** What the sweeper does with a reclaimed orphan. */
482
+ type RecoveryDecision = 'deadLetter' | 'requeue';
483
+ /**
484
+ * Requeue an orphaned job while it is below the recovery cap; dead-letter once it
485
+ * reaches the cap, to stop a poison job from thrashing the queue. `recoveryAttempts`
486
+ * is the count before this pass (a requeue increments it). `maxRecoveries` of 0
487
+ * dead-letters on the first orphan.
488
+ */
489
+ declare const decideRecovery: (recoveryAttempts: number, maxRecoveries: number) => RecoveryDecision;
490
+ //#endregion
491
+ //#region src/reliability/sweeper.d.ts
492
+ /** What one sweep pass did. */
493
+ type SweepResult = {
494
+ scanned: number;
495
+ requeued: number;
496
+ deadLettered: number;
497
+ };
498
+ type RunSweepArgs = {
499
+ payload: Payload;
500
+ options: ResolvedReliabilityOptions; /** Reuse a store (tests); built from `payload` otherwise. */
501
+ store?: JobLeaseStore; /** The instant the pass runs at; defaults to the swappable clock. */
502
+ now?: Date; /** Max candidates per pass. Default 100. */
503
+ limit?: number; /** Leadership gate. When false the pass is a no-op. Default true. */
504
+ isLeader?: boolean;
505
+ };
506
+ /**
507
+ * One sweep pass: find stale `processing: true` orphans and either requeue them
508
+ * (below the recovery cap) or dead-letter them (at the cap), each through a fenced
509
+ * conditional write that re-checks staleness, so a job that renewed between the find
510
+ * and the write is skipped and two overlapping sweepers never both reclaim the same
511
+ * orphan. Gated by leadership: callers pass `isLeader` from the Plan 1 sweeper lease.
512
+ */
513
+ declare const runSweep: (args: RunSweepArgs) => Promise<SweepResult>;
514
+ //#endregion
515
+ //#region src/index.d.ts
516
+ declare module 'payload' {
517
+ interface RegisteredPlugins {
518
+ '@10x-media/jobs': JobsPluginOptions;
519
+ }
520
+ }
521
+ /**
522
+ * Jobs plugin for Payload v3. Enhances the built-in `payload-jobs` collection
523
+ * with an ops dashboard (status, queue health, error and log panels) and the
524
+ * supporting i18n. Authored with `definePlugin` so the automations and webhooks
525
+ * plugins can detect it by slug. Runs first (`order: 0`).
526
+ */
527
+ declare const jobs: (options: JobsPluginOptions) => import("payload").Plugin;
528
+ //#endregion
529
+ 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-CYsbNe4q.d.ts.map
@@ -0,0 +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-CYsbNe4q.js";
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 };