@softure-ai/jobs 0.1.1 → 0.1.3

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 (55) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +63 -10
  3. package/dist/index.d.ts +13 -12
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +1 -1
  6. package/dist/index.js.map +1 -1
  7. package/dist/options.d.ts +23 -11
  8. package/dist/options.d.ts.map +1 -1
  9. package/dist/options.js +37 -4
  10. package/dist/options.js.map +1 -1
  11. package/dist/schema.d.ts +34 -0
  12. package/dist/schema.d.ts.map +1 -1
  13. package/dist/schema.js +2 -0
  14. package/dist/schema.js.map +1 -1
  15. package/dist/server/claim.d.ts +2 -1
  16. package/dist/server/claim.d.ts.map +1 -1
  17. package/dist/server/claim.js +22 -14
  18. package/dist/server/claim.js.map +1 -1
  19. package/dist/server/schedules.d.ts +13 -1
  20. package/dist/server/schedules.d.ts.map +1 -1
  21. package/dist/server/schedules.js +51 -4
  22. package/dist/server/schedules.js.map +1 -1
  23. package/dist/worker/health.d.ts +30 -0
  24. package/dist/worker/health.d.ts.map +1 -0
  25. package/dist/worker/health.js +53 -0
  26. package/dist/worker/health.js.map +1 -0
  27. package/dist/worker/index.d.ts +1 -0
  28. package/dist/worker/index.d.ts.map +1 -1
  29. package/dist/worker/index.js +3 -2
  30. package/dist/worker/index.js.map +1 -1
  31. package/dist/worker/process.d.ts +8 -2
  32. package/dist/worker/process.d.ts.map +1 -1
  33. package/dist/worker/process.js +27 -3
  34. package/dist/worker/process.js.map +1 -1
  35. package/dist/worker/run-job-worker.d.ts +5 -0
  36. package/dist/worker/run-job-worker.d.ts.map +1 -1
  37. package/dist/worker/run-job-worker.js +9 -0
  38. package/dist/worker/run-job-worker.js.map +1 -1
  39. package/dist/zoned-time.d.ts +19 -0
  40. package/dist/zoned-time.d.ts.map +1 -0
  41. package/dist/zoned-time.js +61 -0
  42. package/dist/zoned-time.js.map +1 -0
  43. package/migrations/0003_add_schedule_failures.sql +8 -0
  44. package/module.json +1 -1
  45. package/package.json +1 -1
  46. package/src/index.ts +3 -1
  47. package/src/options.ts +55 -8
  48. package/src/schema.ts +2 -0
  49. package/src/server/claim.ts +20 -14
  50. package/src/server/schedules.ts +58 -5
  51. package/src/worker/health.ts +64 -0
  52. package/src/worker/index.ts +3 -2
  53. package/src/worker/process.ts +32 -4
  54. package/src/worker/run-job-worker.ts +13 -0
  55. package/src/zoned-time.ts +75 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,45 @@ Newest first. Each version lists what changed for an app that uses `@softure-ai/
4
4
  production, the version gets a line `verified in: <app>@<commit>` ([docs/05](../../docs/05-adoption-playbook.md),
5
5
  "Definition of done").
6
6
 
7
+ ## 0.1.3
8
+
9
+ - A health check of the worker's loop (#610): `runJobWorkerProcess({ healthFile })` (and `runJobWorker`) touches the
10
+ file after each round whose claims reached the database, removes a stale one at start and its own after a clean
11
+ stop; started with `--health`, the same entry checks the file instead of running (exit 0 when no older than
12
+ `healthMaxAgeMs`, default five poll intervals and at least 30 s; 1 when missing or older, or without `healthFile`).
13
+ New exports from `@softure-ai/jobs/worker`: `checkJobWorkerHealth`, `getJobWorkerHealthMaxAgeMs`, `JobWorkerHealth`.
14
+ Off by default: an app that passes no `healthFile` sees no change.
15
+ - Migration for an app whose worker runs in Docker with a liveness check of PID 1 (`node -e "process.kill(1, 0)"`):
16
+ after upgrading to this version, pass `healthFile: "/tmp/softure-jobs-worker.alive"` in `scripts/worker.ts` and set
17
+ the worker service's `healthcheck.test` to `["CMD", "node", "worker.mjs", "--health"]` in the production compose
18
+ file (and the integration one, if it has a worker). Do it in that order: an older worker does not know `--health`.
19
+ - `getQueueStats` reports a scheduled queue's last failure (#603): each `schedule` gains `lastFailedAt` (when a job of
20
+ the queue last ended `failed`: attempts used up, `failJob`, an invalid payload or an expired lease with no attempts
21
+ left; a retried attempt does not count), `lastFailureCode` (that job's error code, never an error's text) and
22
+ `isFailing` (`lastFailedAt` later than `lastSucceededAt`, or a failure and no success yet). Stored in
23
+ `jobs.schedules` in the same transaction as the failed job, so it outlives pruning; migration
24
+ `0003_add_schedule_failures.sql` adds two nullable columns.
25
+ - Migration for an app: run the module migrations (`0003` adds the columns; failures before it are not back-filled).
26
+ An app that kept a log of its own runs only to tell whether the latest run failed reads
27
+ `stats.schedule.isFailing`, `lastFailedAt` and `lastFailureCode` from `getQueueStats` instead and can drop that log.
28
+ Code or tests that compare a whole `schedule` with `toEqual` see the three new fields.
29
+
30
+ ## 0.1.2
31
+
32
+ - Schedules at local times of day (#554): `schedules: { "<queue>": { at: ["09:00", "21:00"], timeZone: "Europe/Warsaw" } }`
33
+ enqueues one run per listed local time, with the zone's offset on each date, so the run keeps its local time across
34
+ DST changes (a skipped time runs just after the change, a repeated one once). The same "once per slot however many
35
+ workers run" guarantee as periods, no migration. A schedule takes exactly one of `every` and `at`; `timeZone` is
36
+ required with `at` and refused with `every`. Period schedules are unchanged. `getQueueStats` reports an `at`
37
+ schedule's `everySeconds` as the longest gap between its times. New types `PeriodScheduleOptions` and
38
+ `LocalTimeScheduleOptions`; `JobScheduleOptions` is their union, so code that read `schedule.every` checks
39
+ `"every" in schedule` first.
40
+ - Migration for an app that runs a job at a local time from a host cron: add the schedule to `jobs({ schedules })`
41
+ (to move billing's reminder mail: `"billing.access-reminders": { at: ["09:00", "21:00"], timeZone: "<zone>" }`
42
+ after `...billingJobSchedules`, which replaces its daily UTC period), make sure the worker runs the queue's handler
43
+ (`...billingJobHandlers` or `createBillingJobHandlers({ reminders })`), then remove the host cron entry (the deploy
44
+ `maintain` hook) so the job does not run twice.
45
+
7
46
  ## 0.1.1
8
47
 
9
48
  - Recurring schedules (#491): `jobs({ schedules: { "<queue>": { every: "1h", payload } } })`. Workers enqueue each
package/README.md CHANGED
@@ -47,7 +47,9 @@ export default defineSoftureConfig({
47
47
  | `queues.<name>.backoff` | `{ baseSeconds: 10, maxSeconds: 3600 }` | delay after attempt n is `min(max, base * 2^(n-1))`, shortened by up to 20 % at random |
48
48
  | `queues.<name>.leaseSeconds` | `300` | how long a claimed job is reserved; the worker extends it while the handler runs, so it bounds how long a crashed worker's job waits, not how long a handler may take |
49
49
  | `queues.<name>.concurrency` | `1` | jobs of the queue one worker process runs at once |
50
- | `schedules.<queue>.every` | (required) | how often the schedule runs: `<n>m`, `<n>h` or `<n>d`, from `1m` to `7d` (§3, "Schedules") |
50
+ | `schedules.<queue>.every` | (one of `every`, `at`) | how often the schedule runs: `<n>m`, `<n>h` or `<n>d`, from `1m` to `7d`, aligned to UTC (§3, "Schedules") |
51
+ | `schedules.<queue>.at` | (one of `every`, `at`) | local times of day the schedule runs at, `HH:MM` (`00:00` to `23:59`), each once, up to 48 |
52
+ | `schedules.<queue>.timeZone` | (required with `at`) | the IANA time zone of `at`, such as `Europe/Warsaw` or `UTC` |
51
53
  | `schedules.<queue>.payload` | `{}` | the payload of every scheduled run |
52
54
  | `pollIntervalMs` | `1000` | how often an idle worker looks for due jobs |
53
55
  | `shutdownGraceMs` | `20000` | how long a stopping worker waits for running handlers before releasing their jobs |
@@ -149,12 +151,38 @@ On SIGTERM the worker stops claiming, waits up to `shutdownGraceMs` for running
149
151
  releases their jobs (pending again, due now, the attempt given back). Database errors while claiming or recording are
150
152
  logged and retried on the next round; a database restart does not end the worker.
151
153
 
154
+ **Health check of the loop.** A process that is alive is not a loop that runs: a hung claim query or a database
155
+ connection the worker never gets back leaves the process up and the jobs untouched. With `healthFile`, the loop
156
+ touches that file after each round in which every claim reached the database (it removes a file left by an earlier
157
+ run at start, and removes its own after a clean stop), and the same entry answers `--health` instead of running:
158
+
159
+ ```ts
160
+ // scripts/worker.ts
161
+ await runJobWorkerProcess({ config, handlers, healthFile: "/tmp/softure-jobs-worker.alive" });
162
+ ```
163
+
164
+ ```yaml
165
+ # docker compose: the worker service
166
+ healthcheck:
167
+ test: ["CMD", "node", "worker.mjs", "--health"]
168
+ ```
169
+
170
+ `node worker.mjs --health` opens no database and starts no loop: it exits 0 when the file is no older than
171
+ `healthMaxAgeMs` (default five poll intervals, at least 30 s: `getJobWorkerHealthMaxAgeMs(config)`) and 1 when it is
172
+ missing or older, with one line saying which. `--health` without `healthFile` exits 1 rather than start a second
173
+ worker; an older jobs version has no `--health` and would start one, so switch the check only after upgrading. An app
174
+ that runs the loop itself passes `healthFile` to `runJobWorker` and checks with
175
+ `checkJobWorkerHealth({ healthFile, maxAgeMs })`. `docker compose up --wait` then waits for a loop that reached the
176
+ database, and the container reads `unhealthy` while it is stuck; Docker's `restart:` policy does not act on that
177
+ status (a monitor or an orchestrator does). `@softure-ai/deploy` writes both lines from `init`.
178
+
152
179
  `runJobWorker({ db, config, handlers, signal })` is the loop without the process part, for an app that runs it inside
153
180
  a process of its own.
154
181
 
155
182
  ### Schedules
156
183
 
157
- A schedule runs its queue's handler once per period, instead of an app cron:
184
+ A schedule runs its queue's handler once per period (`every`) or at local times of day (`at` in `timeZone`), instead
185
+ of an app cron:
158
186
 
159
187
  ```ts
