@cedarjs/jobs 7.0.1-next.314 → 7.0.1-next.466

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/adapters/BaseAdapter/BaseAdapter.d.ts +155 -10
  2. package/dist/adapters/BaseAdapter/BaseAdapter.d.ts.map +1 -1
  3. package/dist/adapters/BaseAdapter/BaseAdapter.js +6 -0
  4. package/dist/adapters/PrismaAdapter/PrismaAdapter.d.ts +68 -3
  5. package/dist/adapters/PrismaAdapter/PrismaAdapter.d.ts.map +1 -1
  6. package/dist/adapters/PrismaAdapter/PrismaAdapter.js +411 -70
  7. package/dist/adapters/PrismaAdapter/errors.d.ts +14 -0
  8. package/dist/adapters/PrismaAdapter/errors.d.ts.map +1 -1
  9. package/dist/adapters/PrismaAdapter/errors.js +17 -1
  10. package/dist/bins/cedar-jobs-worker.d.ts +11 -0
  11. package/dist/bins/cedar-jobs-worker.d.ts.map +1 -1
  12. package/dist/bins/cedar-jobs-worker.js +12 -1
  13. package/dist/bins/cedar-jobs.d.ts +25 -1
  14. package/dist/bins/cedar-jobs.d.ts.map +1 -1
  15. package/dist/bins/cedar-jobs.js +104 -3
  16. package/dist/consts.d.ts +18 -0
  17. package/dist/consts.d.ts.map +1 -1
  18. package/dist/consts.js +9 -1
  19. package/dist/core/Executor.d.ts +15 -1
  20. package/dist/core/Executor.d.ts.map +1 -1
  21. package/dist/core/Executor.js +90 -30
  22. package/dist/core/JobManager.d.ts +77 -1
  23. package/dist/core/JobManager.d.ts.map +1 -1
  24. package/dist/core/JobManager.js +210 -1
  25. package/dist/core/Scheduler.d.ts +1 -1
  26. package/dist/core/Scheduler.d.ts.map +1 -1
  27. package/dist/core/Scheduler.js +22 -5
  28. package/dist/core/Worker.d.ts +8 -0
  29. package/dist/core/Worker.d.ts.map +1 -1
  30. package/dist/core/Worker.js +49 -3
  31. package/dist/errors.d.ts +54 -0
  32. package/dist/errors.d.ts.map +1 -1
  33. package/dist/errors.js +60 -0
  34. package/dist/index.d.ts +5 -1
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +16 -1
  37. package/dist/loaders.d.ts +29 -0
  38. package/dist/loaders.d.ts.map +1 -1
  39. package/dist/loaders.js +48 -1
  40. package/dist/types.d.ts +109 -5
  41. package/dist/types.d.ts.map +1 -1
  42. package/dist/util.d.ts +6 -0
  43. package/dist/util.d.ts.map +1 -1
  44. package/dist/util.js +6 -1
  45. package/package.json +14 -9
@@ -7,6 +7,38 @@ export interface SchedulePayload {
7
7
  runAt: Date;
8
8
  queue: string;
9
9
  priority: number;
10
+ /**
11
+ * The job's unique key, if it was scheduled with one. Only passed to
12
+ * adapters that set `supportsUniqueKeys`. While a job with this key is
13
+ * still queued, the adapter must not add another one (see
14
+ * `ScheduleJobOptions['key']`)
15
+ */
16
+ key?: string | undefined;
17
+ }
18
+ /** A recurring schedule declared in code, as passed to `syncSchedules()` */
19
+ export interface ScheduleDefinition extends SchedulePayload {
20
+ cron: string;
21
+ /**
22
+ * The schedule's identity: `SCHEDULE_KEY_PREFIX`, the job's name and the
23
+ * schedule's own key, like `cedar:schedule:ReportJob:nightly`
24
+ */
25
+ key: string;
26
+ }
27
+ export interface SyncSchedulesOptions {
28
+ /** Every schedule declared in the app's code */
29
+ schedules: ScheduleDefinition[];
30
+ /**
31
+ * Every schedule key starts with this prefix. Stored schedules with this
32
+ * prefix that are not in `schedules` must be removed
33
+ */
34
+ keyPrefix: string;
35
+ }
36
+ /** The keys of the schedules `syncSchedules()` touched, by what it did */
37
+ export interface SyncSchedulesResult {
38
+ created: string[];
39
+ updated: string[];
40
+ removed: string[];
41
+ unchanged: string[];
10
42
  }
