@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.
- package/CHANGELOG.md +15 -0
- package/LICENSE +21 -0
- package/README.md +351 -0
- package/dist/deriveJobStatus-CM_sCsgm.js +72 -0
- package/dist/deriveJobStatus-CM_sCsgm.js.map +1 -0
- package/dist/exports/client.d.ts +49 -0
- package/dist/exports/client.js +573 -0
- package/dist/exports/client.js.map +1 -0
- package/dist/exports/i18n.d.ts +47 -0
- package/dist/exports/i18n.js +3 -0
- package/dist/exports/rsc.d.ts +19 -0
- package/dist/exports/rsc.js +66 -0
- package/dist/exports/rsc.js.map +1 -0
- package/dist/exports/types.d.ts +2 -0
- package/dist/exports/types.js +1 -0
- package/dist/index-CYsbNe4q.d.ts +530 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1622 -0
- package/dist/index.js.map +1 -0
- package/dist/jobStatusMeta-BLBSPUcE.js +41 -0
- package/dist/jobStatusMeta-BLBSPUcE.js.map +1 -0
- package/dist/keys-BYs8GTJy.js +41 -0
- package/dist/keys-BYs8GTJy.js.map +1 -0
- package/dist/server-JsvYf5vy.js +13 -0
- package/dist/server-JsvYf5vy.js.map +1 -0
- package/dist/translations-KyQ3962W.js +61 -0
- package/dist/translations-KyQ3962W.js.map +1 -0
- package/package.json +110 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["JOBS_SLUG","model","JOBS_SLUG","tableName","pool","JOBS_SLUG","JOBS_SLUG"],"sources":["../src/plugin/resolve.ts","../src/plugin/registerJobsEnhancements.ts","../src/plugin/registerTranslations.ts","../src/queueControl/access.ts","../src/queueControl/options.ts","../src/reliability/leaseLogic.ts","../src/reliability/jobLeaseStore.mongo.ts","../src/reliability/jobLeaseStore.postgres.ts","../src/reliability/jobLeaseStore.ts","../src/reliability/leaseMode.ts","../src/reliability/recoveryDecision.ts","../src/reliability/sweeper.ts","../src/queueControl/pauseState.ts","../src/queueControl/pauseStore.ts","../src/queueControl/queueHealth.ts","../src/queueControl/runTargets.ts","../src/queueControl/endpoints.ts","../src/queueControl/registerQueueControl.ts","../src/reliability/options.ts","../src/reliability/concurrencyContract.ts","../src/reliability/fields.ts","../src/reliability/heartbeat.ts","../src/reliability/locksCollection.ts","../src/reliability/nodeId.ts","../src/reliability/registerReliability.ts","../src/execution/autoRunConfig.ts","../src/execution/drain.ts","../src/reliability/leaderController.ts","../src/reliability/leaseStore.mongo.ts","../src/reliability/leaseStore.postgres.ts","../src/reliability/leaseStore.ts","../src/execution/inFlight.ts","../src/execution/signals.ts","../src/execution/workerCycles.ts","../src/execution/worker.ts","../src/presets/presets.ts","../src/index.ts"],"sourcesContent":["/**\n * A customization point: pass a value to replace our default, or a function to\n * transform it. The function form receives the default so callers can compose\n * (extend, filter, reorder) instead of rewriting from scratch.\n */\nexport type Override<T> = ((defaults: T) => T) | T\n\n/** Apply an `Override`, falling back to `defaults` when none was provided. */\nexport const resolve = <T>(override: Override<T> | undefined, defaults: T): T => {\n\tif (override === undefined) {\n\t\treturn defaults\n\t}\n\treturn typeof override === 'function' ? (override as (value: T) => T)(defaults) : override\n}\n","import type {\n\tCollectionBeforeChangeHook,\n\tCollectionConfig,\n\tConfig,\n\tField,\n\tLabelFunction,\n\tPayloadComponent,\n} from 'payload'\n\nimport type { JobsOptions } from '../options'\nimport { keys } from '../translations/keys'\nimport { labelForKey } from '../translations/server'\nimport { resolve } from './resolve'\n\nconst STATUS_CELL = '@10x-media/jobs/client#JobStatusCell'\nconst STATUS_HEADER = '@10x-media/jobs/client#JobStatusHeader'\nconst RELATIVE_CELL = '@10x-media/jobs/client#RelativeTimeCell'\nconst ERROR_PANEL = '@10x-media/jobs/client#JobErrorPanel'\nconst LOG_TIMELINE = '@10x-media/jobs/client#JobLogTimeline'\nconst DOC_DESCRIPTION = '@10x-media/jobs/client#JobDocDescription'\nconst HEALTH_BAR = '@10x-media/jobs/rsc#JobsHealthBar'\n\n/** Stored field that titles the document: the workflow or task the job runs. */\nconst TITLE_FIELD: Field = {\n\tname: 'jobTitle',\n\ttype: 'text',\n\tadmin: { disableListColumn: true, hidden: true },\n}\n\n/**\n * Keep `jobTitle` in sync with the job's workflow or task on every write, falling\n * back to the existing doc so partial state updates never clobber it.\n */\nconst setJobTitle: CollectionBeforeChangeHook = ({ data, originalDoc }) => {\n\tconst source = { ...(originalDoc ?? {}), ...data } as Record<string, unknown>\n\tconst workflow = typeof source.workflowSlug === 'string' ? source.workflowSlug : undefined\n\tconst task = typeof source.taskSlug === 'string' ? source.taskSlug : undefined\n\tconst title = workflow || task\n\treturn title ? { ...data, jobTitle: title } : data\n}\n\n/** Our default document Field component for specific job fields. */\nconst FIELD_COMPONENTS: Record<string, string> = {\n\terror: ERROR_PANEL,\n\tlog: LOG_TIMELINE,\n}\n\nconst DEFAULT_JOBS_COLUMNS = ['workflowSlug', 'status', 'queue', 'totalTried', 'updatedAt']\n\n/** Friendlier labels for a few of Payload's default job fields. */\nconst FIELD_LABELS: Record<string, LabelFunction> = {\n\ttotalTried: labelForKey(keys.fieldAttempts),\n\tworkflowSlug: labelForKey(keys.fieldWorkflow),\n}\n\n/**\n * Payload appends `createdAt`/`updatedAt` after overrides run, but only when they\n * are absent, so we inject our own to attach the relative-time cell to them.\n */\nconst TIMESTAMP_FIELDS: Field[] = [\n\t{\n\t\tname: 'createdAt',\n\t\ttype: 'date',\n\t\tlabel: labelForKey(keys.fieldCreated),\n\t\tindex: true,\n\t\tadmin: { disableBulkEdit: true, hidden: true },\n\t},\n\t{\n\t\tname: 'updatedAt',\n\t\ttype: 'date',\n\t\tlabel: labelForKey(keys.fieldUpdated),\n\t\tindex: true,\n\t\tadmin: { disableBulkEdit: true, hidden: true },\n\t},\n]\n\nconst fieldName = (field: Field): string | undefined =>\n\t'name' in field && typeof field.name === 'string' ? field.name : undefined\n\nconst setCell = (field: Field, cell: PayloadComponent): Field =>\n\t({\n\t\t...field,\n\t\tadmin: { ...field.admin, components: { ...field.admin?.components, Cell: cell } },\n\t}) as Field\n\n/**\n * Resolve a field's list cell: an explicit `cells` override wins (`false` keeps\n * Payload's default), otherwise date fields get the relative-time cell.\n */\nconst resolveCell = (field: Field, cells: JobsOptions['cells']): Field => {\n\tconst name = fieldName(field)\n\tconst override = name ? cells?.[name] : undefined\n\tif (override === false) {\n\t\treturn field\n\t}\n\tif (override) {\n\t\treturn setCell(field, override)\n\t}\n\tif (field.type === 'date') {\n\t\treturn setCell(field, RELATIVE_CELL)\n\t}\n\treturn field\n}\n\n/** Execution-state fields surfaced in the header; hidden from the form, kept as data/columns. */\nconst HIDE_ALWAYS = new Set(['completedAt', 'totalTried', 'hasError', 'processing', 'taskStatus'])\n/** Inputs shown only when creating a job; hidden once it exists. */\nconst HIDE_ON_EDIT = new Set(['waitUntil'])\n/** Execution output: read-only in the admin (admin-only, so the runner can still write it). */\nconst READONLY_OUTPUTS = new Set(['error', 'log'])\n/** Config inputs: editable on Create, read-only on edit; kept in the sidebar. */\nconst READONLY_INPUTS = new Set(['input', 'workflowSlug', 'taskSlug', 'queue'])\n\n/**\n * Lock a field for the read-only-record model. Runner-written fields use\n * admin-only props (`hidden`/`readOnly`) so the jobs runner is never blocked;\n * inputs use field `access.update` so they stay editable on Create but lock once\n * the job exists.\n */\nconst lockField = (field: Field, name: string): Field => {\n\tif (HIDE_ALWAYS.has(name)) {\n\t\treturn { ...field, admin: { ...field.admin, hidden: true } } as Field\n\t}\n\tif (HIDE_ON_EDIT.has(name)) {\n\t\treturn {\n\t\t\t...field,\n\t\t\tadmin: {\n\t\t\t\t...field.admin,\n\t\t\t\tcondition: (_data, _siblingData, { operation }) => operation === 'create',\n\t\t\t},\n\t\t} as Field\n\t}\n\tif (READONLY_OUTPUTS.has(name)) {\n\t\treturn { ...field, admin: { ...field.admin, readOnly: true } } as Field\n\t}\n\tif (READONLY_INPUTS.has(name)) {\n\t\tconst access = 'access' in field && field.access ? field.access : {}\n\t\treturn { ...field, access: { ...access, update: () => false } } as Field\n\t}\n\treturn field\n}\n\n/** Recursively relabel fields, apply cell overrides, and lock the record, descending into tabs. */\nconst enhanceFields = (\n\tfields: Field[],\n\tcells: JobsOptions['cells'],\n\tlockRecord: boolean\n): Field[] =>\n\tfields.map((field): Field => {\n\t\tlet next = field\n\t\tconst name = fieldName(field)\n\t\tif (name && FIELD_LABELS[name]) {\n\t\t\tnext = { ...field, label: FIELD_LABELS[name] } as Field\n\t\t}\n\t\tnext = resolveCell(next, cells)\n\t\tif (lockRecord && name) {\n\t\t\tnext = lockField(next, name)\n\t\t}\n\t\tif (name && FIELD_COMPONENTS[name]) {\n\t\t\tnext = {\n\t\t\t\t...next,\n\t\t\t\tadmin: {\n\t\t\t\t\t...next.admin,\n\t\t\t\t\tcomponents: { ...next.admin?.components, Field: FIELD_COMPONENTS[name] },\n\t\t\t\t},\n\t\t\t} as Field\n\t\t}\n\t\tif ('tabs' in next) {\n\t\t\tnext = {\n\t\t\t\t...next,\n\t\t\t\ttabs: next.tabs.map((tab) => ({\n\t\t\t\t\t...tab,\n\t\t\t\t\tfields: enhanceFields(tab.fields, cells, lockRecord),\n\t\t\t\t})),\n\t\t\t} as Field\n\t\t} else if ('fields' in next) {\n\t\t\tnext = { ...next, fields: enhanceFields(next.fields, cells, lockRecord) } as Field\n\t\t}\n\t\treturn next\n\t})\n\n/** Build the derived Status column, honoring the `status` override (`false` removes it). */\nconst buildStatusField = (status: JobsOptions['status']): Field | null => {\n\tif (status === false) {\n\t\treturn null\n\t}\n\treturn {\n\t\tname: 'status',\n\t\ttype: 'ui',\n\t\tlabel: labelForKey(keys.fieldStatus),\n\t\tadmin: { components: { Cell: status ?? STATUS_CELL, Field: STATUS_HEADER } },\n\t} as Field\n}\n\n/**\n * Enhance Payload's built-in `payload-jobs` collection through its sanctioned\n * `jobs.jobsCollectionOverrides` seam. Composes with a host-provided override\n * (ours layer on top of theirs) so neither clobbers the other, and every piece\n * is replaceable through `options` (`status`, `cells`, `beforeListTable`).\n */\nexport const registerJobsEnhancements = (config: Config, options: JobsOptions): void => {\n\tconst existing = config.jobs?.jobsCollectionOverrides\n\n\tconst enhance = ({\n\t\tdefaultJobsCollection,\n\t}: {\n\t\tdefaultJobsCollection: CollectionConfig\n\t}): CollectionConfig => {\n\t\tconst base = existing ? existing({ defaultJobsCollection }) : defaultJobsCollection\n\t\tconst existingNames = new Set(\n\t\t\tbase.fields.flatMap((field) => {\n\t\t\t\tconst name = fieldName(field)\n\t\t\t\treturn name ? [name] : []\n\t\t\t})\n\t\t)\n\n\t\tconst timestamps = TIMESTAMP_FIELDS.filter((field) => {\n\t\t\tconst name = fieldName(field)\n\t\t\treturn name ? !existingNames.has(name) : false\n\t\t}).map((field) => resolveCell(field, options.cells))\n\n\t\tconst statusField = buildStatusField(options.status)\n\t\tconst lockRecord = options.readOnlyRecord !== false\n\t\tconst hostBeforeTable = base.admin?.components?.beforeListTable ?? []\n\t\tconst ourBeforeTable: PayloadComponent[] =\n\t\t\toptions.beforeListTable === false\n\t\t\t\t? []\n\t\t\t\t: (options.beforeListTable ?? [\n\t\t\t\t\t\t{ path: HEALTH_BAR, serverProps: { cap: options.healthBarCap } },\n\t\t\t\t\t])\n\n\t\treturn {\n\t\t\t...base,\n\t\t\tadmin: {\n\t\t\t\t...base.admin,\n\t\t\t\thidden: options.hidden ?? false,\n\t\t\t\tuseAsTitle: 'jobTitle',\n\t\t\t\tdefaultColumns: resolve(options.defaultColumns, DEFAULT_JOBS_COLUMNS),\n\t\t\t\tcomponents: {\n\t\t\t\t\t...base.admin?.components,\n\t\t\t\t\tDescription: DOC_DESCRIPTION,\n\t\t\t\t\tbeforeListTable: [...hostBeforeTable, ...ourBeforeTable],\n\t\t\t\t},\n\t\t\t},\n\t\t\thooks: {\n\t\t\t\t...base.hooks,\n\t\t\t\tbeforeChange: [...(base.hooks?.beforeChange ?? []), setJobTitle],\n\t\t\t},\n\t\t\tfields: [\n\t\t\t\t...(statusField ? [statusField] : []),\n\t\t\t\tTITLE_FIELD,\n\t\t\t\t...enhanceFields(base.fields, options.cells, lockRecord),\n\t\t\t\t...timestamps,\n\t\t\t],\n\t\t} as CollectionConfig\n\t}\n\n\tconfig.jobs = { ...config.jobs, jobsCollectionOverrides: enhance }\n}\n","import type { Config } from 'payload'\nimport { deepMergeSimple } from 'payload/shared'\n\nimport { translations } from '../translations'\n\ntype Translations = NonNullable<NonNullable<Config['i18n']>['translations']>\n\n/**\n * Merge this plugin's translations into the host config. A host value wins on\n * conflict (`deepMergeSimple` lets the second argument override), so projects can\n * override any string.\n */\nexport const registerTranslations = (config: Config): void => {\n\tconfig.i18n ??= {}\n\tconfig.i18n.translations = deepMergeSimple<Translations>(\n\t\ttranslations,\n\t\tconfig.i18n.translations ?? {}\n\t)\n}\n","import type { PayloadRequest } from 'payload'\n\n/** A jobs access checker (matches Payload's `jobs.access.run` shape). */\nexport type JobAccess = (args: { req: PayloadRequest }) => boolean | Promise<boolean>\n\nexport type CronSecretAccessOptions = {\n\t/** Env var holding the shared secret. Default `CRON_SECRET`. */\n\tenvVar?: string\n}\n\n/** The default endpoint guard: logged-in users only (safer than Payload's open default). */\nexport const loggedInAccess: JobAccess = ({ req }) => Boolean(req.user)\n\n/**\n * An access checker for serverless cron triggers: a logged-in user passes, otherwise\n * the request must carry `Authorization: Bearer ${process.env[envVar]}`. Payload ships\n * no built-in secret check, so this implements the canonical Vercel-cron pattern.\n */\nexport const cronSecretAccess = (options: CronSecretAccessOptions = {}): JobAccess => {\n\tconst envVar = options.envVar ?? 'CRON_SECRET'\n\treturn ({ req }) => {\n\t\tif (req.user) {\n\t\t\treturn true\n\t\t}\n\t\t// biome-ignore lint/plugin/noProcessEnv: reads the operator-provided cron secret at request time\n\t\tconst secret = process.env[envVar]\n\t\tif (!secret) {\n\t\t\treturn false\n\t\t}\n\t\treturn req.headers.get('authorization') === `Bearer ${secret}`\n\t}\n}\n","import { type JobAccess, loggedInAccess } from './access'\n\nexport type QueueControlOptions = {\n\t/** Gate the queue-control endpoints (and the native run endpoint). Default: logged-in users only. */\n\taccess?: JobAccess\n\t/** Queues to report per-queue health for. Default ['default']. */\n\tqueues?: string[]\n}\n\nexport type ResolvedQueueControlOptions = {\n\taccess: JobAccess\n\tqueues: string[]\n}\n\n/** Resolve queue-control options to a fully-defaulted object, or `null` when disabled. */\nexport const resolveQueueControlOptions = (\n\toptions: QueueControlOptions | false | undefined\n): ResolvedQueueControlOptions | null => {\n\tif (options === undefined || options === false) {\n\t\treturn null\n\t}\n\treturn {\n\t\taccess: options.access ?? loggedInAccess,\n\t\tqueues: options.queues ?? ['default'],\n\t}\n}\n","/**\n * A lease is stale (free to acquire/steal) when it has no expiry, or its expiry\n * is strictly before `now`. Strict `<` so a lease is still held exactly at expiry.\n *\n * Staleness primitive consumed by the heartbeat sweeper in the next reliability plan.\n */\nexport const isLeaseStale = (leaseExpiresAt: Date | null, now: Date): boolean => {\n\tif (leaseExpiresAt === null) {\n\t\treturn true\n\t}\n\treturn leaseExpiresAt.getTime() < now.getTime()\n}\n\n/**\n * A privileged write is stale (must be rejected) when its fence token is below the current one.\n *\n * Fence-rejection primitive consumed by privileged-write fencing in the next reliability plan.\n */\nexport const fenceIsStale = (incomingToken: number, currentToken: number): boolean =>\n\tincomingToken < currentToken\n\n/** The expiry instant for a lease acquired/renewed at `now` for `ttlMs`. */\nexport const leaseExpiry = (now: Date, ttlMs: number): Date => new Date(now.getTime() + ttlMs)\n\n/**\n * A claimed job is stale (sweepable) when its lease has elapsed (strict `<`, so a\n * job is still live exactly at expiry), or when it has no lease yet but its claim,\n * proxied by `updatedAt` (the claim write bumps it), is older than `fallbackMs`. The\n * second branch recovers a job claimed but crashed before the heartbeat wrapper\n * stamped a lease. Args is an object to stay within the 3-parameter lint cap.\n */\nexport const isJobStale = (args: {\n\tleaseExpiresAt: Date | null\n\tupdatedAt: Date\n\tnow: Date\n\tfallbackMs: number\n}): boolean => {\n\tconst { fallbackMs, leaseExpiresAt, now, updatedAt } = args\n\tif (leaseExpiresAt !== null) {\n\t\treturn leaseExpiresAt.getTime() < now.getTime()\n\t}\n\treturn updatedAt.getTime() < now.getTime() - fallbackMs\n}\n","import type { Payload } from 'payload'\nimport type {\n\tDeadLetterArgs,\n\tJobLeaseResult,\n\tJobLeaseRow,\n\tJobLeaseStore,\n\tStampResult,\n} from './jobLeaseStore'\nimport { leaseExpiry } from './leaseLogic'\n\nconst JOBS_SLUG = 'payload-jobs'\n\ntype MongoDoc = {\n\tprocessing?: boolean\n\tleaseExpiresAt?: Date | string | null\n\tclaimedBy?: string | null\n\tfenceToken?: number\n\trecoveryAttempts?: number\n\tupdatedAt?: Date | string\n}\n\ntype MongoModel = {\n\tfindOne: (filter: Record<string, unknown>) => { lean: () => Promise<MongoDoc | null> }\n\tfindOneAndUpdate: (\n\t\tfilter: Record<string, unknown>,\n\t\tupdate: Record<string, unknown>,\n\t\toptions?: Record<string, unknown>\n\t) => Promise<MongoDoc | null>\n\tupdateMany: (\n\t\tfilter: Record<string, unknown>,\n\t\tupdate: Record<string, unknown>\n\t) => Promise<{ modifiedCount?: number }>\n}\n\n/** Reach the raw Mongoose model the adapter exposes on `db.collections[slug]`. */\nconst model = (payload: Payload): MongoModel => {\n\tconst collections = (payload.db as unknown as { collections: Record<string, MongoModel> })\n\t\t.collections\n\tconst found = collections[JOBS_SLUG]\n\tif (!found) {\n\t\tthrow new Error(`@10x-media/jobs: missing Mongoose model for \"${JOBS_SLUG}\"`)\n\t}\n\treturn found\n}\n\n/** The stale-orphan predicate shared by requeue and dead-letter. */\nconst stale = (now: Date, fallbackMs: number): Record<string, unknown> => ({\n\thasError: { $ne: true },\n\tprocessing: true,\n\t$or: [\n\t\t{ leaseExpiresAt: { $lt: now } },\n\t\t{ leaseExpiresAt: null, updatedAt: { $lt: new Date(now.getTime() - fallbackMs) } },\n\t],\n})\n\n/** Single-document `findOneAndUpdate` is an atomic compare-and-set on MongoDB. */\nexport const createMongoJobLeaseStore = (payload: Payload): JobLeaseStore => {\n\tconst m = model(payload)\n\n\treturn {\n\t\tdeadLetter: async ({\n\t\t\terror,\n\t\t\tfallbackMs,\n\t\t\tjobId,\n\t\t\tnow,\n\t\t}: DeadLetterArgs): Promise<JobLeaseResult> => {\n\t\t\tconst doc = await m.findOneAndUpdate(\n\t\t\t\t{ _id: jobId, ...stale(now, fallbackMs) },\n\t\t\t\t{\n\t\t\t\t\t$inc: { fenceToken: 1 },\n\t\t\t\t\t$set: { claimedBy: null, error, hasError: true, leaseExpiresAt: null, processing: false },\n\t\t\t\t},\n\t\t\t\t{ new: true }\n\t\t\t)\n\t\t\treturn { ok: doc !== null }\n\t\t},\n\t\tread: async (jobId): Promise<JobLeaseRow | null> => {\n\t\t\tconst doc = await m.findOne({ _id: jobId }).lean()\n\t\t\tif (doc === null) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tclaimedBy: doc.claimedBy ?? null,\n\t\t\t\tfenceToken: doc.fenceToken ?? 0,\n\t\t\t\tleaseExpiresAt: doc.leaseExpiresAt ? new Date(doc.leaseExpiresAt) : null,\n\t\t\t\tprocessing: doc.processing === true,\n\t\t\t\trecoveryAttempts: doc.recoveryAttempts ?? 0,\n\t\t\t\tupdatedAt: doc.updatedAt ? new Date(doc.updatedAt) : new Date(0),\n\t\t\t}\n\t\t},\n\t\t// biome-ignore lint/complexity/useMaxParams: lease primitive signature (jobId, fenceToken, ttlMs, now)\n\t\trenew: async (jobId, fenceToken, ttlMs, now): Promise<JobLeaseResult> => {\n\t\t\tconst doc = await m.findOneAndUpdate(\n\t\t\t\t{ _id: jobId, fenceToken },\n\t\t\t\t{ $set: { leaseExpiresAt: leaseExpiry(now, ttlMs) } },\n\t\t\t\t{ new: true }\n\t\t\t)\n\t\t\treturn { ok: doc !== null }\n\t\t},\n\t\treleaseAllClaims: async (owner): Promise<{ released: number }> => {\n\t\t\tconst res = await m.updateMany(\n\t\t\t\t{ claimedBy: owner, processing: true },\n\t\t\t\t{\n\t\t\t\t\t$inc: { fenceToken: 1, recoveryAttempts: 1 },\n\t\t\t\t\t$set: { claimedBy: null, leaseExpiresAt: null, processing: false, waitUntil: null },\n\t\t\t\t}\n\t\t\t)\n\t\t\treturn { released: res.modifiedCount ?? 0 }\n\t\t},\n\t\trequeue: async (jobId, now, fallbackMs): Promise<JobLeaseResult> => {\n\t\t\tconst doc = await m.findOneAndUpdate(\n\t\t\t\t{ _id: jobId, ...stale(now, fallbackMs) },\n\t\t\t\t{\n\t\t\t\t\t$inc: { fenceToken: 1, recoveryAttempts: 1 },\n\t\t\t\t\t$set: { claimedBy: null, leaseExpiresAt: null, processing: false, waitUntil: null },\n\t\t\t\t},\n\t\t\t\t{ new: true }\n\t\t\t)\n\t\t\treturn { ok: doc !== null }\n\t\t},\n\t\t// biome-ignore lint/complexity/useMaxParams: lease primitive signature (jobId, owner, ttlMs, now)\n\t\tstampClaim: async (jobId, owner, ttlMs, now): Promise<StampResult> => {\n\t\t\tconst doc = await m.findOneAndUpdate(\n\t\t\t\t{ _id: jobId, processing: true },\n\t\t\t\t{\n\t\t\t\t\t$inc: { fenceToken: 1 },\n\t\t\t\t\t$set: { claimedBy: owner, leaseExpiresAt: leaseExpiry(now, ttlMs), startedAt: now },\n\t\t\t\t},\n\t\t\t\t{ new: true }\n\t\t\t)\n\t\t\treturn { fenceToken: doc?.fenceToken ?? 0, ok: doc !== null }\n\t\t},\n\t}\n}\n","import type { Payload } from 'payload'\nimport type {\n\tDeadLetterArgs,\n\tJobLeaseResult,\n\tJobLeaseRow,\n\tJobLeaseStore,\n\tStampResult,\n} from './jobLeaseStore'\nimport { leaseExpiry } from './leaseLogic'\n\nconst JOBS_SLUG = 'payload-jobs'\n\ntype PgRow = {\n\tprocessing?: boolean\n\tlease_expires_at?: Date | string | null\n\tclaimed_by?: string | null\n\tfence_token?: number | string\n\trecovery_attempts?: number | string\n\tupdated_at?: Date | string\n}\n\ntype PgPool = {\n\tquery: (text: string, values?: unknown[]) => Promise<{ rowCount: number; rows: PgRow[] }>\n}\n\n/** Payload tables for kebab slugs are the slug with hyphens replaced by underscores. */\nconst tableName = (payload: Payload): string => {\n\tconst defaultTable = JOBS_SLUG.replace(/-/g, '_')\n\tconst map = (payload.db as unknown as { tableNameMap?: Map<string, string> }).tableNameMap\n\tconst fromMap = map && typeof map.get === 'function' ? map.get(defaultTable) : undefined\n\treturn fromMap ?? defaultTable\n}\n\nconst pool = (payload: Payload): PgPool => {\n\tconst found = (payload.db as unknown as { pool?: PgPool }).pool\n\tif (!found) {\n\t\tthrow new Error(`@10x-media/jobs: missing pg pool on the \"${payload.db.name}\" adapter`)\n\t}\n\treturn found\n}\n\n/** Single-statement `UPDATE ... WHERE <guard> RETURNING` is atomic under READ COMMITTED. */\nexport const createPostgresJobLeaseStore = (payload: Payload): JobLeaseStore => {\n\tconst table = tableName(payload)\n\tconst db = pool(payload)\n\n\t// Shared stale-orphan guard fragment. $2 = now, $3 = updatedAt cutoff. A raw UPDATE\n\t// here does not bump updated_at (the column has no onUpdate), unlike Mongoose which\n\t// auto-bumps it. That divergence never reaches this guard: a stamped row always has a\n\t// non-null lease (so the IS NULL fallback branch skips it), and a reclaimed row has\n\t// processing = false, so the fallback only ever evaluates Payload-written rows.\n\tconst staleGuard =\n\t\t'processing = true AND has_error IS NOT TRUE AND (lease_expires_at < $2 OR (lease_expires_at IS NULL AND updated_at < $3))'\n\n\treturn {\n\t\tdeadLetter: async ({\n\t\t\terror,\n\t\t\tfallbackMs,\n\t\t\tjobId,\n\t\t\tnow,\n\t\t}: DeadLetterArgs): Promise<JobLeaseResult> => {\n\t\t\tconst res = await db.query(\n\t\t\t\t`UPDATE ${table}\n\t\t\t\t SET processing = false, has_error = true, error = $4::jsonb,\n\t\t\t\t lease_expires_at = NULL, claimed_by = NULL, fence_token = COALESCE(fence_token, 0) + 1\n\t\t\t\t WHERE id = $1 AND ${staleGuard}\n\t\t\t\t RETURNING id`,\n\t\t\t\t[jobId, now, new Date(now.getTime() - fallbackMs), JSON.stringify(error)]\n\t\t\t)\n\t\t\treturn { ok: res.rowCount === 1 }\n\t\t},\n\t\tread: async (jobId): Promise<JobLeaseRow | null> => {\n\t\t\tconst res = await db.query(\n\t\t\t\t`SELECT processing, lease_expires_at, claimed_by, fence_token, recovery_attempts, updated_at\n\t\t\t\t FROM ${table} WHERE id = $1`,\n\t\t\t\t[jobId]\n\t\t\t)\n\t\t\tconst row = res.rows[0]\n\t\t\tif (row === undefined) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tclaimedBy: row.claimed_by ?? null,\n\t\t\t\tfenceToken: Number(row.fence_token ?? 0),\n\t\t\t\tleaseExpiresAt: row.lease_expires_at ? new Date(row.lease_expires_at) : null,\n\t\t\t\tprocessing: row.processing === true,\n\t\t\t\trecoveryAttempts: Number(row.recovery_attempts ?? 0),\n\t\t\t\tupdatedAt: row.updated_at ? new Date(row.updated_at) : new Date(0),\n\t\t\t}\n\t\t},\n\t\t// biome-ignore lint/complexity/useMaxParams: lease primitive signature (jobId, fenceToken, ttlMs, now)\n\t\trenew: async (jobId, fenceToken, ttlMs, now): Promise<JobLeaseResult> => {\n\t\t\tconst res = await db.query(\n\t\t\t\t`UPDATE ${table} SET lease_expires_at = $1\n\t\t\t\t WHERE id = $2 AND fence_token = $3\n\t\t\t\t RETURNING id`,\n\t\t\t\t[leaseExpiry(now, ttlMs), jobId, fenceToken]\n\t\t\t)\n\t\t\treturn { ok: res.rowCount === 1 }\n\t\t},\n\t\treleaseAllClaims: async (owner): Promise<{ released: number }> => {\n\t\t\tconst res = await db.query(\n\t\t\t\t`UPDATE ${table}\n\t\t\t\t SET processing = false, claimed_by = NULL, lease_expires_at = NULL, wait_until = NULL,\n\t\t\t\t recovery_attempts = COALESCE(recovery_attempts, 0) + 1,\n\t\t\t\t fence_token = COALESCE(fence_token, 0) + 1\n\t\t\t\t WHERE claimed_by = $1 AND processing = true\n\t\t\t\t RETURNING id`,\n\t\t\t\t[owner]\n\t\t\t)\n\t\t\treturn { released: res.rowCount ?? 0 }\n\t\t},\n\t\trequeue: async (jobId, now, fallbackMs): Promise<JobLeaseResult> => {\n\t\t\tconst res = await db.query(\n\t\t\t\t`UPDATE ${table}\n\t\t\t\t SET processing = false, lease_expires_at = NULL, claimed_by = NULL, wait_until = NULL,\n\t\t\t\t recovery_attempts = COALESCE(recovery_attempts, 0) + 1,\n\t\t\t\t fence_token = COALESCE(fence_token, 0) + 1\n\t\t\t\t WHERE id = $1 AND ${staleGuard}\n\t\t\t\t RETURNING id`,\n\t\t\t\t[jobId, now, new Date(now.getTime() - fallbackMs)]\n\t\t\t)\n\t\t\treturn { ok: res.rowCount === 1 }\n\t\t},\n\t\t// biome-ignore lint/complexity/useMaxParams: lease primitive signature (jobId, owner, ttlMs, now)\n\t\tstampClaim: async (jobId, owner, ttlMs, now): Promise<StampResult> => {\n\t\t\tconst res = await db.query(\n\t\t\t\t`UPDATE ${table}\n\t\t\t\t SET started_at = $1, claimed_by = $2, lease_expires_at = $3,\n\t\t\t\t fence_token = COALESCE(fence_token, 0) + 1\n\t\t\t\t WHERE id = $4 AND processing = true\n\t\t\t\t RETURNING fence_token`,\n\t\t\t\t[now, owner, leaseExpiry(now, ttlMs), jobId]\n\t\t\t)\n\t\t\tconst ok = res.rowCount === 1\n\t\t\treturn { fenceToken: ok ? Number(res.rows[0]?.fence_token) : 0, ok }\n\t\t},\n\t}\n}\n","import type { Payload } from 'payload'\n\nimport { createMongoJobLeaseStore } from './jobLeaseStore.mongo'\nimport { createPostgresJobLeaseStore } from './jobLeaseStore.postgres'\n\n/** A Payload job id: a string on Mongo (ObjectId), a number on Postgres (serial). */\nexport type JobId = number | string\n\n/** The result of a stamp (returns the new claim-generation fence token). */\nexport type StampResult = { ok: boolean; fenceToken: number }\n\n/** The result of a renew/requeue/dead-letter attempt. */\nexport type JobLeaseResult = { ok: boolean }\n\n/** The lease-relevant columns of one `payload-jobs` row (diagnostics and tests). */\nexport type JobLeaseRow = {\n\tprocessing: boolean\n\tleaseExpiresAt: Date | null\n\tclaimedBy: string | null\n\tfenceToken: number\n\trecoveryAttempts: number\n\tupdatedAt: Date\n}\n\n/** Arguments for dead-lettering, grouped to stay within the 3-parameter lint cap. */\nexport type DeadLetterArgs = {\n\tjobId: JobId\n\tnow: Date\n\tfallbackMs: number\n\terror: Record<string, unknown>\n}\n\n/**\n * A fenced lease over a single `payload-jobs` row. Every write is one atomic\n * conditional update at the database (Mongo single-document `findOneAndUpdate`, or\n * Postgres `UPDATE ... WHERE <guard> RETURNING`), so two contenders never both win.\n * Sibling to the Plan 1 locks `LeaseStore`; implemented per adapter because Payload's\n * `db.updateOne` drops the `where` predicate when an `id` is given.\n */\nexport interface JobLeaseStore {\n\t/** Stamp a freshly-claimed job (guarded on `processing = true`); bumps the fence token. */\n\tstampClaim: (jobId: JobId, owner: string, ttlMs: number, now: Date) => Promise<StampResult>\n\t/** Extend the lease iff this owner's fence token still matches. */\n\trenew: (jobId: JobId, fenceToken: number, ttlMs: number, now: Date) => Promise<JobLeaseResult>\n\t/** Requeue a stale orphan (guarded on `processing = true` AND stale); increments recoveryAttempts. */\n\trequeue: (jobId: JobId, now: Date, fallbackMs: number) => Promise<JobLeaseResult>\n\t/** Dead-letter a stale orphan at the recovery cap (same guard). */\n\tdeadLetter: (args: DeadLetterArgs) => Promise<JobLeaseResult>\n\t/**\n\t * Requeue every in-flight job currently claimed by `owner`, in one bulk write, for\n\t * graceful drain. Sets `processing: false`, clears the lease, increments\n\t * recoveryAttempts, and bumps the fence token so a revived worker's renew fails.\n\t * Returns how many rows were released. Unlike `requeue`, it does not require the\n\t * lease to be stale (the node owns these claims and is shutting down).\n\t */\n\treleaseAllClaims: (owner: string) => Promise<{ released: number }>\n\t/** Read the lease columns of a job row. */\n\tread: (jobId: JobId) => Promise<JobLeaseRow | null>\n}\n\n/** Build the job-lease store for the running adapter. Throws for an unsupported adapter. */\nexport const createJobLeaseStore = (payload: Payload): JobLeaseStore => {\n\tif (payload.db.name === 'mongoose') {\n\t\treturn createMongoJobLeaseStore(payload)\n\t}\n\tif (payload.db.name === 'postgres') {\n\t\treturn createPostgresJobLeaseStore(payload)\n\t}\n\tthrow new Error(`@10x-media/jobs reliability does not support db adapter \"${payload.db.name}\"`)\n}\n","import type { ResolvedReliabilityOptions } from './options'\n\n/**\n * Heartbeat mode renews a running job's lease from a side timer. Serverless mode\n * never renews (the function is hard-killed at maxDuration with no SIGTERM), so the\n * stamp encodes the platform limit and the sweeper recovers from it.\n */\nexport const isHeartbeatMode = (options: ResolvedReliabilityOptions): boolean =>\n\toptions.serverlessMaxDurationMs === null\n\n/**\n * The lease TTL stamped when a worker claims a job, and the grace used to age out a\n * claimed-but-never-stamped (null lease) job by its updatedAt. In serverless mode\n * this is the platform hard-kill duration; otherwise the configured job lease TTL.\n */\nexport const initialLeaseTtlMs = (options: ResolvedReliabilityOptions): number =>\n\toptions.serverlessMaxDurationMs ?? options.jobLeaseTtlMs\n","/** What the sweeper does with a reclaimed orphan. */\nexport type RecoveryDecision = 'deadLetter' | 'requeue'\n\n/**\n * Requeue an orphaned job while it is below the recovery cap; dead-letter once it\n * reaches the cap, to stop a poison job from thrashing the queue. `recoveryAttempts`\n * is the count before this pass (a requeue increments it). `maxRecoveries` of 0\n * dead-letters on the first orphan.\n */\nexport const decideRecovery = (\n\trecoveryAttempts: number,\n\tmaxRecoveries: number\n): RecoveryDecision => (recoveryAttempts < maxRecoveries ? 'requeue' : 'deadLetter')\n","import type { Payload, Where } from 'payload'\nimport { getCurrentDate } from 'payload'\n\nimport { createJobLeaseStore, type JobId, type JobLeaseStore } from './jobLeaseStore'\nimport { initialLeaseTtlMs } from './leaseMode'\nimport type { ResolvedReliabilityOptions } from './options'\nimport { decideRecovery } from './recoveryDecision'\n\nconst JOBS_SLUG = 'payload-jobs'\n\n/** What one sweep pass did. */\nexport type SweepResult = { scanned: number; requeued: number; deadLettered: number }\n\nexport type RunSweepArgs = {\n\tpayload: Payload\n\toptions: ResolvedReliabilityOptions\n\t/** Reuse a store (tests); built from `payload` otherwise. */\n\tstore?: JobLeaseStore\n\t/** The instant the pass runs at; defaults to the swappable clock. */\n\tnow?: Date\n\t/** Max candidates per pass. Default 100. */\n\tlimit?: number\n\t/** Leadership gate. When false the pass is a no-op. Default true. */\n\tisLeader?: boolean\n}\n\n/** The dead-letter error payload written when a job reaches the recovery cap. */\nconst deadLetterError = (attempts: number): Record<string, unknown> => ({\n\tcancelled: false,\n\tmessage: `@10x-media/jobs sweeper: dead-lettered after reaching the recovery cap (${attempts} attempts)`,\n\trecovered: false,\n})\n\n// The dev app compiles this file with generated types that do not include the\n// reliability fields, so reach `payload.find` through a slug-agnostic signature\n// (same pattern as registerReliability's create cast).\ntype JobsFinder = (args: {\n\tcollection: string\n\twhere?: Where\n\tlimit?: number\n\tdepth?: number\n\tpagination?: boolean\n}) => Promise<{ docs: Array<{ id: JobId; recoveryAttempts?: number }> }>\n\n/**\n * One sweep pass: find stale `processing: true` orphans and either requeue them\n * (below the recovery cap) or dead-letter them (at the cap), each through a fenced\n * conditional write that re-checks staleness, so a job that renewed between the find\n * and the write is skipped and two overlapping sweepers never both reclaim the same\n * orphan. Gated by leadership: callers pass `isLeader` from the Plan 1 sweeper lease.\n */\nexport const runSweep = async (args: RunSweepArgs): Promise<SweepResult> => {\n\tconst { isLeader = true, limit = 100, options, payload } = args\n\tconst result: SweepResult = { deadLettered: 0, requeued: 0, scanned: 0 }\n\tif (!isLeader) {\n\t\treturn result\n\t}\n\n\tconst now = args.now ?? getCurrentDate()\n\tconst store = args.store ?? createJobLeaseStore(payload)\n\tconst fallbackMs = initialLeaseTtlMs(options)\n\tconst cutoff = new Date(now.getTime() - fallbackMs).toISOString()\n\n\tconst where: Where = {\n\t\tand: [\n\t\t\t{ processing: { equals: true } },\n\t\t\t{ completedAt: { exists: false } },\n\t\t\t{ hasError: { not_equals: true } },\n\t\t\t{\n\t\t\t\tor: [\n\t\t\t\t\t{ leaseExpiresAt: { less_than: now.toISOString() } },\n\t\t\t\t\t{\n\t\t\t\t\t\tand: [{ leaseExpiresAt: { exists: false } }, { updatedAt: { less_than: cutoff } }],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t}\n\n\tconst find = payload.find as unknown as JobsFinder\n\tconst { docs } = await find({ collection: JOBS_SLUG, depth: 0, limit, where })\n\tresult.scanned = docs.length\n\n\tfor (const doc of docs) {\n\t\tconst attempts = typeof doc.recoveryAttempts === 'number' ? doc.recoveryAttempts : 0\n\t\tif (decideRecovery(attempts, options.maxRecoveries) === 'requeue') {\n\t\t\tif ((await store.requeue(doc.id, now, fallbackMs)).ok) {\n\t\t\t\tresult.requeued += 1\n\t\t\t}\n\t\t} else if (\n\t\t\t(await store.deadLetter({ error: deadLetterError(attempts), fallbackMs, jobId: doc.id, now }))\n\t\t\t\t.ok\n\t\t) {\n\t\t\tresult.deadLettered += 1\n\t\t}\n\t}\n\n\treturn result\n}\n","/** Cluster-wide pause state: a global pause plus a set of paused queue names. */\nexport type PauseState = { global: boolean; queues: string[] }\n\n/** The default (nothing paused) state. */\nexport const emptyPauseState = (): PauseState => ({ global: false, queues: [] })\n\n/** Pause everything (no queue) or a single queue (idempotent). */\nexport const applyPause = (state: PauseState, queue: string | undefined): PauseState => {\n\tif (queue === undefined) {\n\t\treturn { ...state, global: true }\n\t}\n\treturn state.queues.includes(queue) ? state : { ...state, queues: [...state.queues, queue] }\n}\n\n/** Resume everything (no queue, clears the global flag) or a single queue. */\nexport const applyResume = (state: PauseState, queue: string | undefined): PauseState => {\n\tif (queue === undefined) {\n\t\treturn { ...state, global: false }\n\t}\n\treturn { ...state, queues: state.queues.filter((q) => q !== queue) }\n}\n\n/** Whether `queue` is currently paused (a global pause covers every queue). */\nexport const isPaused = (state: PauseState, queue: string): boolean =>\n\tstate.global || state.queues.includes(queue)\n","import type { Payload } from 'payload'\n\nimport { applyPause, applyResume, emptyPauseState, isPaused, type PauseState } from './pauseState'\n\nconst PAUSE_KEY = '@10x-media/jobs:pause-state'\n\n/** A durable, cluster-wide pause store backed by `payload.kv`. */\nexport type PauseStore = {\n\tpause: (queue?: string) => Promise<void>\n\tresume: (queue?: string) => Promise<void>\n\tgetState: () => Promise<PauseState>\n\tisPaused: (queue: string) => Promise<boolean>\n}\n\n/**\n * Build the pause store over `payload.kv` (always available, durable, cluster-wide).\n * Pause and resume read-modify-write the single state value; this is last-writer-wins\n * (kv has no atomic compare-and-set), which is acceptable for rare admin actions.\n */\nexport const createPauseStore = (payload: Payload): PauseStore => {\n\tconst getState = async (): Promise<PauseState> =>\n\t\t(await payload.kv.get<PauseState>(PAUSE_KEY)) ?? emptyPauseState()\n\n\treturn {\n\t\tgetState,\n\t\tisPaused: async (queue) => isPaused(await getState(), queue),\n\t\tpause: async (queue) => {\n\t\t\tawait payload.kv.set(PAUSE_KEY, applyPause(await getState(), queue))\n\t\t},\n\t\tresume: async (queue) => {\n\t\t\tawait payload.kv.set(PAUSE_KEY, applyResume(await getState(), queue))\n\t\t},\n\t}\n}\n","import type { Payload, Where } from 'payload'\n\nconst JOBS_SLUG = 'payload-jobs'\nconst STATS_SLUG = 'payload-jobs-stats'\n\n/** Per-queue health counts plus the last scheduled run. */\nexport type QueueHealth = {\n\tqueue: string\n\tpending: number\n\tprocessing: number\n\tfailed: number\n\trecovered: number\n\tlastScheduledRun: string | null\n}\n\nexport type QueueHealthReport = {\n\ttotals: { pending: number; processing: number; failed: number; recovered: number }\n\toldestPendingAgeMs: number | null\n\tqueues: QueueHealth[]\n}\n\nexport type GetQueueHealthOptions = {\n\t/** Queues to break out per-queue. Default ['default']. */\n\tqueues?: string[]\n\t/** Include the recovered count (requires the reliability `recoveryAttempts` field). */\n\tincludeRecovered?: boolean\n\t/** Reference time for the oldest-pending age. Default now. */\n\tnow?: Date\n}\n\n// The dev app compiles this file with generated types lacking our custom fields, so\n// reach the data layer through slug-agnostic signatures (same pattern as the sweeper).\ntype Counter = (args: { collection: string; where?: Where }) => Promise<{ totalDocs: number }>\ntype Finder = (args: {\n\tcollection: string\n\twhere?: Where\n\tlimit?: number\n\tsort?: string\n\tdepth?: number\n}) => Promise<{ docs: Array<{ createdAt?: string }> }>\ntype GlobalReader = (args: { slug: string }) => Promise<unknown>\n\nconst queueClause = (queue?: string): Where[] => (queue ? [{ queue: { equals: queue } }] : [])\n\nconst pendingWhere = (queue?: string): Where => ({\n\tand: [\n\t\t{ completedAt: { exists: false } },\n\t\t{ hasError: { not_equals: true } },\n\t\t{ processing: { equals: false } },\n\t\t...queueClause(queue),\n\t],\n})\nconst processingWhere = (queue?: string): Where => ({\n\tand: [{ processing: { equals: true } }, ...queueClause(queue)],\n})\nconst failedWhere = (queue?: string): Where => ({\n\tand: [{ hasError: { equals: true } }, ...queueClause(queue)],\n})\nconst recoveredWhere = (queue?: string): Where => ({\n\tand: [{ recoveryAttempts: { greater_than: 0 } }, ...queueClause(queue)],\n})\n\nconst readStats = async (payload: Payload): Promise<unknown> => {\n\tconst db = payload.db as unknown as { findGlobal: GlobalReader }\n\ttry {\n\t\treturn await db.findGlobal({ slug: STATS_SLUG })\n\t} catch {\n\t\treturn null\n\t}\n}\n\ntype StatsShape = {\n\tstats?: {\n\t\tscheduledRuns?: {\n\t\t\tqueues?: Record<\n\t\t\t\tstring,\n\t\t\t\t{\n\t\t\t\t\ttasks?: Record<string, { lastScheduledRun?: string }>\n\t\t\t\t\tworkflows?: Record<string, { lastScheduledRun?: string }>\n\t\t\t\t}\n\t\t\t>\n\t\t}\n\t}\n}\n\nconst lastScheduledRunFor = (stats: unknown, queue: string): string | null => {\n\tconst entry = (stats as StatsShape)?.stats?.scheduledRuns?.queues?.[queue]\n\tif (!entry) {\n\t\treturn null\n\t}\n\tconst runs = [...Object.values(entry.tasks ?? {}), ...Object.values(entry.workflows ?? {})]\n\t\t.map((r) => r.lastScheduledRun)\n\t\t.filter((r): r is string => typeof r === 'string')\n\treturn runs.length > 0 ? (runs.sort().at(-1) ?? null) : null\n}\n\n/**\n * Aggregate queue health via `payload.count` per state (pending, processing, failed,\n * and, when reliability is on, recovered), plus the oldest-pending age and the last\n * scheduled run per queue. Reuses Payload's own run-selector predicates. The stats\n * global is read through `payload.db.findGlobal` inside a try/catch because that call\n * throws when the global does not exist (no schedule has run).\n */\nexport const getQueueHealth = async (\n\tpayload: Payload,\n\toptions: GetQueueHealthOptions = {}\n): Promise<QueueHealthReport> => {\n\tconst queues = options.queues ?? ['default']\n\tconst includeRecovered = options.includeRecovered ?? false\n\tconst count = payload.count as unknown as Counter\n\tconst find = payload.find as unknown as Finder\n\tconst countWhere = async (where: Where): Promise<number> =>\n\t\t(await count({ collection: JOBS_SLUG, where })).totalDocs\n\n\tconst totals = {\n\t\tfailed: await countWhere(failedWhere()),\n\t\tpending: await countWhere(pendingWhere()),\n\t\tprocessing: await countWhere(processingWhere()),\n\t\trecovered: includeRecovered ? await countWhere(recoveredWhere()) : 0,\n\t}\n\n\tconst oldest = await find({\n\t\tcollection: JOBS_SLUG,\n\t\tdepth: 0,\n\t\tlimit: 1,\n\t\tsort: 'createdAt',\n\t\twhere: pendingWhere(),\n\t})\n\tconst oldestCreated = oldest.docs[0]?.createdAt\n\tconst nowMs = (options.now ?? new Date()).getTime()\n\tconst oldestPendingAgeMs = oldestCreated ? nowMs - new Date(oldestCreated).getTime() : null\n\n\tconst stats = await readStats(payload)\n\tconst perQueue: QueueHealth[] = []\n\tfor (const queue of queues) {\n\t\tperQueue.push({\n\t\t\tfailed: await countWhere(failedWhere(queue)),\n\t\t\tlastScheduledRun: lastScheduledRunFor(stats, queue),\n\t\t\tpending: await countWhere(pendingWhere(queue)),\n\t\t\tprocessing: await countWhere(processingWhere(queue)),\n\t\t\tqueue,\n\t\t\trecovered: includeRecovered ? await countWhere(recoveredWhere(queue)) : 0,\n\t\t})\n\t}\n\n\treturn { oldestPendingAgeMs, queues: perQueue, totals }\n}\n","import type { Where } from 'payload'\n\nimport type { PauseState } from './pauseState'\n\n/** A single `payload.jobs.run` target, honoring pause. */\nexport type RunTarget = { allQueues?: boolean; queue?: string; where?: Where }\n\n/**\n * Compute the run targets for one cycle, given the worker's configured queues (or\n * undefined for all queues) and the current pause state. A global pause yields no\n * targets. A specific queue list drops the paused queues. All-queues running excludes\n * paused queues via `not_in` paired with `allQueues: true` (the exclusion requires\n * allQueues, because Payload's built-in single-queue filter only applies otherwise).\n */\nexport const runTargetsForPause = (\n\tqueues: string[] | undefined,\n\tstate: PauseState\n): RunTarget[] => {\n\tif (state.global) {\n\t\treturn []\n\t}\n\tif (queues && queues.length > 0) {\n\t\treturn queues.filter((queue) => !state.queues.includes(queue)).map((queue) => ({ queue }))\n\t}\n\tif (state.queues.length > 0) {\n\t\treturn [{ allQueues: true, where: { queue: { not_in: state.queues } } }]\n\t}\n\treturn [{ allQueues: true }]\n}\n","import type { Endpoint, PayloadRequest } from 'payload'\n\nimport { createJobLeaseStore } from '../reliability/jobLeaseStore'\nimport type { ResolvedReliabilityOptions } from '../reliability/options'\nimport { runSweep } from '../reliability/sweeper'\nimport type { JobAccess } from './access'\nimport { createPauseStore } from './pauseStore'\nimport { getQueueHealth } from './queueHealth'\nimport { runTargetsForPause } from './runTargets'\n\nexport type QueueEndpointDeps = {\n\taccess: JobAccess\n\tqueues: string[]\n\treliability: ResolvedReliabilityOptions | null\n}\n\nconst unauthorized = (): Response => Response.json({ message: 'Unauthorized' }, { status: 401 })\n\n/** GET queue health, grouped by queue. */\nexport const statusEndpoint = (deps: QueueEndpointDeps): Endpoint => ({\n\thandler: async (req: PayloadRequest) => {\n\t\tif (!(await deps.access({ req }))) {\n\t\t\treturn unauthorized()\n\t\t}\n\t\tconst report = await getQueueHealth(req.payload, {\n\t\t\tincludeRecovered: deps.reliability !== null,\n\t\t\tqueues: deps.queues,\n\t\t})\n\t\treturn Response.json(report, { status: 200 })\n\t},\n\tmethod: 'get',\n\tpath: '/queue-status',\n})\n\n/** GET a hardened, pause-aware run. Mirrors the native run params. */\nexport const runControlEndpoint = (deps: QueueEndpointDeps): Endpoint => ({\n\thandler: async (req: PayloadRequest) => {\n\t\tif (!(await deps.access({ req }))) {\n\t\t\treturn unauthorized()\n\t\t}\n\t\tconst query = req.query as {\n\t\t\tallQueues?: string\n\t\t\tdisableScheduling?: string\n\t\t\tlimit?: string\n\t\t\tqueue?: string\n\t\t\tsilent?: string\n\t\t}\n\t\tconst limit = query.limit ? Number(query.limit) : undefined\n\t\tconst silent = query.silent === 'true'\n\t\tconst state = await createPauseStore(req.payload).getState()\n\t\t// Mirror the native run scope: `allQueues` runs every queue, otherwise a single\n\t\t// queue (defaulting to `default`, as the native endpoint does). Pause is honored\n\t\t// either way via runTargetsForPause.\n\t\tconst requested = query.allQueues === 'true' ? undefined : [query.queue ?? 'default']\n\t\tconst targets = runTargetsForPause(requested, state)\n\n\t\tif (query.disableScheduling !== 'true') {\n\t\t\tawait req.payload.jobs.handleSchedules({ allQueues: true })\n\t\t}\n\t\tconst results = []\n\t\tfor (const target of targets) {\n\t\t\tresults.push(\n\t\t\t\tawait req.payload.jobs.run({\n\t\t\t\t\t...target,\n\t\t\t\t\t...(limit !== undefined ? { limit } : {}),\n\t\t\t\t\tsilent,\n\t\t\t\t})\n\t\t\t)\n\t\t}\n\t\treturn Response.json({ paused: state, ran: targets.length, results }, { status: 200 })\n\t},\n\tmethod: 'get',\n\tpath: '/queue-run',\n})\n\n/** GET a one-shot sweep for serverless (one cron invocation, so no leader election). */\nexport const sweepEndpoint = (deps: QueueEndpointDeps): Endpoint => ({\n\thandler: async (req: PayloadRequest) => {\n\t\tif (!(await deps.access({ req }))) {\n\t\t\treturn unauthorized()\n\t\t}\n\t\tif (!deps.reliability) {\n\t\t\treturn Response.json(\n\t\t\t\t{ message: 'reliability is not enabled; the sweeper is unavailable' },\n\t\t\t\t{ status: 400 }\n\t\t\t)\n\t\t}\n\t\tconst result = await runSweep({\n\t\t\tisLeader: true,\n\t\t\toptions: deps.reliability,\n\t\t\tpayload: req.payload,\n\t\t\tstore: createJobLeaseStore(req.payload),\n\t\t})\n\t\treturn Response.json(result, { status: 200 })\n\t},\n\tmethod: 'get',\n\tpath: '/queue-sweep',\n})\n","import type { Config } from 'payload'\n\nimport type { ResolvedReliabilityOptions } from '../reliability/options'\nimport {\n\ttype QueueEndpointDeps,\n\trunControlEndpoint,\n\tstatusEndpoint,\n\tsweepEndpoint,\n} from './endpoints'\nimport type { ResolvedQueueControlOptions } from './options'\n\n/**\n * Register the queue-control layer: harden the native run endpoint by setting\n * `jobs.access.run` to the configured checker, and add the status, hardened-run, and\n * sweep endpoints to `payload-jobs` through the same `jobsCollectionOverrides` seam the\n * reliability and observability layers use (composing, never clobbering).\n */\nexport const registerQueueControl = (\n\tconfig: Config,\n\toptions: ResolvedQueueControlOptions,\n\treliability: ResolvedReliabilityOptions | null\n): void => {\n\tconst deps: QueueEndpointDeps = { access: options.access, queues: options.queues, reliability }\n\tconst controlEndpoints = [statusEndpoint(deps), runControlEndpoint(deps), sweepEndpoint(deps)]\n\n\tconst existingOverride = config.jobs?.jobsCollectionOverrides\n\tconfig.jobs = {\n\t\t...config.jobs,\n\t\taccess: { ...config.jobs?.access, run: options.access },\n\t\tjobsCollectionOverrides: ({ defaultJobsCollection }) => {\n\t\t\tconst base = existingOverride\n\t\t\t\t? existingOverride({ defaultJobsCollection })\n\t\t\t\t: defaultJobsCollection\n\t\t\tconst baseEndpoints = Array.isArray(base.endpoints) ? base.endpoints : []\n\t\t\treturn { ...base, endpoints: [...baseEndpoints, ...controlEndpoints] }\n\t\t},\n\t}\n}\n","/** Tuning for the jobs reliability layer. All durations are milliseconds. */\nexport type ReliabilityOptions = {\n\t/** How long a worker's claim is valid before the sweeper may reclaim it. Default 300000 (5 min). */\n\tjobLeaseTtlMs?: number\n\t/** How often a running worker renews its job lease. Default jobLeaseTtlMs / 3. */\n\theartbeatIntervalMs?: number\n\t/** How often the sweeper scans for orphaned jobs. Default 60000. */\n\tsweepIntervalMs?: number\n\t/** How many times the sweeper requeues a job before dead-lettering it. Default 3. */\n\tmaxRecoveries?: number\n\t/** How long a leadership lease (scheduler/sweeper) is valid. Default 30000. */\n\tleaderLeaseTtlMs?: number\n\t/** A stable id for this node/process. Defaults to a generated value at runtime. */\n\tleaderId?: string\n\t/**\n\t * Serverless mode: when set, job staleness derives from this platform hard-kill\n\t * duration instead of a heartbeat (heartbeats are meaningless when the function\n\t * is killed at maxDuration with no SIGTERM).\n\t */\n\tserverless?: { maxDurationMs: number }\n\t/**\n\t * Recommend (true) Payload's `enableConcurrencyControl` for app-level mutual\n\t * exclusion under multi-node. Documentation-facing; consumed in a later plan.\n\t */\n\trequireConcurrencyControl?: boolean\n}\n\n/** Reliability options with every value resolved. `null` means reliability is off. */\nexport type ResolvedReliabilityOptions = {\n\tjobLeaseTtlMs: number\n\theartbeatIntervalMs: number\n\tsweepIntervalMs: number\n\tmaxRecoveries: number\n\tleaderLeaseTtlMs: number\n\tleaderId: string | null\n\tserverlessMaxDurationMs: number | null\n\trequireConcurrencyControl: boolean\n}\n\n/** Resolve user reliability options to a fully-defaulted object, or `null` when disabled. */\nexport const resolveReliabilityOptions = (\n\toptions: ReliabilityOptions | false | undefined\n): ResolvedReliabilityOptions | null => {\n\tif (options === undefined || options === false) {\n\t\treturn null\n\t}\n\tconst jobLeaseTtlMs = options.jobLeaseTtlMs ?? 300_000\n\treturn {\n\t\theartbeatIntervalMs: options.heartbeatIntervalMs ?? Math.floor(jobLeaseTtlMs / 3),\n\t\tjobLeaseTtlMs,\n\t\tleaderId: options.leaderId ?? null,\n\t\tleaderLeaseTtlMs: options.leaderLeaseTtlMs ?? 30_000,\n\t\tmaxRecoveries: options.maxRecoveries ?? 3,\n\t\trequireConcurrencyControl: options.requireConcurrencyControl ?? false,\n\t\tserverlessMaxDurationMs: options.serverless?.maxDurationMs ?? null,\n\t\tsweepIntervalMs: options.sweepIntervalMs ?? 60_000,\n\t}\n}\n","import type { ResolvedReliabilityOptions } from './options'\n\n/**\n * When `reliability.requireConcurrencyControl` is set, refuse to start unless\n * Payload's own `jobs.enableConcurrencyControl` is on. The at-least-once contract\n * relies on it for app-level mutual exclusion under multi-node, and enabling it\n * changes the jobs schema (adds a `concurrencyKey` field), so we fail loudly rather\n * than silently mutate the adopter's schema. The config parameter is a structural\n * subset (Payload's `Config` satisfies it), which keeps the function trivial to unit\n * test with a plain object literal.\n */\nexport const enforceConcurrencyControl = (\n\tconfig: { jobs?: { enableConcurrencyControl?: boolean } },\n\toptions: ResolvedReliabilityOptions\n): void => {\n\tif (!options.requireConcurrencyControl) {\n\t\treturn\n\t}\n\tif (config.jobs?.enableConcurrencyControl === true) {\n\t\treturn\n\t}\n\tthrow new Error(\n\t\t'@10x-media/jobs: reliability.requireConcurrencyControl is set but jobs.enableConcurrencyControl is not true. ' +\n\t\t\t'Enable it in your Payload config (it adds a concurrencyKey field, so run a migration) or unset requireConcurrencyControl.'\n\t)\n}\n\n/** A minimal store for at-most-once side-effect guarding, keyed by a stable idempotency key. */\nexport interface IdempotencyStore {\n\t/** True if `key` was already marked done. */\n\thas: (key: string) => Promise<boolean>\n\t/** Mark `key` done. Ideally written in the same transaction as the side effect. */\n\tmark: (key: string) => Promise<void>\n}\n\n/**\n * Wrap a job handler so its side effect runs at most once per idempotency key, even\n * when at-least-once delivery re-runs the job. The race this guards is not only\n * redelivery: when the sweeper requeues a job whose lease expired while it was still\n * running, the original execution cannot be aborted (Payload exposes no AbortSignal),\n * so a second worker can run the handler concurrently with the first. Key on the\n * stable unit of work, never the job id, so both executions resolve to the same key.\n * The check and the mark are the caller's to make transactional (Payload's queue and\n * the app data share one database, which makes that natural); this helper only\n * sequences them around the handler. A skipped run returns `{ output: {} }`.\n */\nexport const withIdempotencyKey = <A>(\n\thandler: (args: A) => Promise<unknown>,\n\tidem: { keyFor: (args: A) => string; store: IdempotencyStore }\n): ((args: A) => Promise<unknown>) => {\n\treturn async (args: A): Promise<unknown> => {\n\t\tconst key = idem.keyFor(args)\n\t\tif (await idem.store.has(key)) {\n\t\t\treturn { output: {} }\n\t\t}\n\t\tconst out = await handler(args)\n\t\tawait idem.store.mark(key)\n\t\treturn out\n\t}\n}\n","import type { Field } from 'payload'\n\n/**\n * Fields added to the built-in `payload-jobs` collection (via jobsCollectionOverrides)\n * when reliability is enabled. `leaseExpiresAt` is the liveness signal renewed by the\n * worker heartbeat; the sweeper reclaims a job when `leaseExpiresAt < now`. All are\n * sidebar, read-only-in-admin diagnostics (the runtime, not a human, writes them).\n */\nexport const reliabilityJobFields = (): Field[] => [\n\t{\n\t\tname: 'startedAt',\n\t\ttype: 'date',\n\t\tadmin: { position: 'sidebar', readOnly: true },\n\t\tindex: true,\n\t},\n\t{\n\t\tname: 'leaseExpiresAt',\n\t\ttype: 'date',\n\t\tadmin: { position: 'sidebar', readOnly: true },\n\t\tindex: true,\n\t},\n\t{\n\t\tname: 'claimedBy',\n\t\ttype: 'text',\n\t\tadmin: { position: 'sidebar', readOnly: true },\n\t\tindex: true,\n\t},\n\t{\n\t\tname: 'fenceToken',\n\t\ttype: 'number',\n\t\tadmin: { position: 'sidebar', readOnly: true },\n\t},\n\t{\n\t\tname: 'recoveryAttempts',\n\t\ttype: 'number',\n\t\tadmin: { position: 'sidebar', readOnly: true },\n\t\tdefaultValue: 0,\n\t},\n]\n","import type { Config, Payload } from 'payload'\nimport { getCurrentDate } from 'payload'\n\nimport { createJobLeaseStore, type JobId, type JobLeaseStore } from './jobLeaseStore'\nimport { initialLeaseTtlMs, isHeartbeatMode } from './leaseMode'\nimport type { ResolvedReliabilityOptions } from './options'\n\n/** The slice of a handler's args the heartbeat needs. Real handlers pass a superset. */\nexport type HeartbeatHandlerArgs = {\n\tjob: { id: JobId }\n\treq: { payload: Payload }\n}\n\n/** A job handler reduced to what the heartbeat sees. */\nexport type JobHandler = (args: HeartbeatHandlerArgs) => unknown\n\nexport type WithHeartbeatArgs = {\n\thandler: JobHandler\n\toptions: ResolvedReliabilityOptions\n\townerId: string\n\tgetStore: (payload: Payload) => JobLeaseStore\n\t/** Test/diagnostic seam: invoked once if a fenced renew finds the claim was lost. */\n\tonLeaseLost?: (jobId: JobId) => void\n}\n\n/**\n * Wrap one job handler so the job keeps its lease fresh while it runs. On entry the\n * wrapper stamps the just-claimed row (fenced on `processing = true`) and, in\n * heartbeat mode, renews the lease on a self-scheduling timer at\n * `heartbeatIntervalMs`. A renew that matches nothing means the sweeper reclaimed the\n * job (its fence token moved): the wrapper records the loss, warns, and stops\n * renewing, but cannot abort an opaque handler (Payload exposes no AbortSignal), so\n * correctness under that race is the idempotency contract's job. The timer is always\n * cleared in `finally`. If the initial stamp fails (already completed, cancelled, or\n * reclaimed) the handler still runs, just without a heartbeat.\n */\nexport const withHeartbeat = (args: WithHeartbeatArgs): JobHandler => {\n\tconst { getStore, handler, onLeaseLost, options, ownerId } = args\n\tconst ttlMs = initialLeaseTtlMs(options)\n\tconst beats = isHeartbeatMode(options)\n\tconst intervalMs = options.heartbeatIntervalMs\n\n\treturn async (handlerArgs: HeartbeatHandlerArgs): Promise<unknown> => {\n\t\tconst payload = handlerArgs.req.payload\n\t\tconst jobId = handlerArgs.job.id\n\t\tconst store = getStore(payload)\n\t\tconst stamp = await store.stampClaim(jobId, ownerId, ttlMs, getCurrentDate())\n\t\tif (!stamp.ok) {\n\t\t\treturn handler(handlerArgs)\n\t\t}\n\n\t\tconst fence = stamp.fenceToken\n\t\tlet done = false\n\t\tlet timer: ReturnType<typeof setTimeout> | undefined\n\n\t\tconst tick = async (): Promise<void> => {\n\t\t\tif (done) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tlet ok = true\n\t\t\ttry {\n\t\t\t\tok = (await store.renew(jobId, fence, ttlMs, getCurrentDate())).ok\n\t\t\t} catch (err) {\n\t\t\t\tpayload.logger?.warn(\n\t\t\t\t\t`@10x-media/jobs: heartbeat renew error for job ${jobId}: ${String(err)}`\n\t\t\t\t)\n\t\t\t\tschedule()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!ok) {\n\t\t\t\tpayload.logger?.warn(`@10x-media/jobs: lost lease for job ${jobId} (reclaimed)`)\n\t\t\t\tonLeaseLost?.(jobId)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tschedule()\n\t\t}\n\n\t\tfunction schedule(): void {\n\t\t\tif (done) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttimer = setTimeout(() => {\n\t\t\t\tvoid tick()\n\t\t\t}, intervalMs)\n\t\t}\n\n\t\tif (beats) {\n\t\t\tschedule()\n\t\t}\n\n\t\ttry {\n\t\t\treturn await handler(handlerArgs)\n\t\t} finally {\n\t\t\tdone = true\n\t\t\tif (timer) {\n\t\t\t\tclearTimeout(timer)\n\t\t\t}\n\t\t}\n\t}\n}\n\ntype WrappableEntry = { handler?: unknown }\n\n/**\n * Wrap every task and workflow handler on the config with the heartbeat. Only\n * function handlers are wrapped (Payload also allows a string path for controlled\n * handlers, which we leave alone). One job-lease store is reused per Payload instance\n * via a WeakMap. All other task and workflow properties are preserved.\n */\nexport const registerHeartbeat = (\n\tconfig: Config,\n\toptions: ResolvedReliabilityOptions,\n\townerId: string\n): void => {\n\tconst jobs = config.jobs\n\tif (!jobs) {\n\t\treturn\n\t}\n\n\tconst storeCache = new WeakMap<Payload, JobLeaseStore>()\n\tconst getStore = (payload: Payload): JobLeaseStore => {\n\t\tconst hit = storeCache.get(payload)\n\t\tif (hit) {\n\t\t\treturn hit\n\t\t}\n\t\tconst store = createJobLeaseStore(payload)\n\t\tstoreCache.set(payload, store)\n\t\treturn store\n\t}\n\n\tconst wrapEntry = <T extends WrappableEntry>(entry: T): T => {\n\t\tif (typeof entry.handler !== 'function') {\n\t\t\treturn entry\n\t\t}\n\t\tconst wrapped = withHeartbeat({\n\t\t\tgetStore,\n\t\t\thandler: entry.handler as unknown as JobHandler,\n\t\t\toptions,\n\t\t\townerId,\n\t\t})\n\t\treturn { ...entry, handler: wrapped as unknown as T['handler'] }\n\t}\n\n\tif (Array.isArray(jobs.tasks)) {\n\t\tjobs.tasks = jobs.tasks.map(wrapEntry) as typeof jobs.tasks\n\t}\n\tif (Array.isArray(jobs.workflows)) {\n\t\tjobs.workflows = jobs.workflows.map(wrapEntry) as typeof jobs.workflows\n\t}\n}\n","import type { CollectionConfig } from 'payload'\n\n/** Slug of the plugin-owned leases collection. Table name: payload_jobs_locks. */\nexport const JOBS_LOCKS_SLUG = 'payload-jobs-locks'\n\n/** The two singleton leadership roles. */\nexport const LEADER_ROLES = ['scheduler', 'sweeper'] as const\nexport type LeaderRole = (typeof LEADER_ROLES)[number]\n\n/**\n * A hidden collection holding one row per leadership role. Acquire/renew/steal are\n * conditional updates against these rows (see the lease store). Not edit-locked,\n * not shown in admin, and access is closed by default (the plugin mutates it\n * directly through the db adapter, never the REST/GraphQL API).\n */\nexport const buildJobsLocksCollection = (): CollectionConfig => ({\n\tslug: JOBS_LOCKS_SLUG,\n\taccess: {\n\t\tcreate: () => false,\n\t\tdelete: () => false,\n\t\tread: () => false,\n\t\tupdate: () => false,\n\t},\n\tadmin: { hidden: true },\n\tfields: [\n\t\t{ name: 'role', type: 'text', index: true, required: true, unique: true },\n\t\t{ name: 'owner', type: 'text' },\n\t\t{ name: 'leaseExpiresAt', type: 'date' },\n\t\t{ name: 'fenceToken', type: 'number', defaultValue: 0, required: true },\n\t],\n\tlockDocuments: false,\n})\n","import { hostname } from 'node:os'\n\n/**\n * A stable-per-process identity for job claims and leadership. An explicit\n * `leaderId` wins; otherwise derive `hostname:pid`, which is stable within a process\n * and distinguishes nodes in a cluster.\n */\nexport const resolveNodeId = (leaderId: string | null): string =>\n\tleaderId ?? `${hostname()}:${process.pid}`\n","import { type Config, type Payload, ValidationError } from 'payload'\n\nimport { enforceConcurrencyControl } from './concurrencyContract'\nimport { reliabilityJobFields } from './fields'\nimport { registerHeartbeat } from './heartbeat'\nimport { buildJobsLocksCollection, JOBS_LOCKS_SLUG, LEADER_ROLES } from './locksCollection'\nimport { resolveNodeId } from './nodeId'\nimport type { ResolvedReliabilityOptions } from './options'\n\n/** Idempotently ensure one lock row per leadership role. Race-safe via the unique `role`. */\nconst ensureLockRows = async (payload: Payload): Promise<void> => {\n\t// The locks collection is registered by this plugin at runtime, so a host app's\n\t// generated Payload types need not include it; create through a slug-agnostic signature.\n\tconst create = payload.create as unknown as (args: {\n\t\tcollection: string\n\t\tdata: Record<string, unknown>\n\t\toverrideAccess?: boolean\n\t}) => Promise<unknown>\n\tfor (const role of LEADER_ROLES) {\n\t\ttry {\n\t\t\tawait create({\n\t\t\t\tcollection: JOBS_LOCKS_SLUG,\n\t\t\t\tdata: { fenceToken: 0, leaseExpiresAt: null, owner: null, role },\n\t\t\t\toverrideAccess: true,\n\t\t\t})\n\t\t} catch (err) {\n\t\t\t// Only a duplicate role (row already seeded by another node/boot) is expected.\n\t\t\tif (!(err instanceof ValidationError)) {\n\t\t\t\tthrow err\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Register the reliability layer on the incoming config: add diagnostic fields to\n * `payload-jobs` through the same `jobsCollectionOverrides` seam the observability\n * layer uses (composing, never clobbering), add the locks collection, and ensure the\n * lock rows at init (preserving any host onInit).\n */\nexport const registerReliability = (config: Config, options: ResolvedReliabilityOptions): void => {\n\tenforceConcurrencyControl(config, options)\n\n\tconst existingOverride = config.jobs?.jobsCollectionOverrides\n\tconfig.jobs = {\n\t\t...config.jobs,\n\t\tjobsCollectionOverrides: ({ defaultJobsCollection }) => {\n\t\t\tconst base = existingOverride\n\t\t\t\t? existingOverride({ defaultJobsCollection })\n\t\t\t\t: defaultJobsCollection\n\t\t\treturn { ...base, fields: [...base.fields, ...reliabilityJobFields()] }\n\t\t},\n\t}\n\n\tconfig.collections = [...(config.collections ?? []), buildJobsLocksCollection()]\n\n\tconst previousOnInit = config.onInit\n\tconfig.onInit = async (payload) => {\n\t\tawait previousOnInit?.(payload)\n\t\tawait ensureLockRows(payload)\n\t}\n\n\tregisterHeartbeat(config, options, resolveNodeId(options.leaderId))\n}\n","import type { JobsConfig } from 'payload'\n\n/**\n * Payload's per-cron autoRun config. Payload 3.85.0 does not re-export the\n * `AutorunCronConfig` type from its package root, so derive it from the array branch of\n * the publicly exported `JobsConfig['autoRun']` (which Payload types as that element).\n */\nexport type AutorunCronConfig = Extract<NonNullable<JobsConfig['autoRun']>, unknown[]>[number]\n\n/** One logical queue's autoRun cadence. */\nexport type AutoRunQueueConfig = {\n\tqueue: string\n\t/** Cron cadence for this queue. Default every minute. */\n\tcron?: string\n\t/** Max jobs claimed per tick. Default 10. */\n\tlimit?: number\n}\n\nexport type AutoRunConfigOptions = {\n\t/** One entry per logical queue. Default a single `default` queue. */\n\tqueues?: AutoRunQueueConfig[]\n\t/** Suppress per-run info logging. Default true. */\n\tsilent?: boolean\n\t/**\n\t * Disable native auto-scheduling on these crons. Default false. Set true when a\n\t * `createWorker` owns scheduling (multi-node), so the cron only runs jobs.\n\t */\n\tdisableScheduling?: boolean\n}\n\nconst DEFAULT_CRON = '* * * * *'\nconst DEFAULT_LIMIT = 10\n\n/**\n * Build a production `jobs.autoRun` array: one Croner config per queue, silent by\n * default, with Payload's own `protect: true` preventing overlap. This is the simple\n * single-node and serverless-adjacent path where native autoRun safely handles both\n * scheduling and running in one process. Multi-node deployments use `createWorker`\n * instead, because native autoRun cannot gate scheduling to one elected leader (its\n * only dynamic lever, `shouldAutoRun`, permanently stops the cron rather than pausing).\n */\nexport const autoRunConfig = (options: AutoRunConfigOptions = {}): AutorunCronConfig[] => {\n\tconst { disableScheduling = false, queues = [{ queue: 'default' }], silent = true } = options\n\treturn queues.map((q) => ({\n\t\tcron: q.cron ?? DEFAULT_CRON,\n\t\tdisableScheduling,\n\t\tlimit: q.limit ?? DEFAULT_LIMIT,\n\t\tqueue: q.queue,\n\t\tsilent,\n\t}))\n}\n","export type DrainDeps = {\n\t/** Stop the worker's interval loops (stop claiming new jobs). */\n\tstopLoops: () => void\n\t/** Count this node's in-flight jobs (processing and claimed by it). */\n\tcountInFlight: () => Promise<number>\n\t/** Requeue this node's remaining in-flight jobs. Returns how many were released. */\n\trequeueStragglers: () => Promise<number>\n\t/** Release the held scheduler and sweeper leadership leases. */\n\treleaseLeadership: () => Promise<void>\n\t/** Destroy the Payload instance (stops crons, closes the DB). */\n\tdestroy: () => Promise<void>\n\t/** Wall-clock milliseconds (real in production, virtual in tests). */\n\tnow: () => number\n\t/** Wait `ms` (real in production, virtual in tests). */\n\tsleep: (ms: number) => Promise<void>\n\tlogger?: { info?: (m: string) => void }\n}\n\nexport type DrainOptions = {\n\t/** Max wall-clock time to await in-flight jobs before requeuing stragglers. */\n\tdrainTimeoutMs: number\n\t/** How often to re-count in-flight jobs while draining. */\n\tpollIntervalMs: number\n}\n\nexport type DrainResult = {\n\tinFlightAtStart: number\n\tremaining: number\n\trequeued: number\n\ttimedOut: boolean\n}\n\n/**\n * Run the graceful-drain sequence: stop claiming, await this node's in-flight jobs up\n * to a wall-clock budget, requeue any stragglers, release leadership, and destroy. The\n * clock (`now`/`sleep`) is injected so tests drive it deterministically without real\n * waiting. Always releases leadership and destroys, even when nothing was in flight.\n */\nexport const drainWorker = async (deps: DrainDeps, options: DrainOptions): Promise<DrainResult> => {\n\tdeps.stopLoops()\n\tconst start = deps.now()\n\tconst inFlightAtStart = await deps.countInFlight()\n\tlet remaining = inFlightAtStart\n\twhile (remaining > 0 && deps.now() - start < options.drainTimeoutMs) {\n\t\tawait deps.sleep(options.pollIntervalMs)\n\t\tremaining = await deps.countInFlight()\n\t}\n\tconst timedOut = remaining > 0\n\tconst requeued = timedOut ? await deps.requeueStragglers() : 0\n\tawait deps.releaseLeadership()\n\tawait deps.destroy()\n\tdeps.logger?.info?.(\n\t\t`@10x-media/jobs: drain complete (started ${inFlightAtStart}, requeued ${requeued}, timedOut ${timedOut})`\n\t)\n\treturn { inFlightAtStart, remaining, requeued, timedOut }\n}\n","import type { LeaseStore } from './leaseStore'\nimport type { LeaderRole } from './locksCollection'\n\nexport type LeaderController = {\n\t/** Drive one acquire/renew cycle at `now`. Safe to call repeatedly. */\n\ttick: (now: Date) => Promise<void>\n\t/** Whether this controller currently holds leadership. */\n\tisLeader: () => boolean\n\t/** The fence token of the held lease, or 0 when not leading. */\n\tfenceToken: () => number\n\t/** Relinquish leadership now (graceful handoff). */\n\trelease: () => Promise<void>\n}\n\nexport type LeaderControllerArgs = {\n\tstore: LeaseStore\n\trole: LeaderRole\n\townerId: string\n\tttlMs: number\n}\n\n/**\n * Turns a lease into leadership. On each `tick`: if not leading, try to acquire/steal;\n * if leading, renew. A failed renew (the lease was stolen while this node was paused\n * past expiry) drops leadership immediately, so a zombie never keeps acting. No timer\n * lives here; a caller schedules `tick` at `ttlMs / 3`.\n */\nexport const createLeaderController = (args: LeaderControllerArgs): LeaderController => {\n\tconst { ownerId, role, store, ttlMs } = args\n\tlet leading = false\n\tlet token = 0\n\n\treturn {\n\t\tfenceToken: () => (leading ? token : 0),\n\t\tisLeader: () => leading,\n\t\trelease: async () => {\n\t\t\tawait store.release(role, ownerId)\n\t\t\tleading = false\n\t\t\ttoken = 0\n\t\t},\n\t\ttick: async (now) => {\n\t\t\tif (leading) {\n\t\t\t\tconst renewed = await store.renew(role, ownerId, ttlMs, now)\n\t\t\t\tif (!renewed.ok) {\n\t\t\t\t\tleading = false\n\t\t\t\t\ttoken = 0\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst acquired = await store.acquireOrSteal(role, ownerId, ttlMs, now)\n\t\t\tif (acquired.ok) {\n\t\t\t\tleading = true\n\t\t\t\ttoken = acquired.fenceToken\n\t\t\t}\n\t\t},\n\t}\n}\n","import type { Payload } from 'payload'\n\nimport { leaseExpiry } from './leaseLogic'\nimport type { LeaseRecord, LeaseResult, LeaseStore } from './leaseStore'\nimport { JOBS_LOCKS_SLUG } from './locksCollection'\n\ntype MongoDoc = LeaseRecord\n\ntype MongoModel = {\n\tfindOne: (filter: Record<string, unknown>) => { lean: () => Promise<MongoDoc | null> }\n\tfindOneAndUpdate: (\n\t\tfilter: Record<string, unknown>,\n\t\tupdate: Record<string, unknown>,\n\t\toptions?: Record<string, unknown>\n\t) => Promise<MongoDoc | null>\n}\n\n/** Reach the raw Mongoose model the adapter exposes on `db.collections[slug]`. */\nconst model = (payload: Payload): MongoModel => {\n\tconst collections = (payload.db as unknown as { collections: Record<string, MongoModel> })\n\t\t.collections\n\tconst found = collections[JOBS_LOCKS_SLUG]\n\tif (!found) {\n\t\tthrow new Error(`@10x-media/jobs: missing Mongoose model for \"${JOBS_LOCKS_SLUG}\"`)\n\t}\n\treturn found\n}\n\n/** Single-document `findOneAndUpdate` is an atomic compare-and-set on MongoDB. */\nexport const createMongoLeaseStore = (payload: Payload): LeaseStore => {\n\tconst m = model(payload)\n\n\tconst toRecord = (doc: MongoDoc | null): LeaseRecord | null =>\n\t\tdoc === null\n\t\t\t? null\n\t\t\t: {\n\t\t\t\t\tfenceToken: doc.fenceToken,\n\t\t\t\t\tleaseExpiresAt: doc.leaseExpiresAt ? new Date(doc.leaseExpiresAt) : null,\n\t\t\t\t\towner: doc.owner ?? null,\n\t\t\t\t\trole: doc.role,\n\t\t\t\t}\n\n\treturn {\n\t\t// biome-ignore lint/complexity/useMaxParams: lease primitive signature (role, owner, ttlMs, now)\n\t\tacquireOrSteal: async (role, owner, ttlMs, now): Promise<LeaseResult> => {\n\t\t\tconst doc = await m.findOneAndUpdate(\n\t\t\t\t{\n\t\t\t\t\t$or: [{ owner: null }, { leaseExpiresAt: { $lt: now } }],\n\t\t\t\t\trole,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t$inc: { fenceToken: 1 },\n\t\t\t\t\t$set: { leaseExpiresAt: leaseExpiry(now, ttlMs), owner },\n\t\t\t\t},\n\t\t\t\t{ new: true }\n\t\t\t)\n\t\t\treturn { fenceToken: doc?.fenceToken ?? 0, ok: doc !== null }\n\t\t},\n\t\tread: async (role): Promise<LeaseRecord | null> => toRecord(await m.findOne({ role }).lean()),\n\t\trelease: async (role, owner): Promise<void> => {\n\t\t\tawait m.findOneAndUpdate({ owner, role }, { $set: { leaseExpiresAt: null, owner: null } })\n\t\t},\n\t\t// biome-ignore lint/complexity/useMaxParams: lease primitive signature (role, owner, ttlMs, now)\n\t\trenew: async (role, owner, ttlMs, now): Promise<LeaseResult> => {\n\t\t\tconst doc = await m.findOneAndUpdate(\n\t\t\t\t{ owner, role },\n\t\t\t\t{ $set: { leaseExpiresAt: leaseExpiry(now, ttlMs) } },\n\t\t\t\t{ new: true }\n\t\t\t)\n\t\t\treturn { fenceToken: doc?.fenceToken ?? 0, ok: doc !== null }\n\t\t},\n\t}\n}\n","import type { Payload } from 'payload'\n\nimport { leaseExpiry } from './leaseLogic'\nimport type { LeaseRecord, LeaseResult, LeaseStore } from './leaseStore'\nimport { JOBS_LOCKS_SLUG, type LeaderRole } from './locksCollection'\n\ntype PgRow = {\n\trole: LeaderRole\n\towner: string | null\n\tlease_expires_at: Date | string | null\n\tfence_token: number | string\n}\n\ntype PgPool = {\n\tquery: (text: string, values?: unknown[]) => Promise<{ rowCount: number; rows: PgRow[] }>\n}\n\n/** Payload tables for kebab slugs are the slug with hyphens replaced by underscores. */\nconst tableName = (payload: Payload): string => {\n\tconst defaultTable = JOBS_LOCKS_SLUG.replace(/-/g, '_')\n\tconst map = (payload.db as unknown as { tableNameMap?: Map<string, string> }).tableNameMap\n\tconst fromMap = map && typeof map.get === 'function' ? map.get(defaultTable) : undefined\n\treturn fromMap ?? defaultTable\n}\n\nconst pool = (payload: Payload): PgPool => {\n\tconst found = (payload.db as unknown as { pool?: PgPool }).pool\n\tif (!found) {\n\t\tthrow new Error(`@10x-media/jobs: missing pg pool on the \"${payload.db.name}\" adapter`)\n\t}\n\treturn found\n}\n\n/** Single-statement `UPDATE ... WHERE <guard> RETURNING` is atomic under READ COMMITTED. */\nexport const createPostgresLeaseStore = (payload: Payload): LeaseStore => {\n\tconst table = tableName(payload)\n\tconst db = pool(payload)\n\n\tconst toRecord = (row: PgRow | undefined): LeaseRecord | null =>\n\t\trow === undefined\n\t\t\t? null\n\t\t\t: {\n\t\t\t\t\tfenceToken: Number(row.fence_token),\n\t\t\t\t\tleaseExpiresAt: row.lease_expires_at ? new Date(row.lease_expires_at) : null,\n\t\t\t\t\towner: row.owner ?? null,\n\t\t\t\t\trole: row.role,\n\t\t\t\t}\n\n\treturn {\n\t\t// biome-ignore lint/complexity/useMaxParams: lease primitive signature (role, owner, ttlMs, now)\n\t\tacquireOrSteal: async (role, owner, ttlMs, now): Promise<LeaseResult> => {\n\t\t\tconst res = await db.query(\n\t\t\t\t`UPDATE ${table}\n\t\t\t\t SET owner = $1, lease_expires_at = $2, fence_token = fence_token + 1\n\t\t\t\t WHERE role = $3 AND (owner IS NULL OR lease_expires_at < $4)\n\t\t\t\t RETURNING fence_token`,\n\t\t\t\t[owner, leaseExpiry(now, ttlMs), role, now]\n\t\t\t)\n\t\t\treturn {\n\t\t\t\tfenceToken: res.rowCount === 1 ? Number(res.rows[0]?.fence_token) : 0,\n\t\t\t\tok: res.rowCount === 1,\n\t\t\t}\n\t\t},\n\t\tread: async (role): Promise<LeaseRecord | null> => {\n\t\t\tconst res = await db.query(\n\t\t\t\t`SELECT role, owner, lease_expires_at, fence_token FROM ${table} WHERE role = $1`,\n\t\t\t\t[role]\n\t\t\t)\n\t\t\treturn toRecord(res.rows[0])\n\t\t},\n\t\trelease: async (role, owner): Promise<void> => {\n\t\t\tawait db.query(\n\t\t\t\t`UPDATE ${table} SET owner = NULL, lease_expires_at = NULL WHERE role = $1 AND owner = $2`,\n\t\t\t\t[role, owner]\n\t\t\t)\n\t\t},\n\t\t// biome-ignore lint/complexity/useMaxParams: lease primitive signature (role, owner, ttlMs, now)\n\t\trenew: async (role, owner, ttlMs, now): Promise<LeaseResult> => {\n\t\t\tconst res = await db.query(\n\t\t\t\t`UPDATE ${table}\n\t\t\t\t SET lease_expires_at = $1\n\t\t\t\t WHERE role = $2 AND owner = $3\n\t\t\t\t RETURNING fence_token`,\n\t\t\t\t[leaseExpiry(now, ttlMs), role, owner]\n\t\t\t)\n\t\t\treturn {\n\t\t\t\tfenceToken: res.rowCount === 1 ? Number(res.rows[0]?.fence_token) : 0,\n\t\t\t\tok: res.rowCount === 1,\n\t\t\t}\n\t\t},\n\t}\n}\n","import type { Payload } from 'payload'\n\nimport { createMongoLeaseStore } from './leaseStore.mongo'\nimport { createPostgresLeaseStore } from './leaseStore.postgres'\nimport type { LeaderRole } from './locksCollection'\n\n/** The current state of one leadership lease row. */\nexport type LeaseRecord = {\n\trole: LeaderRole\n\towner: string | null\n\tleaseExpiresAt: Date | null\n\tfenceToken: number\n}\n\n/** The outcome of an acquire/renew attempt. */\nexport type LeaseResult = {\n\t/** Whether this caller now holds (or still holds) the lease. */\n\tok: boolean\n\t/** The fence token after the attempt (monotonic; only meaningful when ok). */\n\tfenceToken: number\n}\n\n/**\n * A distributed lease over the `payload-jobs-locks` rows. Every method is a single\n * atomic conditional write at the database, so two contenders never both win.\n * Implemented per adapter because Payload's `db.updateOne` drops the `where`\n * predicate when an `id` is given (validated), so it cannot express a compare-and-set.\n */\nexport interface LeaseStore {\n\t/** Acquire `role` if free or expired at `now`. Bumps the fence token on success. */\n\tacquireOrSteal: (\n\t\trole: LeaderRole,\n\t\towner: string,\n\t\tttlMs: number,\n\t\tnow: Date\n\t) => Promise<LeaseResult>\n\t/** Renew `role` if `owner` still holds it at `now`. Does not bump the fence token. */\n\trenew: (role: LeaderRole, owner: string, ttlMs: number, now: Date) => Promise<LeaseResult>\n\t/** Release `role` if `owner` holds it (graceful handoff: clears owner and expiry). */\n\trelease: (role: LeaderRole, owner: string) => Promise<void>\n\t/** Read the current lease row (diagnostics and tests). */\n\tread: (role: LeaderRole) => Promise<LeaseRecord | null>\n}\n\n/** Build the lease store for the running adapter. Throws for an unsupported adapter. */\nexport const createLeaseStore = (payload: Payload): LeaseStore => {\n\tif (payload.db.name === 'mongoose') {\n\t\treturn createMongoLeaseStore(payload)\n\t}\n\tif (payload.db.name === 'postgres') {\n\t\treturn createPostgresLeaseStore(payload)\n\t}\n\tthrow new Error(`@10x-media/jobs reliability does not support db adapter \"${payload.db.name}\"`)\n}\n","import type { Payload, Where } from 'payload'\n\nconst JOBS_SLUG = 'payload-jobs'\n\n// The dev app compiles this file with generated types that do not include the\n// reliability `claimedBy` field, so reach `payload.count` through a slug-agnostic\n// signature (same pattern as the sweeper's `payload.find` cast).\ntype JobsCounter = (args: { collection: string; where?: Where }) => Promise<{ totalDocs: number }>\n\n/** Count this node's in-flight jobs: `processing: true` AND claimed by `claimedBy`. */\nexport const countInFlight = async (payload: Payload, claimedBy: string): Promise<number> => {\n\tconst count = payload.count as unknown as JobsCounter\n\tconst res = await count({\n\t\tcollection: JOBS_SLUG,\n\t\twhere: { and: [{ processing: { equals: true } }, { claimedBy: { equals: claimedBy } }] },\n\t})\n\treturn res.totalDocs\n}\n","/** The subset of `process` the signal installer needs (injectable for tests). */\nexport type SignalTarget = {\n\ton: (signal: NodeJS.Signals, listener: () => void) => unknown\n\tremoveListener: (signal: NodeJS.Signals, listener: () => void) => unknown\n}\n\nexport type SignalCleanup = () => void\n\n/**\n * Register `handler` for each signal and return a cleanup that removes them. The\n * handler fires at most once across all signals (a second signal during drain is\n * ignored). Payload installs no signal handlers of its own, so these never conflict.\n * `target` defaults to `process`; tests pass an EventEmitter.\n */\nexport const installSignalHandlers = (\n\tsignals: NodeJS.Signals[],\n\thandler: (signal: NodeJS.Signals) => void,\n\ttarget: SignalTarget = process\n): SignalCleanup => {\n\tlet fired = false\n\tconst registered = signals.map((signal) => {\n\t\tconst listener = () => {\n\t\t\tif (fired) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tfired = true\n\t\t\thandler(signal)\n\t\t}\n\t\ttarget.on(signal, listener)\n\t\treturn [signal, listener] as const\n\t})\n\treturn () => {\n\t\tfor (const [signal, listener] of registered) {\n\t\t\ttarget.removeListener(signal, listener)\n\t\t}\n\t}\n}\n","type Logger = { error?: (m: string) => void }\n\nconst guard = async (\n\tlogger: Logger | undefined,\n\tlabel: string,\n\tfn: () => Promise<void>\n): Promise<void> => {\n\ttry {\n\t\tawait fn()\n\t} catch (err) {\n\t\tlogger?.error?.(`@10x-media/jobs: worker ${label} cycle error: ${String(err)}`)\n\t}\n}\n\nexport type RunCycleDeps = { runJobs: () => Promise<void>; logger?: Logger }\n\n/** One run cycle: claim and execute jobs on this node. Errors are logged, not thrown. */\nexport const runCycle = async (deps: RunCycleDeps): Promise<void> => {\n\tawait guard(deps.logger, 'run', deps.runJobs)\n}\n\nexport type MaintenanceCycleDeps = {\n\ttickLeaders: (now: Date) => Promise<void>\n\tisSchedulerLeader: () => boolean\n\thandleSchedules: () => Promise<void>\n\tnow: () => Date\n\tlogger?: Logger\n}\n\n/** One maintenance cycle: advance leadership, then schedule only if scheduler-leader. */\nexport const maintenanceCycle = async (deps: MaintenanceCycleDeps): Promise<void> => {\n\tawait guard(deps.logger, 'leadership', () => deps.tickLeaders(deps.now()))\n\tif (deps.isSchedulerLeader()) {\n\t\tawait guard(deps.logger, 'schedule', deps.handleSchedules)\n\t}\n}\n\nexport type SweepCycleDeps = {\n\tisSweeperLeader: () => boolean\n\tsweep: () => Promise<void>\n\tlogger?: Logger\n}\n\n/** One sweep cycle: reclaim stuck jobs only if sweeper-leader. */\nexport const sweepCycle = async (deps: SweepCycleDeps): Promise<void> => {\n\tif (deps.isSweeperLeader()) {\n\t\tawait guard(deps.logger, 'sweep', deps.sweep)\n\t}\n}\n","import type { Payload } from 'payload'\nimport { getCurrentDate } from 'payload'\nimport { emptyPauseState } from '../queueControl/pauseState'\nimport type { PauseStore } from '../queueControl/pauseStore'\nimport { runTargetsForPause } from '../queueControl/runTargets'\nimport { createJobLeaseStore } from '../reliability/jobLeaseStore'\nimport { createLeaderController } from '../reliability/leaderController'\nimport { createLeaseStore } from '../reliability/leaseStore'\nimport type { LeaderRole } from '../reliability/locksCollection'\nimport { resolveNodeId } from '../reliability/nodeId'\nimport type { ResolvedReliabilityOptions } from '../reliability/options'\nimport { runSweep } from '../reliability/sweeper'\nimport { type DrainResult, drainWorker } from './drain'\nimport { countInFlight } from './inFlight'\nimport { installSignalHandlers, type SignalCleanup } from './signals'\nimport { maintenanceCycle, runCycle, sweepCycle } from './workerCycles'\n\nexport type CreateWorkerArgs = {\n\tpayload: Payload\n\treliability: ResolvedReliabilityOptions\n\t/** Queues to run. Omit (or empty) to run all queues. */\n\tqueues?: string[]\n\t/** When provided, the run loop honors cluster-wide pause/resume. */\n\tpauseStore?: PauseStore\n\t/** How often this node claims and runs jobs. Default 2000. */\n\trunIntervalMs?: number\n\t/** How often leadership is advanced and scheduling runs (leader only). Default leaderLeaseTtlMs / 3. */\n\tmaintenanceIntervalMs?: number\n\t/** Max jobs per run tick. Default 10. */\n\trunLimit?: number\n\t/** Wall-clock budget to await in-flight jobs on drain. Default 30000. */\n\tdrainTimeoutMs?: number\n\t/** How often the drain re-counts in-flight jobs. Default 500. */\n\tpollIntervalMs?: number\n\t/** Register SIGTERM/SIGINT handlers that drain then exit. Default true. */\n\tinstallSignals?: boolean\n\t/** Which signals to drain on. Default ['SIGTERM', 'SIGINT']. */\n\tsignals?: NodeJS.Signals[]\n\t/** Injectable for tests: destroy (default payload.destroy), exit, wall clock. */\n\tdestroy?: () => Promise<void>\n\texit?: (code: number) => void\n\tnow?: () => number\n\tsleep?: (ms: number) => Promise<void>\n}\n\nexport type Worker = {\n\t/** Start the run, maintenance, and sweep loops. */\n\tstart: () => void\n\t/**\n\t * Gracefully drain and shut down (removes signal handlers, stops loops, requeues,\n\t * releases, destroys). Idempotent: repeated calls return the same in-flight drain.\n\t */\n\tdrain: () => Promise<DrainResult>\n\t/** Stop the loops and remove signal handlers WITHOUT draining (test teardown). */\n\tstop: () => void\n\t/** Whether this node currently holds the given leadership role. */\n\tisLeader: (role: LeaderRole) => boolean\n}\n\nconst realSleep = (ms: number): Promise<void> =>\n\tnew Promise((resolve) => {\n\t\tsetTimeout(resolve, ms)\n\t})\n\n/** A self-skipping interval: a slow tick never overlaps the next (like Croner's `protect`). */\nconst guardedInterval = (fn: () => Promise<void>, ms: number): ReturnType<typeof setInterval> => {\n\tlet busy = false\n\treturn setInterval(() => {\n\t\tif (busy) {\n\t\t\treturn\n\t\t}\n\t\tbusy = true\n\t\tvoid fn().finally(() => {\n\t\t\tbusy = false\n\t\t})\n\t}, ms)\n}\n\n/**\n * A plugin-driven worker: runs jobs on every node, schedules and sweeps only while\n * holding the corresponding leadership lease, and drains gracefully on SIGTERM/SIGINT.\n * It owns its own timers (never Payload's autoRun cron), because Payload's\n * `shouldAutoRun` gate permanently stops a cron and cannot follow dynamic leadership.\n * Leadership timestamps use Payload's swappable `getCurrentDate()`; the drain budget\n * uses the injected wall clock.\n */\nexport const createWorker = (args: CreateWorkerArgs): Worker => {\n\tconst { payload, reliability } = args\n\tif (!payload.collections['payload-jobs']) {\n\t\tthrow new Error(\n\t\t\t'@10x-media/jobs: createWorker requires at least one configured job task. Payload only registers the payload-jobs collection when jobs.tasks or jobs.workflows is non-empty.'\n\t\t)\n\t}\n\tconst nodeId = resolveNodeId(reliability.leaderId)\n\tconst leaseStore = createLeaseStore(payload)\n\tconst jobLeaseStore = createJobLeaseStore(payload)\n\tconst scheduler = createLeaderController({\n\t\townerId: nodeId,\n\t\trole: 'scheduler',\n\t\tstore: leaseStore,\n\t\tttlMs: reliability.leaderLeaseTtlMs,\n\t})\n\tconst sweeper = createLeaderController({\n\t\townerId: nodeId,\n\t\trole: 'sweeper',\n\t\tstore: leaseStore,\n\t\tttlMs: reliability.leaderLeaseTtlMs,\n\t})\n\n\tconst runIntervalMs = args.runIntervalMs ?? 2000\n\tconst maintenanceIntervalMs =\n\t\targs.maintenanceIntervalMs ?? Math.max(1000, Math.floor(reliability.leaderLeaseTtlMs / 3))\n\tconst sweepIntervalMs = reliability.sweepIntervalMs\n\tconst runLimit = args.runLimit ?? 10\n\tconst drainTimeoutMs = args.drainTimeoutMs ?? 30_000\n\tconst pollIntervalMs = args.pollIntervalMs ?? 500\n\tconst destroy = args.destroy ?? (() => payload.destroy())\n\tconst now = args.now ?? (() => Date.now())\n\tconst sleep = args.sleep ?? realSleep\n\tconst logger = payload.logger\n\n\tlet timers: ReturnType<typeof setInterval>[] = []\n\tlet signalCleanup: SignalCleanup | undefined\n\tlet draining: Promise<DrainResult> | undefined\n\n\tconst runJobs = async (): Promise<void> => {\n\t\tconst state = args.pauseStore ? await args.pauseStore.getState() : emptyPauseState()\n\t\tfor (const target of runTargetsForPause(args.queues, state)) {\n\t\t\tawait payload.jobs.run({ ...target, limit: runLimit, silent: true })\n\t\t}\n\t}\n\tconst handleSchedules = async (): Promise<void> => {\n\t\tawait payload.jobs.handleSchedules({ allQueues: true })\n\t}\n\tconst sweep = async (): Promise<void> => {\n\t\tawait runSweep({\n\t\t\tisLeader: sweeper.isLeader(),\n\t\t\tnow: getCurrentDate(),\n\t\t\toptions: reliability,\n\t\t\tpayload,\n\t\t\tstore: jobLeaseStore,\n\t\t})\n\t}\n\tconst tickLeaders = async (at: Date): Promise<void> => {\n\t\tawait scheduler.tick(at)\n\t\tawait sweeper.tick(at)\n\t}\n\n\tconst stopLoops = (): void => {\n\t\tfor (const timer of timers) {\n\t\t\tclearInterval(timer)\n\t\t}\n\t\ttimers = []\n\t}\n\tconst removeSignals = (): void => {\n\t\tsignalCleanup?.()\n\t\tsignalCleanup = undefined\n\t}\n\n\t// Idempotent: a repeat call (or a second signal) returns the in-flight drain rather\n\t// than running the shutdown sequence twice.\n\tconst drain = (): Promise<DrainResult> => {\n\t\tif (draining) {\n\t\t\treturn draining\n\t\t}\n\t\tremoveSignals()\n\t\tdraining = drainWorker(\n\t\t\t{\n\t\t\t\tcountInFlight: () => countInFlight(payload, nodeId),\n\t\t\t\tdestroy,\n\t\t\t\tlogger,\n\t\t\t\tnow,\n\t\t\t\treleaseLeadership: async () => {\n\t\t\t\t\tawait scheduler.release()\n\t\t\t\t\tawait sweeper.release()\n\t\t\t\t},\n\t\t\t\trequeueStragglers: async () => (await jobLeaseStore.releaseAllClaims(nodeId)).released,\n\t\t\t\tsleep,\n\t\t\t\tstopLoops,\n\t\t\t},\n\t\t\t{ drainTimeoutMs, pollIntervalMs }\n\t\t)\n\t\treturn draining\n\t}\n\n\tconst worker: Worker = {\n\t\tdrain,\n\t\tisLeader: (role) => (role === 'scheduler' ? scheduler.isLeader() : sweeper.isLeader()),\n\t\tstart: () => {\n\t\t\tstopLoops()\n\t\t\ttimers = [\n\t\t\t\tguardedInterval(() => runCycle({ logger, runJobs }), runIntervalMs),\n\t\t\t\tguardedInterval(\n\t\t\t\t\t() =>\n\t\t\t\t\t\tmaintenanceCycle({\n\t\t\t\t\t\t\thandleSchedules,\n\t\t\t\t\t\t\tisSchedulerLeader: scheduler.isLeader,\n\t\t\t\t\t\t\tlogger,\n\t\t\t\t\t\t\tnow: getCurrentDate,\n\t\t\t\t\t\t\ttickLeaders,\n\t\t\t\t\t\t}),\n\t\t\t\t\tmaintenanceIntervalMs\n\t\t\t\t),\n\t\t\t\tguardedInterval(\n\t\t\t\t\t() => sweepCycle({ isSweeperLeader: sweeper.isLeader, logger, sweep }),\n\t\t\t\t\tsweepIntervalMs\n\t\t\t\t),\n\t\t\t]\n\t\t},\n\t\tstop: () => {\n\t\t\tstopLoops()\n\t\t\tremoveSignals()\n\t\t},\n\t}\n\n\tif (args.installSignals !== false) {\n\t\tconst exit = args.exit ?? ((code: number) => process.exit(code))\n\t\tsignalCleanup = installSignalHandlers(args.signals ?? ['SIGTERM', 'SIGINT'], () => {\n\t\t\tvoid drain()\n\t\t\t\t.then(() => exit(0))\n\t\t\t\t.catch(() => exit(1))\n\t\t})\n\t}\n\n\treturn worker\n}\n","import { cronSecretAccess } from '../queueControl/access'\nimport type { QueueControlOptions } from '../queueControl/options'\nimport type { ReliabilityOptions } from '../reliability/options'\n\n/** The option groups a topology preset configures. */\nexport type TopologyPreset = {\n\treliability: ReliabilityOptions\n\tqueueControl: QueueControlOptions\n}\n\n/**\n * Single-node Docker: one serial claimer, so claim races are moot. Reliability and\n * queue control on with defaults; the sweeper runs from the in-process worker.\n */\nexport const singleNodePreset = (): TopologyPreset => ({ queueControl: {}, reliability: {} })\n\n/**\n * Multi-node Docker: leader-elected scheduling and sweeping (the default). Pass a\n * stable `leaderId` per node if you do not want the generated hostname:pid identity.\n */\nexport const multiNodePreset = (options: { leaderId?: string } = {}): TopologyPreset => ({\n\tqueueControl: {},\n\treliability: options.leaderId === undefined ? {} : { leaderId: options.leaderId },\n})\n\n/**\n * Serverless (Vercel): no long-running worker, so staleness derives from the platform\n * hard-kill duration (the function maxDuration) rather than a heartbeat, and the run\n * and sweep endpoints are guarded by the cron secret. Drive them with Vercel Cron\n * (see `vercelCrons`).\n */\nexport const serverlessPreset = (options: {\n\tmaxDurationMs: number\n\tcronSecretEnvVar?: string\n}): TopologyPreset => ({\n\tqueueControl: { access: cronSecretAccess({ envVar: options.cronSecretEnvVar }) },\n\treliability: {\n\t\tjobLeaseTtlMs: options.maxDurationMs,\n\t\tserverless: { maxDurationMs: options.maxDurationMs },\n\t},\n})\n\n/** A `vercel.json` `crons` entry. */\nexport type VercelCron = { path: string; schedule: string }\n\n/**\n * Build the `vercel.json` `crons` array: one entry hitting the hardened run endpoint\n * (all queues) and one hitting the sweep endpoint. Defaults to every minute (Vercel\n * Pro). Vercel sends the `CRON_SECRET` as a Bearer token, which `cronSecretAccess`\n * checks.\n */\nexport const vercelCrons = (\n\toptions: {\n\t\trunPath?: string\n\t\tsweepPath?: string\n\t\trunSchedule?: string\n\t\tsweepSchedule?: string\n\t} = {}\n): VercelCron[] => [\n\t{\n\t\tpath: options.runPath ?? '/api/payload-jobs/queue-run?allQueues=true',\n\t\tschedule: options.runSchedule ?? '* * * * *',\n\t},\n\t{\n\t\tpath: options.sweepPath ?? '/api/payload-jobs/queue-sweep',\n\t\tschedule: options.sweepSchedule ?? '* * * * *',\n\t},\n]\n","import { type Config, definePlugin } from 'payload'\n\nimport type { JobsPluginOptions } from './options'\nimport { registerJobsEnhancements } from './plugin/registerJobsEnhancements'\nimport { registerTranslations } from './plugin/registerTranslations'\nimport { resolveQueueControlOptions } from './queueControl/options'\nimport { registerQueueControl } from './queueControl/registerQueueControl'\nimport { resolveReliabilityOptions } from './reliability/options'\nimport { registerReliability } from './reliability/registerReliability'\n\ndeclare module 'payload' {\n\tinterface RegisteredPlugins {\n\t\t'@10x-media/jobs': JobsPluginOptions\n\t}\n}\n\n/**\n * Jobs plugin for Payload v3. Enhances the built-in `payload-jobs` collection\n * with an ops dashboard (status, queue health, error and log panels) and the\n * supporting i18n. Authored with `definePlugin` so the automations and webhooks\n * plugins can detect it by slug. Runs first (`order: 0`).\n */\nexport const jobs = definePlugin<JobsPluginOptions>({\n\tslug: '@10x-media/jobs',\n\torder: 0,\n\tplugin: ({ config, plugins: _plugins, ...options }): Config => {\n\t\tif (options.disabled === true) {\n\t\t\treturn config\n\t\t}\n\t\tregisterTranslations(config)\n\t\t// JobsPluginOptions is assignable to JobsOptions (the extra `disabled` is ignored).\n\t\tregisterJobsEnhancements(config, options)\n\t\tconst reliability = resolveReliabilityOptions(options.reliability)\n\t\tif (reliability) {\n\t\t\tregisterReliability(config, reliability)\n\t\t}\n\t\tconst queueControl = resolveQueueControlOptions(options.queueControl)\n\t\tif (queueControl) {\n\t\t\tregisterQueueControl(config, queueControl, reliability)\n\t\t}\n\t\treturn config\n\t},\n})\n\nexport {\n\ttype AutoRunConfigOptions,\n\ttype AutoRunQueueConfig,\n\tautoRunConfig,\n} from './execution/autoRunConfig'\nexport { type DrainDeps, type DrainOptions, type DrainResult, drainWorker } from './execution/drain'\nexport { type CreateWorkerArgs, createWorker, type Worker } from './execution/worker'\nexport type { JobStatus, JobStatusInput } from './jobs/deriveJobStatus'\nexport { deriveJobStatus } from './jobs/deriveJobStatus'\nexport type { JobsOptions, JobsPluginOptions, JobsPluginOptions as PluginOptions } from './options'\nexport {\n\tmultiNodePreset,\n\tserverlessPreset,\n\tsingleNodePreset,\n\ttype TopologyPreset,\n\ttype VercelCron,\n\tvercelCrons,\n} from './presets/presets'\nexport { cronSecretAccess, type JobAccess, loggedInAccess } from './queueControl/access'\nexport type { QueueControlOptions } from './queueControl/options'\nexport type { PauseState } from './queueControl/pauseState'\nexport { createPauseStore, type PauseStore } from './queueControl/pauseStore'\nexport {\n\ttype GetQueueHealthOptions,\n\tgetQueueHealth,\n\ttype QueueHealth,\n\ttype QueueHealthReport,\n} from './queueControl/queueHealth'\nexport {\n\ttype IdempotencyStore,\n\twithIdempotencyKey,\n} from './reliability/concurrencyContract'\nexport {\n\tcreateJobLeaseStore,\n\ttype DeadLetterArgs,\n\ttype JobId,\n\ttype JobLeaseResult,\n\ttype JobLeaseRow,\n\ttype JobLeaseStore,\n\ttype StampResult,\n} from './reliability/jobLeaseStore'\nexport {\n\tcreateLeaderController,\n\ttype LeaderController,\n} from './reliability/leaderController'\nexport {\n\tcreateLeaseStore,\n\ttype LeaseRecord,\n\ttype LeaseResult,\n\ttype LeaseStore,\n} from './reliability/leaseStore'\nexport { JOBS_LOCKS_SLUG, LEADER_ROLES, type LeaderRole } from './reliability/locksCollection'\nexport type { ReliabilityOptions } from './reliability/options'\nexport {\n\ttype ResolvedReliabilityOptions,\n\tresolveReliabilityOptions,\n} from './reliability/options'\nexport { decideRecovery, type RecoveryDecision } from './reliability/recoveryDecision'\nexport { type RunSweepArgs, runSweep, type SweepResult } from './reliability/sweeper'\n"],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { t as keys } from "./keys-BYs8GTJy.js";
|
|
2
|
+
//#region src/jobs/jobStatusMeta.ts
|
|
3
|
+
/**
|
|
4
|
+
* Translation key and native Pill style per status, shared by the list cell,
|
|
5
|
+
* document header, and health bar so the three never drift. Kept as plain data
|
|
6
|
+
* (no React) so the server-rendered health bar can import it.
|
|
7
|
+
*/
|
|
8
|
+
const jobStatusMeta = {
|
|
9
|
+
queued: {
|
|
10
|
+
labelKey: keys.statusQueued,
|
|
11
|
+
pillStyle: "light"
|
|
12
|
+
},
|
|
13
|
+
scheduled: {
|
|
14
|
+
labelKey: keys.statusScheduled,
|
|
15
|
+
pillStyle: "light-gray"
|
|
16
|
+
},
|
|
17
|
+
retrying: {
|
|
18
|
+
labelKey: keys.statusRetrying,
|
|
19
|
+
pillStyle: "warning"
|
|
20
|
+
},
|
|
21
|
+
running: {
|
|
22
|
+
labelKey: keys.statusRunning,
|
|
23
|
+
pillStyle: "dark"
|
|
24
|
+
},
|
|
25
|
+
succeeded: {
|
|
26
|
+
labelKey: keys.statusSucceeded,
|
|
27
|
+
pillStyle: "success"
|
|
28
|
+
},
|
|
29
|
+
failed: {
|
|
30
|
+
labelKey: keys.statusFailed,
|
|
31
|
+
pillStyle: "error"
|
|
32
|
+
},
|
|
33
|
+
cancelled: {
|
|
34
|
+
labelKey: keys.statusCancelled,
|
|
35
|
+
pillStyle: "white"
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
//#endregion
|
|
39
|
+
export { jobStatusMeta as t };
|
|
40
|
+
|
|
41
|
+
//# sourceMappingURL=jobStatusMeta-BLBSPUcE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jobStatusMeta-BLBSPUcE.js","names":[],"sources":["../src/jobs/jobStatusMeta.ts"],"sourcesContent":["import { keys, type TranslationKey } from '../translations/keys'\nimport type { JobStatus } from './deriveJobStatus'\n\n/** Payload `Pill` styles used for job statuses. */\nexport type JobStatusPillStyle =\n\t| 'dark'\n\t| 'error'\n\t| 'light'\n\t| 'light-gray'\n\t| 'success'\n\t| 'warning'\n\t| 'white'\n\n/**\n * Translation key and native Pill style per status, shared by the list cell,\n * document header, and health bar so the three never drift. Kept as plain data\n * (no React) so the server-rendered health bar can import it.\n */\nexport const jobStatusMeta: Record<\n\tJobStatus,\n\t{ labelKey: TranslationKey; pillStyle: JobStatusPillStyle }\n> = {\n\tqueued: { labelKey: keys.statusQueued, pillStyle: 'light' },\n\tscheduled: { labelKey: keys.statusScheduled, pillStyle: 'light-gray' },\n\tretrying: { labelKey: keys.statusRetrying, pillStyle: 'warning' },\n\trunning: { labelKey: keys.statusRunning, pillStyle: 'dark' },\n\tsucceeded: { labelKey: keys.statusSucceeded, pillStyle: 'success' },\n\tfailed: { labelKey: keys.statusFailed, pillStyle: 'error' },\n\tcancelled: { labelKey: keys.statusCancelled, pillStyle: 'white' },\n}\n"],"mappings":";;;;;;;AAkBA,MAAa,gBAGT;CACH,QAAQ;EAAE,UAAU,KAAK;EAAc,WAAW;CAAQ;CAC1D,WAAW;EAAE,UAAU,KAAK;EAAiB,WAAW;CAAa;CACrE,UAAU;EAAE,UAAU,KAAK;EAAgB,WAAW;CAAU;CAChE,SAAS;EAAE,UAAU,KAAK;EAAe,WAAW;CAAO;CAC3D,WAAW;EAAE,UAAU,KAAK;EAAiB,WAAW;CAAU;CAClE,QAAQ;EAAE,UAAU,KAAK;EAAc,WAAW;CAAQ;CAC1D,WAAW;EAAE,UAAU,KAAK;EAAiB,WAAW;CAAQ;AACjE"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//#region src/translations/keys.ts
|
|
2
|
+
/**
|
|
3
|
+
* Typed translation keys. Lookups must go through these constants, not string
|
|
4
|
+
* literals (enforced by requireI18nKeysTyped.grit). Every key here must have a
|
|
5
|
+
* value in every locale (`en.ts`), or it is a type error.
|
|
6
|
+
*/
|
|
7
|
+
const keys = {
|
|
8
|
+
pluginName: "jobs:pluginName",
|
|
9
|
+
statusQueued: "jobs:statusQueued",
|
|
10
|
+
statusScheduled: "jobs:statusScheduled",
|
|
11
|
+
statusRetrying: "jobs:statusRetrying",
|
|
12
|
+
statusRunning: "jobs:statusRunning",
|
|
13
|
+
statusSucceeded: "jobs:statusSucceeded",
|
|
14
|
+
statusFailed: "jobs:statusFailed",
|
|
15
|
+
statusCancelled: "jobs:statusCancelled",
|
|
16
|
+
fieldStatus: "jobs:fieldStatus",
|
|
17
|
+
fieldWorkflow: "jobs:fieldWorkflow",
|
|
18
|
+
fieldTask: "jobs:fieldTask",
|
|
19
|
+
fieldJob: "jobs:fieldJob",
|
|
20
|
+
fieldQueue: "jobs:fieldQueue",
|
|
21
|
+
fieldAttempts: "jobs:fieldAttempts",
|
|
22
|
+
fieldCreated: "jobs:fieldCreated",
|
|
23
|
+
fieldUpdated: "jobs:fieldUpdated",
|
|
24
|
+
fieldCompleted: "jobs:fieldCompleted",
|
|
25
|
+
fieldExecuted: "jobs:fieldExecuted",
|
|
26
|
+
fieldTaskId: "jobs:fieldTaskId",
|
|
27
|
+
fieldInput: "jobs:fieldInput",
|
|
28
|
+
fieldOutput: "jobs:fieldOutput",
|
|
29
|
+
fieldError: "jobs:fieldError",
|
|
30
|
+
fieldId: "jobs:fieldId",
|
|
31
|
+
outcome: "jobs:outcome",
|
|
32
|
+
noAttempts: "jobs:noAttempts",
|
|
33
|
+
copy: "jobs:copy",
|
|
34
|
+
copied: "jobs:copied",
|
|
35
|
+
jobSingular: "jobs:jobSingular",
|
|
36
|
+
jobPlural: "jobs:jobPlural"
|
|
37
|
+
};
|
|
38
|
+
//#endregion
|
|
39
|
+
export { keys as t };
|
|
40
|
+
|
|
41
|
+
//# sourceMappingURL=keys-BYs8GTJy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys-BYs8GTJy.js","names":[],"sources":["../src/translations/keys.ts"],"sourcesContent":["/**\n * Typed translation keys. Lookups must go through these constants, not string\n * literals (enforced by requireI18nKeysTyped.grit). Every key here must have a\n * value in every locale (`en.ts`), or it is a type error.\n */\nexport const keys = {\n\tpluginName: 'jobs:pluginName',\n\n\tstatusQueued: 'jobs:statusQueued',\n\tstatusScheduled: 'jobs:statusScheduled',\n\tstatusRetrying: 'jobs:statusRetrying',\n\tstatusRunning: 'jobs:statusRunning',\n\tstatusSucceeded: 'jobs:statusSucceeded',\n\tstatusFailed: 'jobs:statusFailed',\n\tstatusCancelled: 'jobs:statusCancelled',\n\n\tfieldStatus: 'jobs:fieldStatus',\n\tfieldWorkflow: 'jobs:fieldWorkflow',\n\tfieldTask: 'jobs:fieldTask',\n\tfieldJob: 'jobs:fieldJob',\n\tfieldQueue: 'jobs:fieldQueue',\n\tfieldAttempts: 'jobs:fieldAttempts',\n\tfieldCreated: 'jobs:fieldCreated',\n\tfieldUpdated: 'jobs:fieldUpdated',\n\tfieldCompleted: 'jobs:fieldCompleted',\n\tfieldExecuted: 'jobs:fieldExecuted',\n\tfieldTaskId: 'jobs:fieldTaskId',\n\tfieldInput: 'jobs:fieldInput',\n\tfieldOutput: 'jobs:fieldOutput',\n\tfieldError: 'jobs:fieldError',\n\tfieldId: 'jobs:fieldId',\n\n\toutcome: 'jobs:outcome',\n\tnoAttempts: 'jobs:noAttempts',\n\tcopy: 'jobs:copy',\n\tcopied: 'jobs:copied',\n\tjobSingular: 'jobs:jobSingular',\n\tjobPlural: 'jobs:jobPlural',\n} as const\n\nexport type TranslationKey = (typeof keys)[keyof typeof keys]\n"],"mappings":";;;;;;AAKA,MAAa,OAAO;CACnB,YAAY;CAEZ,cAAc;CACd,iBAAiB;CACjB,gBAAgB;CAChB,eAAe;CACf,iBAAiB;CACjB,cAAc;CACd,iBAAiB;CAEjB,aAAa;CACb,eAAe;CACf,WAAW;CACX,UAAU;CACV,YAAY;CACZ,eAAe;CACf,cAAc;CACd,cAAc;CACd,gBAAgB;CAChB,eAAe;CACf,aAAa;CACb,YAAY;CACZ,aAAa;CACb,YAAY;CACZ,SAAS;CAET,SAAS;CACT,YAAY;CACZ,MAAM;CACN,QAAQ;CACR,aAAa;CACb,WAAW;AACZ"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/translations/server.ts
|
|
2
|
+
/**
|
|
3
|
+
* Adapt a Payload request `t` (typed to core keys only) so it also accepts this
|
|
4
|
+
* plugin's keys. They are registered at config time and resolve at runtime; the
|
|
5
|
+
* cast only widens the compile-time key domain.
|
|
6
|
+
*/
|
|
7
|
+
const asTranslate = (t) => t;
|
|
8
|
+
/** A field `label`/`description` backed by a typed key, resolved per request. */
|
|
9
|
+
const labelForKey = (key) => ({ t }) => asTranslate(t)(key);
|
|
10
|
+
//#endregion
|
|
11
|
+
export { labelForKey as n, asTranslate as t };
|
|
12
|
+
|
|
13
|
+
//# sourceMappingURL=server-JsvYf5vy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-JsvYf5vy.js","names":[],"sources":["../src/translations/server.ts"],"sourcesContent":["import type { LabelFunction } from 'payload'\n\nimport type { TranslationKey } from './keys'\n\n/** A `t`-like function narrowed to this plugin's typed keys. */\ntype Translate = (key: TranslationKey) => string\n\n/**\n * Adapt a Payload request `t` (typed to core keys only) so it also accepts this\n * plugin's keys. They are registered at config time and resolve at runtime; the\n * cast only widens the compile-time key domain.\n */\nexport const asTranslate = (t: unknown): Translate => t as Translate\n\n/** A field `label`/`description` backed by a typed key, resolved per request. */\nexport const labelForKey =\n\t(key: TranslationKey): LabelFunction =>\n\t({ t }) =>\n\t\tasTranslate(t)(key)\n"],"mappings":";;;;;;AAYA,MAAa,eAAe,MAA0B;;AAGtD,MAAa,eACX,SACA,EAAE,QACF,YAAY,CAAC,EAAE,GAAG"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { t as keys } from "./keys-BYs8GTJy.js";
|
|
2
|
+
//#region src/translations/en.ts
|
|
3
|
+
/**
|
|
4
|
+
* English values, keyed by the typed constants in `keys.ts` so the two stay in
|
|
5
|
+
* lockstep. The `Record<TranslationKey, string>` annotation makes a missing or
|
|
6
|
+
* unknown key a type error. `translations/index.ts` nests these for Payload.
|
|
7
|
+
*/
|
|
8
|
+
const en = {
|
|
9
|
+
[keys.pluginName]: "Jobs",
|
|
10
|
+
[keys.statusQueued]: "Queued",
|
|
11
|
+
[keys.statusScheduled]: "Scheduled",
|
|
12
|
+
[keys.statusRetrying]: "Retrying",
|
|
13
|
+
[keys.statusRunning]: "Running",
|
|
14
|
+
[keys.statusSucceeded]: "Succeeded",
|
|
15
|
+
[keys.statusFailed]: "Failed",
|
|
16
|
+
[keys.statusCancelled]: "Cancelled",
|
|
17
|
+
[keys.fieldStatus]: "Status",
|
|
18
|
+
[keys.fieldWorkflow]: "Workflow",
|
|
19
|
+
[keys.fieldTask]: "Task",
|
|
20
|
+
[keys.fieldJob]: "Job",
|
|
21
|
+
[keys.fieldQueue]: "Queue",
|
|
22
|
+
[keys.fieldAttempts]: "Attempts",
|
|
23
|
+
[keys.fieldCreated]: "Created",
|
|
24
|
+
[keys.fieldUpdated]: "Updated",
|
|
25
|
+
[keys.fieldCompleted]: "Completed",
|
|
26
|
+
[keys.fieldExecuted]: "Executed",
|
|
27
|
+
[keys.fieldTaskId]: "Task ID",
|
|
28
|
+
[keys.fieldInput]: "Input",
|
|
29
|
+
[keys.fieldOutput]: "Output",
|
|
30
|
+
[keys.fieldError]: "Error",
|
|
31
|
+
[keys.fieldId]: "ID",
|
|
32
|
+
[keys.outcome]: "Outcome",
|
|
33
|
+
[keys.noAttempts]: "No attempts recorded yet.",
|
|
34
|
+
[keys.copy]: "Copy",
|
|
35
|
+
[keys.copied]: "Copied",
|
|
36
|
+
[keys.jobSingular]: "job",
|
|
37
|
+
[keys.jobPlural]: "jobs"
|
|
38
|
+
};
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/translations/index.ts
|
|
41
|
+
/**
|
|
42
|
+
* Flat `jobs:foo` entries to the nested `{ jobs: { foo } }` shape
|
|
43
|
+
* Payload resolves `t('jobs:foo')` against (it splits the key on `:`).
|
|
44
|
+
*/
|
|
45
|
+
const toNested = (flat) => {
|
|
46
|
+
const out = {};
|
|
47
|
+
for (const [fullKey, value] of Object.entries(flat)) {
|
|
48
|
+
const separator = fullKey.indexOf(":");
|
|
49
|
+
const namespace = fullKey.slice(0, separator);
|
|
50
|
+
const bucket = out[namespace] ?? {};
|
|
51
|
+
bucket[fullKey.slice(separator + 1)] = value;
|
|
52
|
+
out[namespace] = bucket;
|
|
53
|
+
}
|
|
54
|
+
return out;
|
|
55
|
+
};
|
|
56
|
+
/** Per-locale messages merged into `config.i18n.translations`. English only for now. */
|
|
57
|
+
const translations = { en: toNested(en) };
|
|
58
|
+
//#endregion
|
|
59
|
+
export { translations as t };
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=translations-KyQ3962W.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translations-KyQ3962W.js","names":[],"sources":["../src/translations/en.ts","../src/translations/index.ts"],"sourcesContent":["import { keys, type TranslationKey } from './keys'\n\n/**\n * English values, keyed by the typed constants in `keys.ts` so the two stay in\n * lockstep. The `Record<TranslationKey, string>` annotation makes a missing or\n * unknown key a type error. `translations/index.ts` nests these for Payload.\n */\nexport const en: Record<TranslationKey, string> = {\n\t[keys.pluginName]: 'Jobs',\n\n\t[keys.statusQueued]: 'Queued',\n\t[keys.statusScheduled]: 'Scheduled',\n\t[keys.statusRetrying]: 'Retrying',\n\t[keys.statusRunning]: 'Running',\n\t[keys.statusSucceeded]: 'Succeeded',\n\t[keys.statusFailed]: 'Failed',\n\t[keys.statusCancelled]: 'Cancelled',\n\n\t[keys.fieldStatus]: 'Status',\n\t[keys.fieldWorkflow]: 'Workflow',\n\t[keys.fieldTask]: 'Task',\n\t[keys.fieldJob]: 'Job',\n\t[keys.fieldQueue]: 'Queue',\n\t[keys.fieldAttempts]: 'Attempts',\n\t[keys.fieldCreated]: 'Created',\n\t[keys.fieldUpdated]: 'Updated',\n\t[keys.fieldCompleted]: 'Completed',\n\t[keys.fieldExecuted]: 'Executed',\n\t[keys.fieldTaskId]: 'Task ID',\n\t[keys.fieldInput]: 'Input',\n\t[keys.fieldOutput]: 'Output',\n\t[keys.fieldError]: 'Error',\n\t[keys.fieldId]: 'ID',\n\n\t[keys.outcome]: 'Outcome',\n\t[keys.noAttempts]: 'No attempts recorded yet.',\n\t[keys.copy]: 'Copy',\n\t[keys.copied]: 'Copied',\n\t[keys.jobSingular]: 'job',\n\t[keys.jobPlural]: 'jobs',\n}\n","import { en } from './en'\n\nexport type { TranslationKey } from './keys'\nexport { keys } from './keys'\n\n/**\n * Flat `jobs:foo` entries to the nested `{ jobs: { foo } }` shape\n * Payload resolves `t('jobs:foo')` against (it splits the key on `:`).\n */\nconst toNested = (flat: Record<string, string>): Record<string, Record<string, string>> => {\n\tconst out: Record<string, Record<string, string>> = {}\n\tfor (const [fullKey, value] of Object.entries(flat)) {\n\t\tconst separator = fullKey.indexOf(':')\n\t\tconst namespace = fullKey.slice(0, separator)\n\t\tconst bucket = out[namespace] ?? {}\n\t\tbucket[fullKey.slice(separator + 1)] = value\n\t\tout[namespace] = bucket\n\t}\n\treturn out\n}\n\n/** Per-locale messages merged into `config.i18n.translations`. English only for now. */\nexport const translations = {\n\ten: toNested(en),\n}\n"],"mappings":";;;;;;;AAOA,MAAa,KAAqC;EAChD,KAAK,aAAa;EAElB,KAAK,eAAe;EACpB,KAAK,kBAAkB;EACvB,KAAK,iBAAiB;EACtB,KAAK,gBAAgB;EACrB,KAAK,kBAAkB;EACvB,KAAK,eAAe;EACpB,KAAK,kBAAkB;EAEvB,KAAK,cAAc;EACnB,KAAK,gBAAgB;EACrB,KAAK,YAAY;EACjB,KAAK,WAAW;EAChB,KAAK,aAAa;EAClB,KAAK,gBAAgB;EACrB,KAAK,eAAe;EACpB,KAAK,eAAe;EACpB,KAAK,iBAAiB;EACtB,KAAK,gBAAgB;EACrB,KAAK,cAAc;EACnB,KAAK,aAAa;EAClB,KAAK,cAAc;EACnB,KAAK,aAAa;EAClB,KAAK,UAAU;EAEf,KAAK,UAAU;EACf,KAAK,aAAa;EAClB,KAAK,OAAO;EACZ,KAAK,SAAS;EACd,KAAK,cAAc;EACnB,KAAK,YAAY;AACnB;;;;;;;AC/BA,MAAM,YAAY,SAAyE;CAC1F,MAAM,MAA8C,CAAC;CACrD,KAAK,MAAM,CAAC,SAAS,UAAU,OAAO,QAAQ,IAAI,GAAG;EACpD,MAAM,YAAY,QAAQ,QAAQ,GAAG;EACrC,MAAM,YAAY,QAAQ,MAAM,GAAG,SAAS;EAC5C,MAAM,SAAS,IAAI,cAAc,CAAC;EAClC,OAAO,QAAQ,MAAM,YAAY,CAAC,KAAK;EACvC,IAAI,aAAa;CAClB;CACA,OAAO;AACR;;AAGA,MAAa,eAAe,EAC3B,IAAI,SAAS,EAAE,EAChB"}
|
package/package.json
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@10x-media/jobs",
|
|
3
|
+
"version": "0.1.0-beta.0",
|
|
4
|
+
"description": "Jobs ops dashboard, execution helpers, and reliability tooling for Payload",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/10x-media/payload-plugins.git",
|
|
9
|
+
"directory": "packages/jobs"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/10x-media/payload-plugins/tree/main/packages/jobs",
|
|
12
|
+
"bugs": "https://github.com/10x-media/payload-plugins/issues",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"payload",
|
|
15
|
+
"payloadcms",
|
|
16
|
+
"plugin"
|
|
17
|
+
],
|
|
18
|
+
"author": "10x-media",
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=22.18.0"
|
|
21
|
+
},
|
|
22
|
+
"type": "module",
|
|
23
|
+
"sideEffects": false,
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"import": "./dist/index.js",
|
|
28
|
+
"default": "./dist/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./types": {
|
|
31
|
+
"types": "./dist/exports/types.d.ts",
|
|
32
|
+
"import": "./dist/exports/types.js",
|
|
33
|
+
"default": "./dist/exports/types.js"
|
|
34
|
+
},
|
|
35
|
+
"./client": {
|
|
36
|
+
"types": "./dist/exports/client.d.ts",
|
|
37
|
+
"import": "./dist/exports/client.js",
|
|
38
|
+
"default": "./dist/exports/client.js"
|
|
39
|
+
},
|
|
40
|
+
"./rsc": {
|
|
41
|
+
"types": "./dist/exports/rsc.d.ts",
|
|
42
|
+
"import": "./dist/exports/rsc.js",
|
|
43
|
+
"default": "./dist/exports/rsc.js"
|
|
44
|
+
},
|
|
45
|
+
"./i18n": {
|
|
46
|
+
"types": "./dist/exports/i18n.d.ts",
|
|
47
|
+
"import": "./dist/exports/i18n.js",
|
|
48
|
+
"default": "./dist/exports/i18n.js"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"files": [
|
|
52
|
+
"dist",
|
|
53
|
+
"README.md",
|
|
54
|
+
"CHANGELOG.md",
|
|
55
|
+
"LICENSE"
|
|
56
|
+
],
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"@payloadcms/ui": "^3.82.0",
|
|
59
|
+
"payload": "^3.82.0",
|
|
60
|
+
"react": "^19.0.0",
|
|
61
|
+
"react-dom": "^19.0.0"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@payloadcms/db-mongodb": "3.85.0",
|
|
65
|
+
"@payloadcms/ui": "3.85.0",
|
|
66
|
+
"@payloadcms/db-postgres": "3.85.0",
|
|
67
|
+
"@playwright/test": "1.60.0",
|
|
68
|
+
"@types/node": "22.19.19",
|
|
69
|
+
"@types/react": "19.2.15",
|
|
70
|
+
"@types/react-dom": "19.2.3",
|
|
71
|
+
"payload": "3.85.0",
|
|
72
|
+
"playwright": "1.60.0",
|
|
73
|
+
"react": "19.2.6",
|
|
74
|
+
"react-dom": "19.2.6",
|
|
75
|
+
"tsdown": "0.22.1",
|
|
76
|
+
"typescript": "5.9.3",
|
|
77
|
+
"vitest": "4.1.7",
|
|
78
|
+
"@10x-media/payload-test-harness": "0.0.0",
|
|
79
|
+
"@10x-media/tsconfig": "0.0.0",
|
|
80
|
+
"@10x-media/vitest-config": "0.0.0"
|
|
81
|
+
},
|
|
82
|
+
"publishConfig": {
|
|
83
|
+
"access": "public"
|
|
84
|
+
},
|
|
85
|
+
"scripts": {
|
|
86
|
+
"build": "tsdown",
|
|
87
|
+
"lint": "biome check src tests dev",
|
|
88
|
+
"lint:fix": "biome check --write src tests dev",
|
|
89
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
90
|
+
"test": "vitest run",
|
|
91
|
+
"test:unit": "vitest run src",
|
|
92
|
+
"test:int": "vitest run tests/int",
|
|
93
|
+
"test:matrix": "DB_MATRIX=mongo vitest run tests/int/matrix.int.spec.ts tests/int/reliability-lease.int.spec.ts tests/int/heartbeat-sweeper.int.spec.ts tests/int/execution.int.spec.ts tests/int/queue-control.int.spec.ts tests/int/multi-instance.int.spec.ts && DB_MATRIX=postgres vitest run tests/int/matrix.int.spec.ts tests/int/reliability-lease.int.spec.ts tests/int/heartbeat-sweeper.int.spec.ts tests/int/execution.int.spec.ts tests/int/queue-control.int.spec.ts tests/int/multi-instance.int.spec.ts",
|
|
94
|
+
"test:container": "TEST_DB=container DB_MATRIX=mongo vitest run tests/int/matrix.int.spec.ts tests/int/reliability-lease.int.spec.ts tests/int/heartbeat-sweeper.int.spec.ts tests/int/execution.int.spec.ts tests/int/queue-control.int.spec.ts tests/int/multi-instance.int.spec.ts && TEST_DB=container DB_MATRIX=postgres vitest run tests/int/matrix.int.spec.ts tests/int/reliability-lease.int.spec.ts tests/int/heartbeat-sweeper.int.spec.ts tests/int/execution.int.spec.ts tests/int/queue-control.int.spec.ts tests/int/multi-instance.int.spec.ts",
|
|
95
|
+
"test:e2e": "bash scripts/e2e.sh",
|
|
96
|
+
"dev": "pnpm --filter @10x-media/jobs-dev dev",
|
|
97
|
+
"start": "pnpm --filter @10x-media/jobs-dev start",
|
|
98
|
+
"gen": "pnpm --filter @10x-media/jobs-dev gen",
|
|
99
|
+
"gen:types": "pnpm --filter @10x-media/jobs-dev gen:types",
|
|
100
|
+
"gen:importmap": "pnpm --filter @10x-media/jobs-dev gen:importmap",
|
|
101
|
+
"migrate": "pnpm --filter @10x-media/jobs-dev migrate",
|
|
102
|
+
"migrate:create": "pnpm --filter @10x-media/jobs-dev migrate:create",
|
|
103
|
+
"migrate:down": "pnpm --filter @10x-media/jobs-dev migrate:down",
|
|
104
|
+
"migrate:refresh": "pnpm --filter @10x-media/jobs-dev migrate:refresh",
|
|
105
|
+
"migrate:reset": "pnpm --filter @10x-media/jobs-dev migrate:reset",
|
|
106
|
+
"migrate:status": "pnpm --filter @10x-media/jobs-dev migrate:status",
|
|
107
|
+
"migrate:fresh": "pnpm --filter @10x-media/jobs-dev migrate:fresh",
|
|
108
|
+
"clean": "rm -rf dist *.tsbuildinfo dev/.next"
|
|
109
|
+
}
|
|
110
|
+
}
|