160
188
  import { authJobSchedules } from "@softure-ai/auth/jobs";
@@ -165,6 +193,8 @@ jobs({
165
193
  ...authJobSchedules, // auth.prune-sessions hourly, auth.prune-password-resets daily
166
194
  ...securityJobSchedules, // security.prune-rate-limits hourly
167
195
  "app.digest": { every: "1d", payload: { kind: "weekly" } },
196
+ // The trial-ending reminder at 09:00 and 21:00 in the users' time zone, in place of billing's daily UTC period.
197
+ "billing.access-reminders": { at: ["09:00", "21:00"], timeZone: "Europe/Warsaw" },
168
198
  },
169
199
  });
170
200
  ```
@@ -179,10 +209,15 @@ export const handlers: JobHandlers = { ...authJobHandlers, ...securityJobHandler
179
209
 
180
210
  - Periods start on whole multiples of `every` counted from 1970-01-01 00:00 UTC: `1h` on the full hour, `1d` at
181
211
  midnight UTC, `15m` at :00, :15, :30, :45. A run is due at the start of its period.
212
+ - An `at` schedule's slots are its listed times on each local date in `timeZone`, with the zone's offset on that date:
213
+ `09:00` in `Europe/Warsaw` is 07:00 UTC in summer and 08:00 UTC in winter. A time a DST change skips runs as far
214
+ after the change as it would have been (`02:30` on the spring-forward day runs at 03:30); a time a DST change
215
+ repeats runs once, at its first occurrence. A worker that starts after a listed time enqueues that slot's run at
216
+ once, the same way a period schedule enqueues the period it starts in.
182
217
  - Once per period, however many workers run: a worker takes a period with a conditional upsert of
183
218
  `jobs.schedules` (the period must be later than the stored one) and enqueues the run in the same transaction, so a
184
219
  missed or doubled tick cannot happen. A worker enqueues only the schedules of the queues it runs.
185
- - Missed periods (no worker ran) collapse into one run for the current period.
220
+ - Missed periods or times (no worker ran) collapse into one run for the current slot.
186
221
  - Every scheduled run has the dedup key `schedule`: while a run is still pending or running (retrying a failure), the
187
222
  next period joins it instead of queueing a second run behind it.
188
223
  - Scheduled runs are ordinary jobs: retries, `maxAttempts`, `getJob`, `retryJob` and pruning apply.
@@ -190,10 +225,25 @@ export const handlers: JobHandlers = { ...authJobHandlers, ...securityJobHandler
190
225
  `@softure-ai/waitlist/jobs`, `@softure-ai/security/jobs`, `@softure-ai/analytics/jobs`), with `@softure-ai/jobs` as an
191
226
  optional peer.
192
227
 
193
- `getQueueStats` reports each scheduled queue's `schedule`: `everySeconds`, `lastEnqueuedAt` (the start of the latest
194
- period a run was enqueued for), `lastSucceededAt` (any succeeded job of the queue, a run enqueued by hand too) and
195
- `isLate`: no success within two periods, counted from when a worker first saw the schedule, or no worker has seen it
196
- at all. The module's health check does not fail on a late schedule (a late cleanup must not take the app out of
228
+ `getQueueStats` reports each scheduled queue's `schedule`: `everySeconds` (for an `at` schedule the longest gap
229
+ between two of its times, 24h for one time), `lastEnqueuedAt` (the start of the latest slot a run was enqueued for), `lastSucceededAt` (any succeeded job of the queue, a run enqueued by hand too),
230
+ `lastFailedAt` and `lastFailureCode` (the latest job of the queue that ended `failed`, with its error code: the
231
+ handler's code, `jobs.handler_threw`, `jobs.invalid_payload` or `jobs.lease_expired`, never an error's text; a retried
232
+ attempt is not a failure until the attempts are used up), `isFailing` and `isLate`. A queue is failing when its latest
233
+ outcome is a failure: `isFailing` is `lastFailedAt !== null && (lastSucceededAt === null || lastFailedAt >
234
+ lastSucceededAt)`. It is late when no run succeeded within two periods, counted from when a worker first saw the
235
+ schedule, or no worker has seen it at all. Successes and failures are recorded once a worker has taken the schedule's
236
+ first slot (its row in `jobs.schedules` exists), and they outlive the pruned jobs.
237
+
238
+ An app that shows how fresh a synced source is needs nothing else:
239
+
240
+ ```ts
241
+ const sync = (await getQueueStats(ctx)).find((stats) => stats.queue === "app.sync")?.schedule;
242
+ // "Updated at {lastSucceededAt}", plus "the last update failed ({lastFailureCode})" while isFailing.
243
+ const freshness = { updatedAt: sync?.lastSucceededAt ?? null, isFailing: sync?.isFailing ?? false };
244
+ ```
245
+
246
+ The module's health check does not fail on a late schedule (a late cleanup must not take the app out of
197
247
  rotation); an app that wants an alarm adds a check of its own:
198
248
 
199
249
  ```ts