11
43
  export interface FindArgs {
12
44
  processName: string;
@@ -18,6 +50,11 @@ export interface BaseAdapterOptions {
18
50
  }
19
51
  export interface SuccessOptions<TJob extends BaseJob = BaseJob> {
20
52
  job: TJob;
53
+ /**
54
+ * When set, the job is a recurring (cron) job and has to run again at this
55
+ * time. The adapter must store it as the job's new `runAt` and reset the
56
+ * job's attempt count to 0
57
+ */
21
58
  runAt: Date | undefined;
22
59
  deleteJob?: boolean;
23
60
  }
@@ -30,10 +67,10 @@ export interface FailureOptions<TJob extends BaseJob = BaseJob> {
30
67
  job: TJob;
31
68
  deleteJob?: boolean;
32
69
  /**
33
- * Present when the job is failed directly, without a preceding `error()`
34
- * call for the same attempt (currently: when the job exceeded
35
- * `maxRuntime`), so the adapter can record what went wrong in a single
36
- * write
70
+ * The error of the attempt that failed the job (it exceeded `maxRuntime`,
71
+ * or it was the `maxAttempts`th attempt). There is no preceding `error()`
72
+ * call for that attempt, so the adapter records the error in the same
73
+ * write that marks the job as failed
37
74
  */
38
75
  error?: Error;
39
76
  }
@@ -41,6 +78,57 @@ export interface CancelOptions {
41
78
  /** The id of the job to cancel, as returned by `schedule()` */
42
79
  jobId: string | number;
43
80
  }
81
+ export interface PauseOptions {
82
+ /** The id of the job to pause, as returned by `schedule()` */
83
+ jobId: string | number;
84
+ }
85
+ export interface PauseResult {
86
+ /** `true` when the job was paused already, and nothing changed */
87
+ alreadyPaused: boolean;
88
+ /** When the job was paused */
89
+ pausedAt: Date;
90
+ }
91
+ export interface ResumeOptions {
92
+ /** The id of the job to resume, as returned by `schedule()` */
93
+ jobId: string | number;
94
+ }
95
+ export interface ResumeResult {
96
+ /** `false` when the job wasn't paused, and nothing changed */
97
+ wasPaused: boolean;
98
+ /**
99
+ * When the job runs next. `null` for a recurring job with a run in
100
+ * progress: the worker sets its next run time when that run finishes
101
+ */
102
+ runAt: Date | null;
103
+ }
104
+ export interface ListJobsOptions {
105
+ /** The most jobs to return, the ones that run next first */
106
+ limit: number;
107
+ /**
108
+ * Only list jobs in these queues. All queues when left out or `['*']`
109
+ */
110
+ queues?: string[];
111
+ /**
112
+ * Only list paused jobs. A worker uses this when it starts, to warn about
113
+ * paused jobs in its queues
114
+ */
115
+ paused?: boolean;
116
+ }
117
+ /** A job waiting to run, running or paused, as `list()` returns it */
118
+ export interface ListedJob {
119
+ id: string | number;
120
+ name: string;
121
+ queue: string;
122
+ /** Set for a recurring job */
123
+ cron: string | null;
124
+ /** When the job runs next (or would, if it weren't paused) */
125
+ runAt: Date | null;
126
+ /** When the job was paused, or `null` when it isn't */
127
+ pausedAt: Date | null;
128
+ /** Whether a worker is running the job right now */
129
+ running: boolean;
130
+ attempts: number;
131
+ }
44
132
  /**
45
133
  * Base class for all job adapters. Provides a common interface for scheduling
46
134
  * jobs. At a minimum, you must implement the `schedule` method in your adapter.
@@ -49,9 +137,15 @@ export interface CancelOptions {
49
137
  * be used to configure your custom adapter. If `options.logger` is included
50
138
  * you can access it via `this.logger`
51
139
  */
52
- export declare abstract class BaseAdapter<TOptions extends BaseAdapterOptions = BaseAdapterOptions, TScheduleReturn = void | Promise<void>> {
140
+ export declare abstract class BaseAdapter<TOptions extends BaseAdapterOptions = BaseAdapterOptions, TScheduleReturn = unknown> {
53
141
  options: TOptions;
54
142
  logger: NonNullable<TOptions['logger']>;
143
+ /**
144
+ * Whether `schedule()` honors `payload.key` (see `SchedulePayload['key']`).
145
+ * Scheduling a job with a `key` through an adapter that doesn't throws a
146
+ * `UniqueKeysNotSupportedError`, so a key is never silently ignored
147
+ */
148
+ readonly supportsUniqueKeys: boolean;
55
149
  constructor(options: TOptions);
56
150
  abstract schedule(payload: SchedulePayload): TScheduleReturn;
57
151
  /**
@@ -59,19 +153,26 @@ export declare abstract class BaseAdapter<TOptions extends BaseAdapterOptions =
59
153
  */
60
154
  abstract find(args: FindArgs): PossibleBaseJob | Promise<PossibleBaseJob>;
61
155
  /**
62
- * Called when a job has successfully completed
156
+ * Called when a job has successfully completed.
157
+ *
158
+ * When `options.runAt` is set the job is a recurring (cron) job that has to
159
+ * run again at that time. The adapter must then store the new `runAt` and
160
+ * reset the job's attempt count to 0, so that `attempts` (which the worker
161
+ * compares against `maxAttempts` and uses for the retry backoff) counts
162
+ * consecutive failures of a single run rather than every run of the job
63
163
  */
64
164
  abstract success(options: SuccessOptions): void | Promise<void>;
65
165
  /**
66
- * Called when an attempt to run a job produced an error.
166
+ * Called when an attempt to run a job produced an error and the job will
167
+ * be retried.
67
168
  * This should update the stored job with the new `options.runAt` so that it
68
169
  * will be retried
69
170
  */
70
171
  abstract error(options: ErrorOptions): void | Promise<void>;
71
172
  /**
72
- * Called when a job will not be retried: it has either errored more than
73
- * maxAttempts times, or exceeded maxRuntime (in which case
74
- * `options.error` contains the timeout error to record)
173
+ * Called, instead of `error()`, when a job will not be retried: it has
174
+ * either errored maxAttempts times, or exceeded maxRuntime.
175
+ * `options.error` contains the error to record
75
176
  */
76
177
  abstract failure(options: FailureOptions): void | Promise<void>;
77
178
  /**
@@ -88,5 +189,49 @@ export declare abstract class BaseAdapter<TOptions extends BaseAdapterOptions =
88
189
  * cancellation and `later.cancel()` will throw a `CancelNotImplementedError`
89
190
  */
90
191
  cancel?(options: CancelOptions): boolean | Promise<boolean>;
192
+ /**
193
+ * Makes the stored recurring schedules match `options.schedules`, the ones
194
+ * declared in code. Called by every job worker when it starts, so several
195
+ * calls can run at the same time and must not create duplicates:
196
+ * - a declared schedule without a stored job is created, with its `runAt`
197
+ * at the next match of its `cron`
198
+ * - a stored schedule whose job name, path, args, queue, priority or cron
199
+ * differ from the declaration is updated
200
+ * - a stored schedule (key starting with `options.keyPrefix`) that is not
201
+ * declared any more is removed
202
+ *
203
+ * This method is optional: declaring `schedules` on a job with an adapter
204
+ * that doesn't implement it makes the workers throw a
205
+ * `SchedulesNotSupportedError` when they start
206
+ */
207
+ syncSchedules?(options: SyncSchedulesOptions): SyncSchedulesResult | Promise<SyncSchedulesResult>;
208
+ /**
209
+ * Pause a job, so that no worker picks it up until it's resumed. A run in
210
+ * progress finishes, and a recurring job's next run stays paused: `success()`
211
+ * and `error()` must keep the pause when they reschedule the job.
212
+ *
213
+ * Throws a `JobIdNotFoundError` when no job has the id, and a
214
+ * `JobNotActiveError` when the job has completed or failed for good.
215
+ *
216
+ * This method is optional, together with `resume()`: adapters that don't
217
+ * implement it don't support pausing, and `jobs.pauseJob()` throws a
218
+ * `PauseNotImplementedError`
219
+ */
220
+ pause?(options: PauseOptions): PauseResult | Promise<PauseResult>;
221
+ /**
222
+ * Resume a paused job. A recurring job runs next at the next match of its
223
+ * cron from now, so runs missed while it was paused are not made up for. A
224
+ * one-off job keeps its run time, so it runs right away when that has
225
+ * passed. A job that isn't paused is left as it is.
226
+ *
227
+ * Throws like `pause()`
228
+ */
229
+ resume?(options: ResumeOptions): ResumeResult | Promise<ResumeResult>;
230
+ /**
231
+ * List the jobs that are waiting to run, running or paused (not the
232
+ * completed or failed ones), the ones that run next first. Used by
233
+ * `yarn cedar jobs list` to find a job's id. Optional
234
+ */
235
+ list?(options: ListJobsOptions): ListedJob[] | Promise<ListedJob[]>;
91
236
  }
92
237
  //# sourceMappingURL=BaseAdapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"BaseAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/BaseAdapter/BaseAdapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAG3E,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,OAAO,EAAE,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,KAAK,EAAE,IAAI,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,QAAQ;IACvB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED,MAAM,WAAW,cAAc,CAAC,IAAI,SAAS,OAAO,GAAG,OAAO;IAC5D,GAAG,EAAE,IAAI,CAAA;IACT,KAAK,EAAE,IAAI,GAAG,SAAS,CAAA;IACvB,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AAED,MAAM,WAAW,YAAY,CAAC,IAAI,SAAS,OAAO,GAAG,OAAO;IAC1D,GAAG,EAAE,IAAI,CAAA;IACT,KAAK,EAAE,IAAI,CAAA;IACX,KAAK,EAAE,KAAK,CAAA;CACb;AAED,MAAM,WAAW,cAAc,CAAC,IAAI,SAAS,OAAO,GAAG,OAAO;IAC5D,GAAG,EAAE,IAAI,CAAA;IACT,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,KAAK,CAAA;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,+DAA+D;IAC/D,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;CACvB;AAED;;;;;;;GAOG;AACH,8BAAsB,WAAW,CAC/B,QAAQ,SAAS,kBAAkB,GAAG,kBAAkB,EACxD,eAAe,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAEtC,OAAO,EAAE,QAAQ,CAAA;IACjB,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAA;gBAE3B,OAAO,EAAE,QAAQ;IAU7B,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,eAAe;IAE5D;;OAEG;IACH,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,GAAG,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;IAEzE;;OAEG;IACH,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAE/D;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAE3D;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAE/D;;OAEG;IACH,QAAQ,CAAC,KAAK,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAEtC;;;;;;;;OAQG;IACH,MAAM,CAAC,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;CAC5D"}
1
+ {"version":3,"file":"BaseAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/BaseAdapter/BaseAdapter.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,12 @@ import { DEFAULT_LOGGER } from "../../consts.js";
2
2
  class BaseAdapter {
3
3
  options;
4
4
  logger;
5
+ /**
6
+ * Whether `schedule()` honors `payload.key` (see `SchedulePayload['key']`).
7
+ * Scheduling a job with a `key` through an adapter that doesn't throws a
8
+ * `UniqueKeysNotSupportedError`, so a key is never silently ignored
9
+ */
10
+ supportsUniqueKeys = false;
5
11
  constructor(options) {
6
12
  this.options = options;
7
13
  this.logger = options?.logger ?? DEFAULT_LOGGER;
@@ -1,9 +1,11 @@
1
1
  import type { BaseJob } from '../../types.js';
2
- import type { BaseAdapterOptions, SchedulePayload, FindArgs, SuccessOptions, ErrorOptions, FailureOptions, CancelOptions } from '../BaseAdapter/BaseAdapter.js';
2
+ import type { BaseAdapterOptions, ListedJob, ListJobsOptions, PauseOptions, PauseResult, ResumeOptions, ResumeResult, SchedulePayload, SyncSchedulesOptions, SyncSchedulesResult, FindArgs, SuccessOptions, ErrorOptions, FailureOptions, CancelOptions } from '../BaseAdapter/BaseAdapter.js';
3
3
  import { BaseAdapter } from '../BaseAdapter/BaseAdapter.js';
4
4
  export interface PrismaJob extends BaseJob {
5
5
  id: number;
6
6
  handler: string;
7
+ queue: string;
8
+ priority: number;
7
9
  /** Null once the job has completed or permanently failed */
8
10
  runAt: Date | null;
9
11
  cron: string | null | undefined;
@@ -13,8 +15,27 @@ export interface PrismaJob extends BaseJob {
13
15
  lockedBy: string | null;
14
16
  lastError: string | null;
15
17
  failedAt: Date | null;
18
+ /**
19
+ * When the job was paused, or null when it isn't. Workers don't pick up a
20
+ * paused job. Undefined when the model has no `pausedAt` column
21
+ */
22
+ pausedAt?: Date | null;
16
23
  createdAt: Date;
17
24
  updatedAt: Date;
25
+ /**
26
+ * The job's unique key. Only queued jobs and active recurring jobs hold
27
+ * their key, it's null once a worker has picked up a non-recurring job.
28
+ * Undefined when the model has no `key` column
29
+ */
30
+ key?: string | null;
31
+ }
32
+ /** What `schedule()` returns: the stored job */
33
+ export interface ScheduledPrismaJob extends PrismaJob {
34
+ /**
35
+ * `true` when the job was scheduled with a `key` and a job with that key
36
+ * was already queued. No new job was added, and this is the queued job
37
+ */
38
+ alreadyQueued: boolean;
18
39
  }
19
40
  interface PrismaAdapterDelegate {
20
41
  findFirst(args: Record<string, unknown>): Promise<any>;
@@ -25,6 +46,8 @@ interface PrismaAdapterDelegate {
25
46
  update(args: Record<string, unknown>): Promise<unknown>;
26
47
  create(args: Record<string, unknown>): Promise<unknown>;
27
48
  deleteMany(args?: Record<string, unknown>): Promise<unknown>;
49
+ /** Every Prisma delegate has it. Only `syncSchedules()` and `list()` use it */
50
+ findMany?(args: Record<string, unknown>): Promise<any[]>;
28
51
  }
29
52
  interface DelegateLike {
30
53
  findFirst: (...args: any[]) => any;
@@ -81,12 +104,15 @@ export interface PrismaAdapterOptions<TDb extends object = object> extends BaseA
81
104
  * lockedBy String?
82
105
  * lastError String?
83
106
  * failedAt DateTime?
107
+ * pausedAt DateTime?
84
108
  * createdAt DateTime \@default(now())
85
109
  * updatedAt DateTime \@updatedAt
86
110
  * }
87
111
  * ```
88
112
  */
89
- export declare class PrismaAdapter<TDb extends object = object> extends BaseAdapter<PrismaAdapterOptions<TDb>, Promise<PrismaJob>> {
113
+ export declare class PrismaAdapter<TDb extends object = object> extends BaseAdapter<PrismaAdapterOptions<TDb>, Promise<ScheduledPrismaJob>> {
114
+ #private;
115
+ readonly supportsUniqueKeys = true;
90
116
  db: TDb;
91
117
  model: DelegateKey<TDb> | string;
92
118
  accessor: PrismaAdapterDelegate;
@@ -102,7 +128,24 @@ export declare class PrismaAdapter<TDb extends object = object> extends BaseAdap
102
128
  success({ job, runAt, deleteJob }: SuccessOptions<PrismaJob>): Promise<void>;
103
129
  error({ job, runAt, error }: ErrorOptions<PrismaJob>): Promise<void>;
104
130
  failure({ job, deleteJob, error }: FailureOptions<PrismaJob>): Promise<void>;
105
- schedule({ name, path, args, runAt, cron, queue, priority, }: SchedulePayload): Promise<PrismaJob>;
131
+ /**
132
+ * Schedules a job by creating a new record in the background job table.
133
+ * Returns the created job so that callers get access to its `id` (to cancel
134
+ * it later, poll its status, etc.)
135
+ *
136
+ * With a `key`, the `key` column's unique constraint makes sure only one
137
+ * queued job holds the key, also when several processes schedule at once.
138
+ * If the insert hits the constraint, the job that holds the key is
139
+ * returned with `alreadyQueued: true` instead
140
+ */
141
+ schedule({ name, path, args, runAt, cron, queue, priority, key, }: SchedulePayload): Promise<ScheduledPrismaJob>;
142
+ /**
143
+ * Makes the stored declared schedules match `schedules`. Each schedule is
144
+ * one row, identified by its unique `key`, so concurrent syncs can't create
145
+ * duplicates: an insert that hits the unique constraint compares against
146
+ * (and if needed updates) the row the other sync created instead
147
+ */
148
+ syncSchedules({ schedules, keyPrefix, }: SyncSchedulesOptions): Promise<SyncSchedulesResult>;
106
149
  /**
107
150
  * Cancels a job by marking it as permanently failed so no worker will pick
108
151
  * it up (or retry it, if it's currently being worked on).
@@ -113,6 +156,28 @@ export declare class PrismaAdapter<TDb extends object = object> extends BaseAdap
113
156
  * its lock goes stale.
114
157
  */
115
158
  cancel({ jobId }: CancelOptions): Promise<boolean>;
159
+ /**
160
+ * Pauses a job by setting its `pausedAt`, which `find()` leaves out. A run
161
+ * in progress finishes, and `success()` and `error()` keep `pausedAt` when
162
+ * they reschedule the job
163
+ */
164
+ pause({ jobId }: PauseOptions): Promise<PauseResult>;
165
+ /**
166
+ * Resumes a paused job. A recurring job runs next at the next match of its
167
+ * cron from now, and, unless it's running, starts that run with a clean
168
+ * slate (`attempts` reset to 0, like after a successful run). A running
169
+ * job keeps its `attempts` and `runAt`: `attempts` identifies the run's
170
+ * claim (see `#claimedBy()`), and the worker sets the next run time when
171
+ * the run finishes, so a run that finishes while this write is under way
172
+ * keeps the run time it set, and the result's `runAt` is `null`. A one-off
173
+ * job keeps its `runAt`
174
+ */
175
+ resume({ jobId }: ResumeOptions): Promise<ResumeResult>;
176
+ /**
177
+ * Lists the jobs that haven't completed or failed for good, the ones that
178
+ * run next first
179
+ */
180
+ list({ limit, queues, paused, }: ListJobsOptions): Promise<ListedJob[]>;
116
181
  clear(): Promise<void>;
117
182
  }
118
183
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"PrismaAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/PrismaAdapter/PrismaAdapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PrismaAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/PrismaAdapter/PrismaAdapter.ts"],"names":[],"mappings":"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"}