@@ -236,7 +286,8 @@ Nothing to mount: the module has no routes or pages. The worker is a process (§
236
286
 
237
287
  ## 5. Migrations and tables
238
288
 
239
- Schema `jobs`, two tables, `migrations/0001_create_jobs.sql` and `migrations/0002_create_schedules.sql`:
289
+ Schema `jobs`, two tables, `migrations/0001_create_jobs.sql`, `migrations/0002_create_schedules.sql` and
290
+ `migrations/0003_add_schedule_failures.sql`:
240
291
 
241
292
  `jobs.jobs`: `id` (bigint identity; a string in the API), `queue`, `payload` (jsonb), `status` (`pending`, `running`,
242
293
  `succeeded`, `failed`, `cancelled`), `attempts`, `max_attempts`, `run_at`, `locked_until`, `locked_by` (the worker,
@@ -245,7 +296,8 @@ Schema `jobs`, two tables, `migrations/0001_create_jobs.sql` and `migrations/000
245
296
  for finished jobs; a partial unique index allows one live job per queue and dedup key.
246
297
 
247
298
  `jobs.schedules`: `name` (the schedule's queue, primary key), `last_slot_at` (the start of the latest period a run
248
- was enqueued for), `last_succeeded_at`, `created_at`, `updated_at`. One row per schedule a worker has seen; a row of
299
+ was enqueued for), `last_succeeded_at`, `last_failed_at`, `last_failure_code` (an error code, never a message),
300
+ `created_at`, `updated_at`. One row per schedule a worker has seen; a row of
249
301
  a schedule removed from the config stays and is ignored.
250
302
 
251
303
  The app role needs `SELECT, INSERT, UPDATE, DELETE` on the tables, which the `@softure-ai/ops` roles recipe grants on
@@ -283,7 +335,8 @@ logger gets payload paths, never values, for a payload that does not match its s
283
335
  ## 12. Limitations
284
336
 
285
337
  - Polling, no `LISTEN/NOTIFY`: a job waits up to `pollIntervalMs` when the worker is idle.
286
- - Schedules take a fixed period (`every`), aligned to UTC; no cron expressions, no time zones, no "at 03:00".
338
+ - Schedules take a fixed period aligned to UTC (`every`) or times of day in a time zone (`at`); no cron expressions,
339
+ no days of the week.
287
340
  - No priorities within a queue and no rate limits per queue beyond `concurrency`; split work into queues instead.
288
341
  - At-least-once delivery (§3, "Handlers run at least once").
289
342
  - PGlite has one connection, so tests run claims one after another; concurrent claiming is Postgres behaviour
package/dist/index.d.ts CHANGED
@@ -23,10 +23,17 @@ export declare const jobs: import("@softure-ai/core").ModuleFactory<{}, {
23
23
  leaseSeconds: import("zod").ZodDefault<import("zod").ZodNumber>;
24
24
  concurrency: import("zod").ZodDefault<import("zod").ZodNumber>;
25
25
  }, import("zod/v4/core").$strict>>>;
26
- schedules: import("zod").ZodDefault<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodObject<{
27
- every: import("zod").ZodString;
26
+ schedules: import("zod").ZodDefault<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodPipe<import("zod").ZodObject<{
27
+ every: import("zod").ZodOptional<import("zod").ZodString>;
28
+ at: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString>>;
29
+ timeZone: import("zod").ZodOptional<import("zod").ZodString>;
28
30
  payload: import("zod").ZodDefault<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
29
- }, import("zod/v4/core").$strict>>>;
31
+ }, import("zod/v4/core").$strict>, import("zod").ZodTransform<import("./options.js").PeriodScheduleOptions | import("./options.js").LocalTimeScheduleOptions, {
32
+ payload: Record<string, unknown>;
33
+ every?: string | undefined;
34
+ at?: string[] | undefined;
35
+ timeZone?: string | undefined;
36
+ }>>>>;
30
37
  pollIntervalMs: import("zod").ZodDefault<import("zod").ZodNumber>;
31
38
  shutdownGraceMs: import("zod").ZodDefault<import("zod").ZodNumber>;
32
39
  retention: import("zod").ZodDefault<import("zod").ZodObject<{
@@ -46,10 +53,7 @@ export declare const jobs: import("@softure-ai/core").ModuleFactory<{}, {
46
53
  concurrency: number;
47
54
  };
48
55
  };
49
- schedules: Record<string, {
50
- every: string;
51
- payload: Record<string, unknown>;
52
- }>;
56
+ schedules: Record<string, import("./options.js").PeriodScheduleOptions | import("./options.js").LocalTimeScheduleOptions>;
53
57
  pollIntervalMs: number;
54
58
  shutdownGraceMs: number;
55
59
  retention: {
@@ -67,10 +71,7 @@ export declare const jobs: import("@softure-ai/core").ModuleFactory<{}, {
67
71
  leaseSeconds: number;
68
72
  concurrency: number;
69
73
  }>;
70
- schedules: Record<string, {
71
- every: string;
72
- payload: Record<string, unknown>;
73
- }>;
74
+ schedules: Record<string, import("./options.js").PeriodScheduleOptions | import("./options.js").LocalTimeScheduleOptions>;
74
75
  pollIntervalMs: number;
75
76
  shutdownGraceMs: number;
76
77
  retention: {
@@ -81,7 +82,7 @@ export declare const jobs: import("@softure-ai/core").ModuleFactory<{}, {
81
82
  }>>>;
82
83
  export { JOB_STATUSES, type Job, type JobFailure, type JobOutcome, type JobsErrorCode, type JobStatus, } from "./contract.js";
83
84
  export { jobsMessages, type JobsMessages } from "./messages/index.js";
84
- export { jobsOptionsSchema, type JobQueueOptions, type JobScheduleOptions, type JobSchedulesInput, type JobsOptions, type JobsOptionsInput, } from "./options.js";
85
+ export { jobsOptionsSchema, type JobQueueOptions, type JobScheduleOptions, type JobSchedulesInput, type JobsOptions, type JobsOptionsInput, type LocalTimeScheduleOptions, type PeriodScheduleOptions, } from "./options.js";
85
86
  export { defineJobHandler, failJob, retryJobLater, type JobHandler, type JobHandlerContext, type JobHandlers } from "./handlers.js";
86
87
  export { jobs as jobsTable, schedules as jobSchedulesTable } from "./schema.js";
87
88
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,SAAS,SAAS,CAAC;AAEhC;;;GAGG;AACH,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAiBf,CAAC;AAEH,OAAO,EACL,YAAY,EACZ,KAAK,GAAG,EACR,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,SAAS,GACf,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EACL,iBAAiB,EACjB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,gBAAgB,GACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,aAAa,EAAE,KAAK,UAAU,EAAE,KAAK,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AACpI,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,SAAS,IAAI,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,SAAS,SAAS,CAAC;AAEhC;;;GAGG;AACH,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAiBf,CAAC;AAEH,OAAO,EACL,YAAY,EACZ,KAAK,GAAG,EACR,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,SAAS,GACf,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EACL,iBAAiB,EACjB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,GAC3B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,aAAa,EAAE,KAAK,UAAU,EAAE,KAAK,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AACpI,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,SAAS,IAAI,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -13,7 +13,7 @@ export const MODULE_ID = "jobs";
13
13
  export const jobs = defineModule({
14
14
  manifest: {
15
15
  id: MODULE_ID,
16
- version: "0.1.1",
16
+ version: "0.1.3",
17
17
  dependsOn: {},
18
18
  dbSchema: "jobs",
19
19
  tables: ["jobs", "schedules"],
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+GAA+G;AAC/G,oHAAoH;AACpH,uCAAuC;AACvC,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC;AAEhC;;;GAGG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,YAAY,CAAC;IAC/B,QAAQ,EAAE;QACR,EAAE,EAAE,SAAS;QACb,OAAO,EAAE,OAAO;QAChB,SAAS,EAAE,EAAE;QACb,QAAQ,EAAE,MAAM;QAChB,MAAM,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC;QAC7B,GAAG,EAAE,EAAE;QACP,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,EAAE;QACV,KAAK,EAAE,EAAE;QACT,OAAO,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE;KAC5C;IACD,QAAQ,EAAE,YAAY;IACtB,OAAO,EAAE,iBAAiB;IAC1B,UAAU,EAAE,EAAE,GAAG,EAAE,oBAAoB,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,gBAAgB,CAAC,EAAE;IAC5E,MAAM,EAAE,cAAc;CACvB,CAAC,CAAC;AAEH,OAAO,EACL,YAAY,GAMb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAqB,MAAM,qBAAqB,CAAC;AACtE,OAAO,EACL,iBAAiB,GAMlB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,aAAa,EAA6D,MAAM,eAAe,CAAC;AACpI,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,SAAS,IAAI,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+GAA+G;AAC/G,oHAAoH;AACpH,uCAAuC;AACvC,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC;AAEhC;;;GAGG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,YAAY,CAAC;IAC/B,QAAQ,EAAE;QACR,EAAE,EAAE,SAAS;QACb,OAAO,EAAE,OAAO;QAChB,SAAS,EAAE,EAAE;QACb,QAAQ,EAAE,MAAM;QAChB,MAAM,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC;QAC7B,GAAG,EAAE,EAAE;QACP,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,EAAE;QACV,KAAK,EAAE,EAAE;QACT,OAAO,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE;KAC5C;IACD,QAAQ,EAAE,YAAY;IACtB,OAAO,EAAE,iBAAiB;IAC1B,UAAU,EAAE,EAAE,GAAG,EAAE,oBAAoB,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,gBAAgB,CAAC,EAAE;IAC5E,MAAM,EAAE,cAAc;CACvB,CAAC,CAAC;AAEH,OAAO,EACL,YAAY,GAMb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAqB,MAAM,qBAAqB,CAAC;AACtE,OAAO,EACL,iBAAiB,GAQlB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,aAAa,EAA6D,MAAM,eAAe,CAAC;AACpI,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,SAAS,IAAI,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
package/dist/options.d.ts CHANGED
@@ -1,6 +1,17 @@
1
1
  import { z } from "zod";
2
2
  /** Seconds of an `every` text such as `15m`, `1h` or `1d`; null when it is not one or is outside 1m to 7d. */
3
3
  export declare function parseEverySeconds(every: string): number | null;
4
+ /** A schedule that runs once per period, aligned to UTC. */
5
+ export interface PeriodScheduleOptions {
6
+ readonly every: string;
7
+ readonly payload: Record<string, unknown>;
8
+ }
9
+ /** A schedule that runs at local times of day in a time zone; `at` is sorted. */
10
+ export interface LocalTimeScheduleOptions {
11
+ readonly at: readonly string[];
12
+ readonly timeZone: string;
13
+ readonly payload: Record<string, unknown>;
14
+ }
4
15
  export declare const jobsOptionsSchema: z.ZodPipe<z.ZodObject<{
5
16
  queues: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
6
17
  maxAttempts: z.ZodDefault<z.ZodNumber>;
@@ -11,10 +22,17 @@ export declare const jobsOptionsSchema: z.ZodPipe<z.ZodObject<{
11
22
  leaseSeconds: z.ZodDefault<z.ZodNumber>;
12
23
  concurrency: z.ZodDefault<z.ZodNumber>;
13
24
  }, z.core.$strict>>>;
14
- schedules: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
15
- every: z.ZodString;
25
+ schedules: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodPipe<z.ZodObject<{
26
+ every: z.ZodOptional<z.ZodString>;
27
+ at: z.ZodOptional<z.ZodArray<z.ZodString>>;
28
+ timeZone: z.ZodOptional<z.ZodString>;
16
29
  payload: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
17
- }, z.core.$strict>>>;
30
+ }, z.core.$strict>, z.ZodTransform<PeriodScheduleOptions | LocalTimeScheduleOptions, {
31
+ payload: Record<string, unknown>;
32
+ every?: string | undefined;
33
+ at?: string[] | undefined;
34
+ timeZone?: string | undefined;
35
+ }>>>>;
18
36
  pollIntervalMs: z.ZodDefault<z.ZodNumber>;
19
37
  shutdownGraceMs: z.ZodDefault<z.ZodNumber>;
20
38
  retention: z.ZodDefault<z.ZodObject<{
@@ -34,10 +52,7 @@ export declare const jobsOptionsSchema: z.ZodPipe<z.ZodObject<{
34
52
  concurrency: number;
35
53
  };
36
54
  };
37
- schedules: Record<string, {
38
- every: string;
39
- payload: Record<string, unknown>;
40
- }>;
55
+ schedules: Record<string, PeriodScheduleOptions | LocalTimeScheduleOptions>;
41
56
  pollIntervalMs: number;
42
57
  shutdownGraceMs: number;
43
58
  retention: {
@@ -55,10 +70,7 @@ export declare const jobsOptionsSchema: z.ZodPipe<z.ZodObject<{
55
70
  leaseSeconds: number;
56
71
  concurrency: number;
57
72
  }>;
58
- schedules: Record<string, {
59
- every: string;
60
- payload: Record<string, unknown>;
61
- }>;
73
+ schedules: Record<string, PeriodScheduleOptions | LocalTimeScheduleOptions>;
62
74
  pollIntervalMs: number;
63
75
  shutdownGraceMs: number;
64
76
  retention: {
@@ -1 +1 @@
1
- {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAuBtB,8GAA8G;AAC9G,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK9D;AAgCH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwB1B,CAAC;AAQL,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AACjE,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC7D,MAAM,MAAM,eAAe,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;AAC5D,MAAM,MAAM,kBAAkB,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAClE,iGAAiG;AACjG,MAAM,MAAM,iBAAiB,GAAG,WAAW,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAwBtB,8GAA8G;AAC9G,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK9D;AAyCH,4DAA4D;AAC5D,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC3C;AAED,iFAAiF;AACjF,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC3C;AAyBD,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyB1B,CAAC;AAQL,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AACjE,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC7D,MAAM,MAAM,eAAe,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;AAC5D,MAAM,MAAM,kBAAkB,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAClE,iGAAiG;AACjG,MAAM,MAAM,iBAAiB,GAAG,WAAW,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC"}
package/dist/options.js CHANGED
@@ -1,5 +1,6 @@
1
1
  // The options an app passes to `jobs({ ... })` in softure.config.ts, parsed at startup.
2
2
  import { z } from "zod";
3
+ import { isTimeZone } from "./zoned-time.js";
3
4
  const QUEUE_NAME = /^[a-z][a-z0-9_.-]{0,62}$/;
4
5
  const QUEUE_NAME_HINT = "is not a queue name: lowercase letters, digits, _ . and -, starting with a letter";
5
6
  const DAY_SECONDS = 24 * 60 * 60;
@@ -26,11 +27,42 @@ export function parseEverySeconds(every) {
26
27
  const seconds = Number(match[1]) * UNIT_SECONDS[match[2]];
27
28
  return seconds <= MAX_EVERY_SECONDS ? seconds : null;
28
29
  }
29
- const scheduleSchema = z.strictObject({
30
+ const AT_TIME = /^([01][0-9]|2[0-3]):[0-5][0-9]$/;
31
+ const AT_HINT = "must be times of day as HH:MM (00:00 to 23:59), each once";
32
+ const MAX_AT_TIMES = 48;
33
+ const scheduleSchema = z
34
+ .strictObject({
30
35
  /** How often the schedule runs: `15m`, `1h`, `1d`. Runs start on whole periods counted from 1970-01-01 00:00 UTC. */
31
- every: z.string().refine((every) => parseEverySeconds(every) !== null, { message: EVERY_HINT }),
36
+ every: z.string().refine((every) => parseEverySeconds(every) !== null, { message: EVERY_HINT }).optional(),
37
+ /** Instead of `every`: the local times of day the schedule runs at, `HH:MM`, in `timeZone`. */
38
+ at: z
39
+ .array(z.string().regex(AT_TIME, { message: AT_HINT }))
40
+ .min(1)
41
+ .max(MAX_AT_TIMES)
42
+ .refine((times) => new Set(times).size === times.length, { message: AT_HINT })
43
+ .optional(),
44
+ /** The IANA time zone of `at`, such as `Europe/Warsaw`; required with `at`. */
45
+ timeZone: z.string().refine(isTimeZone, { message: "is not a time zone the runtime knows (an IANA name such as Europe/Warsaw)" }).optional(),
32
46
  /** The payload of every run; default `{}`. */
33
47
  payload: z.record(z.string(), z.unknown()).default({}),
48
+ })
49
+ .superRefine((schedule, context) => {
50
+ if ((schedule.every === undefined) === (schedule.at === undefined)) {
51
+ context.addIssue({ code: "custom", path: ["every"], message: "set either every or at, not both" });
52
+ }
53
+ if (schedule.at !== undefined && schedule.timeZone === undefined) {
54
+ context.addIssue({ code: "custom", path: ["timeZone"], message: "is required with at" });
55
+ }
56
+ if (schedule.every !== undefined && schedule.timeZone !== undefined) {
57
+ context.addIssue({ code: "custom", path: ["timeZone"], message: "applies to at only; every runs in UTC" });
58
+ }
59
+ })
60
+ .transform((schedule) => {
61
+ if (schedule.at !== undefined && schedule.timeZone !== undefined) {
62
+ return { at: [...schedule.at].sort(), timeZone: schedule.timeZone, payload: schedule.payload };
63
+ }
64
+ // The refinement above leaves every set whenever at is not.
65
+ return { every: schedule.every ?? "", payload: schedule.payload };
34
66
  });
35
67
  const queueSchema = z.strictObject({
36
68
  /** Attempts before a job is `failed` for good; the first run counts. */
@@ -58,8 +90,9 @@ export const jobsOptionsSchema = z
58
90
  /** The queues, by name. A job is enqueued to one of them and runs with its settings. */
59
91
  queues: z.record(z.string(), queueSchema).default({}).superRefine(checkNames),
60
92
  /**
61
- * Recurring runs, by queue name: the worker enqueues one job per period (`every`) however many workers run. A
62
- * schedule's queue takes the default queue settings unless `queues` names it.
93
+ * Recurring runs, by queue name: the worker enqueues one job per period (`every`) or per local time of day (`at`
94
+ * in `timeZone`) however many workers run. A schedule's queue takes the default queue settings unless `queues`
95
+ * names it.
63
96
  */
64
97
  schedules: z.record(z.string(), scheduleSchema).default({}).superRefine(checkNames),
65
98
  /** How long an idle worker waits before it looks for due jobs again. */
@@ -1 +1 @@
1
- {"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"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"}
package/dist/schema.d.ts CHANGED
@@ -317,6 +317,40 @@ export declare const schedules: import("drizzle-orm/pg-core").PgTableWithColumns
317
317
  identity: undefined;
318
318
  generated: undefined;
319
319
  }, {}, {}>;
320
+ lastFailedAt: import("drizzle-orm/pg-core").PgColumn<{
321
+ name: "last_failed_at";
322
+ tableName: "schedules";
323
+ dataType: "date";
324
+ columnType: "PgTimestamp";
325
+ data: Date;
326
+ driverParam: string;
327
+ notNull: false;
328
+ hasDefault: false;
329
+ isPrimaryKey: false;
330
+ isAutoincrement: false;
331
+ hasRuntimeDefault: false;
332
+ enumValues: undefined;
333
+ baseColumn: never;
334
+ identity: undefined;
335
+ generated: undefined;
336
+ }, {}, {}>;
337
+ lastFailureCode: import("drizzle-orm/pg-core").PgColumn<{
338
+ name: "last_failure_code";
339
+ tableName: "schedules";
340
+ dataType: "string";
341
+ columnType: "PgText";
342
+ data: string;
343
+ driverParam: string;
344
+ notNull: false;
345
+ hasDefault: false;
346
+ isPrimaryKey: false;
347
+ isAutoincrement: false;
348
+ hasRuntimeDefault: false;
349
+ enumValues: [string, ...string[]];
350
+ baseColumn: never;
351
+ identity: undefined;
352
+ generated: undefined;
353
+ }, {}, {}>;
320
354
  createdAt: import("drizzle-orm/pg-core").PgColumn<{
321
355
  name: "created_at";
322
356
  tableName: "schedules";
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,UAAU,gDAAmB,CAAC;AAE3C,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgBf,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,OAAO,IAAI,CAAC,YAAY,CAAC;AAE9C,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAMpB,CAAC"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,UAAU,gDAAmB,CAAC;AAE3C,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgBf,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,OAAO,IAAI,CAAC,YAAY,CAAC;AAE9C,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQpB,CAAC"}
package/dist/schema.js CHANGED
@@ -23,6 +23,8 @@ export const schedules = jobsSchema.table("schedules", {
23
23
  name: text("name").primaryKey(),
24
24
  lastSlotAt: timestamp("last_slot_at", { withTimezone: true }).notNull(),
25
25
  lastSucceededAt: timestamp("last_succeeded_at", { withTimezone: true }),
26
+ lastFailedAt: timestamp("last_failed_at", { withTimezone: true }),
27
+ lastFailureCode: text("last_failure_code"),
26
28
  createdAt: timestamp("created_at", { withTimezone: true }).notNull(),
27
29
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull(),
28
30
  });
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,+BAA+B;AAC/B,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAE9F,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;AAE3C,MAAM,CAAC,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE;IAC3C,EAAE,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,yBAAyB,EAAE;IAC7E,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE;IAC9B,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;IACnC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE;IACtG,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE;IACvC,WAAW,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE;IAC9C,KAAK,EAAE,SAAS,CAAC,QAAQ,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE;IAC5D,WAAW,EAAE,SAAS,CAAC,cAAc,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IAC9D,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC;IAC3B,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC;IAC/B,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC;IAC3B,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC;IAC7B,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE;IACpE,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE;IACpE,UAAU,EAAE,SAAS,CAAC,aAAa,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;CAC7D,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,EAAE;IACrD,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE;IAC/B,UAAU,EAAE,SAAS,CAAC,cAAc,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE;IACvE,eAAe,EAAE,SAAS,CAAC,mBAAmB,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IACvE,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE;IACpE,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE;CACrE,CAAC,CAAC"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,+BAA+B;AAC/B,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAE9F,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;AAE3C,MAAM,CAAC,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE;IAC3C,EAAE,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,yBAAyB,EAAE;IAC7E,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE;IAC9B,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;IACnC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE;IACtG,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE;IACvC,WAAW,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE;IAC9C,KAAK,EAAE,SAAS,CAAC,QAAQ,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE;IAC5D,WAAW,EAAE,SAAS,CAAC,cAAc,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IAC9D,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC;IAC3B,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC;IAC/B,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC;IAC3B,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC;IAC7B,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE;IACpE,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE;IACpE,UAAU,EAAE,SAAS,CAAC,aAAa,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;CAC7D,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,EAAE;IACrD,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE;IAC/B,UAAU,EAAE,SAAS,CAAC,cAAc,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE;IACvE,eAAe,EAAE,SAAS,CAAC,mBAAmB,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IACvE,YAAY,EAAE,SAAS,CAAC,gBAAgB,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IACjE,eAAe,EAAE,IAAI,CAAC,mBAAmB,CAAC;IAC1C,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE;IACpE,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE;CACrE,CAAC,CAAC"}
@@ -33,7 +33,8 @@ export declare function claimJobs(ctx: JobsContext, input: ClaimJobsInput): Prom
33
33
  /** Pushes the lease of a held job forward. False when the job is no longer this claim's: stop working on it. */
34
34
  export declare function extendJobLease(ctx: JobsContext, claimed: ClaimedJob): Promise<boolean>;
35
35
  /**
36
- * Records the end of an attempt; a success of a scheduled queue also updates its schedule, in the same transaction.
36
+ * Records the end of an attempt; a success or a terminal failure of a scheduled queue also updates its schedule, in
37
+ * the same transaction.
37
38
  * False when the job is no longer this claim's: nothing was written.
38
39
  */
39
40
  export declare function completeJob(ctx: JobsContext, claimed: ClaimedJob, completion: Completion): Promise<boolean>;
@@ -1 +1 @@
1
- {"version":3,"file":"claim.d.ts","sourceRoot":"","sources":["../../src/server/claim.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAE1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAKhD,iFAAiF;AACjF,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,8BAA8B;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,gGAAgG;IAChG,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,uCAAuC;AACvC,MAAM,MAAM,UAAU,GAClB;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;CAAE,GAC9B;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GACxE;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAIxD;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAsC9F;AAED,gHAAgH;AAChH,wBAAsB,cAAc,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAS5F;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAejH;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAgBxF"}
1
+ {"version":3,"file":"claim.d.ts","sourceRoot":"","sources":["../../src/server/claim.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAE1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAKhD,iFAAiF;AACjF,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,8BAA8B;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,gGAAgG;IAChG,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,uCAAuC;AACvC,MAAM,MAAM,UAAU,GAClB;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;CAAE,GAC9B;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GACxE;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAIxD;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAsC9F;AAED,gHAAgH;AAChH,wBAAsB,cAAc,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAS5F;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAgBjH;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAgBxF"}
@@ -4,7 +4,7 @@ import { and, asc, eq, gte, inArray, lte, or, sql } from "drizzle-orm";
4
4
  import { jobs } from "../schema.js";
5
5
  import { toJob } from "./job-row.js";
6
6
  import { getJobsOptions, getQueue } from "./options.js";
7
- import { recordScheduleSuccess } from "./schedules.js";
7
+ import { recordScheduleFailure, recordScheduleSuccess } from "./schedules.js";
8
8
  const LEASE_EXPIRED = "jobs.lease_expired";
9
9
  /**
10
10
  * Claims up to `limit` due jobs of one queue, oldest due first: pending jobs whose `run_at` has come and running jobs
@@ -53,7 +53,8 @@ export async function extendJobLease(ctx, claimed) {
53
53
  return rows.length > 0;
54
54
  }
55
55
  /**
56
- * Records the end of an attempt; a success of a scheduled queue also updates its schedule, in the same transaction.
56
+ * Records the end of an attempt; a success or a terminal failure of a scheduled queue also updates its schedule, in
57
+ * the same transaction.
57
58
  * False when the job is no longer this claim's: nothing was written.
58
59
  */
59
60
  export async function completeJob(ctx, claimed, completion) {
@@ -70,6 +71,8 @@ export async function completeJob(ctx, claimed, completion) {
70
71
  return false;
71
72
  if (completion.kind === "succeeded")
72
73
  await recordScheduleSuccess({ ...ctx, db: tx }, claimed.job.queue);
74
+ if (completion.kind === "failed")
75
+ await recordScheduleFailure({ ...ctx, db: tx }, claimed.job.queue, completion.error);
73
76
  return true;
74
77
  });
75
78
  }
@@ -95,18 +98,23 @@ export async function releaseJob(ctx, claimed) {
95
98
  return rows.length > 0;
96
99
  }
97
100
  async function failExhaustedLeases(ctx, queue, now) {
98
- await ctx.db
99
- .update(jobs)
100
- .set({
101
- status: "failed",
102
- lastError: LEASE_EXPIRED,
103
- finishedAt: now,
104
- lockedUntil: null,
105
- lockedBy: null,
106
- claimToken: null,
107
- updatedAt: now,
108
- })
109
- .where(and(eq(jobs.queue, queue), eq(jobs.status, "running"), lte(jobs.lockedUntil, now), gte(jobs.attempts, jobs.maxAttempts)));
101
+ await ctx.db.transaction(async (tx) => {
102
+ const failed = await tx
103
+ .update(jobs)
104
+ .set({
105
+ status: "failed",
106
+ lastError: LEASE_EXPIRED,
107
+ finishedAt: now,
108
+ lockedUntil: null,
109
+ lockedBy: null,
110
+ claimToken: null,
111
+ updatedAt: now,
112
+ })
113
+ .where(and(eq(jobs.queue, queue), eq(jobs.status, "running"), lte(jobs.lockedUntil, now), gte(jobs.attempts, jobs.maxAttempts)))
114
+ .returning({ id: jobs.id });
115
+ if (failed.length > 0)
116
+ await recordScheduleFailure({ ...ctx, db: tx }, queue, LEASE_EXPIRED);
117
+ });
110
118
  }
111
119
  function isHeld(claimed) {
112
120
  return and(eq(jobs.id, BigInt(claimed.job.id)), eq(jobs.status, "running"), eq(jobs.claimToken, claimed.claimToken));
@@ -1 +1 @@
1
- {"version":3,"file":"claim.js","sourceRoot":"","sources":["../../src/server/claim.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"claim.js","sourceRoot":"","sources":["../../src/server/claim.ts"],"names":[],"mappings":"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"}