@softure-ai/jobs 0.1.0 → 0.1.1

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 (49) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +75 -10
  3. package/dist/index.d.ts +54 -6
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +4 -4
  6. package/dist/index.js.map +1 -1
  7. package/dist/options.d.ts +57 -4
  8. package/dist/options.d.ts.map +1 -1
  9. package/dist/options.js +40 -10
  10. package/dist/options.js.map +1 -1
  11. package/dist/schema.d.ts +92 -0
  12. package/dist/schema.d.ts.map +1 -1
  13. package/dist/schema.js +8 -1
  14. package/dist/schema.js.map +1 -1
  15. package/dist/server/claim.d.ts +4 -1
  16. package/dist/server/claim.d.ts.map +1 -1
  17. package/dist/server/claim.js +13 -3
  18. package/dist/server/claim.js.map +1 -1
  19. package/dist/server/index.d.ts +1 -0
  20. package/dist/server/index.d.ts.map +1 -1
  21. package/dist/server/index.js +1 -0
  22. package/dist/server/index.js.map +1 -1
  23. package/dist/server/maintenance.d.ts +5 -2
  24. package/dist/server/maintenance.d.ts.map +1 -1
  25. package/dist/server/maintenance.js +5 -3
  26. package/dist/server/maintenance.js.map +1 -1
  27. package/dist/server/run-due.d.ts +1 -1
  28. package/dist/server/run-due.d.ts.map +1 -1
  29. package/dist/server/run-due.js +3 -1
  30. package/dist/server/run-due.js.map +1 -1
  31. package/dist/server/schedules.d.ts +45 -0
  32. package/dist/server/schedules.d.ts.map +1 -0
  33. package/dist/server/schedules.js +97 -0
  34. package/dist/server/schedules.js.map +1 -0
  35. package/dist/worker/run-job-worker.d.ts.map +1 -1
  36. package/dist/worker/run-job-worker.js +21 -3
  37. package/dist/worker/run-job-worker.js.map +1 -1
  38. package/migrations/0002_create_schedules.sql +12 -0
  39. package/module.json +2 -2
  40. package/package.json +1 -1
  41. package/src/index.ts +11 -4
  42. package/src/options.ts +61 -25
  43. package/src/schema.ts +9 -1
  44. package/src/server/claim.ts +11 -3
  45. package/src/server/index.ts +7 -0
  46. package/src/server/maintenance.ts +7 -3
  47. package/src/server/run-due.ts +3 -1
  48. package/src/server/schedules.ts +121 -0
  49. package/src/worker/run-job-worker.ts +18 -3
@@ -4,6 +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
8
  const LEASE_EXPIRED = "jobs.lease_expired";
8
9
  /**
9
10
  * Claims up to `limit` due jobs of one queue, oldest due first: pending jobs whose `run_at` has come and running jobs
@@ -51,7 +52,10 @@ export async function extendJobLease(ctx, claimed) {
51
52
  .returning();
52
53
  return rows.length > 0;
53
54
  }
54
- /** Records the end of an attempt. False when the job is no longer this claim's: nothing was written. */
55
+ /**
56
+ * Records the end of an attempt; a success of a scheduled queue also updates its schedule, in the same transaction.
57
+ * False when the job is no longer this claim's: nothing was written.
58
+ */
55
59
  export async function completeJob(ctx, claimed, completion) {
56
60
  const now = ctx.clock.now();
57
61
  const unlocked = { lockedUntil: null, lockedBy: null, claimToken: null, updatedAt: now };
@@ -60,8 +64,14 @@ export async function completeJob(ctx, claimed, completion) {
60
64
  : completion.kind === "retry"
61
65
  ? { ...unlocked, status: "pending", runAt: completion.runAt, lastError: completion.error }
62
66
  : { ...unlocked, status: "failed", finishedAt: now, lastError: completion.error };
63
- const rows = await ctx.db.update(jobs).set(set).where(isHeld(claimed)).returning();
64
- return rows.length > 0;
67
+ return ctx.db.transaction(async (tx) => {
68
+ const rows = await tx.update(jobs).set(set).where(isHeld(claimed)).returning();
69
+ if (rows.length === 0)
70
+ return false;
71
+ if (completion.kind === "succeeded")
72
+ await recordScheduleSuccess({ ...ctx, db: tx }, claimed.job.queue);
73
+ return true;
74
+ });
65
75
  }
66
76
  /**
67
77
  * Gives a held job back without an outcome (the worker is stopping): pending again, due now, and the attempt is not
@@ -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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"}
@@ -6,5 +6,6 @@ export { consoleJobsLogger, type JobsLogFields, type JobsLogger } from "./logger
6
6
  export { getQueueStats, pruneJobs, type QueueStats } from "./maintenance.js";
7
7
  export { getJobsOptions } from "./options.js";
8
8
  export { runClaimedJob, type RunClaimedJobOptions } from "./process.js";
9
+ export { enqueueDueSchedules, getScheduleSlot, SCHEDULE_DEDUP_KEY, type EnqueueDueSchedulesInput, type ScheduleState, } from "./schedules.js";
9
10
  export { runDueJobs, type RunDueJobsOptions, type RunDueJobsReport } from "./run-due.js";
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AACpG,OAAO,EACL,SAAS,EACT,WAAW,EACX,cAAc,EACd,UAAU,EACV,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,UAAU,GAChB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAClF,OAAO,EAAE,iBAAiB,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AACpG,OAAO,EACL,SAAS,EACT,WAAW,EACX,cAAc,EACd,UAAU,EACV,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,UAAU,GAChB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAClF,OAAO,EAAE,iBAAiB,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,kBAAkB,EAClB,KAAK,wBAAwB,EAC7B,KAAK,aAAa,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
@@ -7,5 +7,6 @@ export { consoleJobsLogger } from "./logger.js";
7
7
  export { getQueueStats, pruneJobs } from "./maintenance.js";
8
8
  export { getJobsOptions } from "./options.js";
9
9
  export { runClaimedJob } from "./process.js";
10
+ export { enqueueDueSchedules, getScheduleSlot, SCHEDULE_DEDUP_KEY, } from "./schedules.js";
10
11
  export { runDueJobs } from "./run-due.js";
11
12
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,kHAAkH;AAClH,8BAA8B;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAA6C,MAAM,YAAY,CAAC;AACpG,OAAO,EACL,SAAS,EACT,WAAW,EACX,cAAc,EACd,UAAU,GAIX,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,UAAU,EAA0C,MAAM,cAAc,CAAC;AAClF,OAAO,EAAE,iBAAiB,EAAuC,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,SAAS,EAAmB,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAA6B,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,UAAU,EAAiD,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,kHAAkH;AAClH,8BAA8B;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAA6C,MAAM,YAAY,CAAC;AACpG,OAAO,EACL,SAAS,EACT,WAAW,EACX,cAAc,EACd,UAAU,GAIX,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,UAAU,EAA0C,MAAM,cAAc,CAAC;AAClF,OAAO,EAAE,iBAAiB,EAAuC,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,SAAS,EAAmB,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAA6B,MAAM,cAAc,CAAC;AACxE,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,kBAAkB,GAGnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,UAAU,EAAiD,MAAM,cAAc,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { type JobStatus } from "../contract.js";
2
2
  import type { JobsContext } from "./context.js";
3
+ import { type ScheduleState } from "./schedules.js";
3
4
  /**
4
5
  * Deletes succeeded, failed and cancelled jobs older (by `finished_at`) than their retention, in batches. Returns the
5
6
  * number of deleted jobs. The worker calls it once an hour; an app without a worker may call it from a cron.
@@ -13,10 +14,12 @@ export interface QueueStats {
13
14
  readonly due: number;
14
15
  /** The `run_at` of the oldest due pending job, or null: how far behind the workers are. */
15
16
  readonly oldestDueAt: Date | null;
17
+ /** The queue's schedule, when `schedules` names it: when it last ran and whether it is late. */
18
+ readonly schedule: ScheduleState | null;
16
19
  }
17
20
  /**
18
- * Counts per queue: every configured queue, plus any queue that still has rows in the table. For a dashboard, an ops
19
- * script or a health check of the app's own (`ops({ checks })`).
21
+ * Counts per queue: every configured queue, plus any queue that still has rows in the table, with the state of its
22
+ * schedule. For a dashboard, an ops script or a health check of the app's own (`ops({ checks })`).
20
23
  */
21
24
  export declare function getQueueStats(ctx: JobsContext): Promise<QueueStats[]>;
22
25
  //# sourceMappingURL=maintenance.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"maintenance.d.ts","sourceRoot":"","sources":["../../src/server/maintenance.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAOhD;;;GAGG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBjE;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,uBAAuB;IACvB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;IACrD,4FAA4F;IAC5F,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,2FAA2F;IAC3F,QAAQ,CAAC,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;CACnC;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAmB3E"}
1
+ {"version":3,"file":"maintenance.d.ts","sourceRoot":"","sources":["../../src/server/maintenance.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,EAAqB,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAMvE;;;GAGG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBjE;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,uBAAuB;IACvB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;IACrD,4FAA4F;IAC5F,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,2FAA2F;IAC3F,QAAQ,CAAC,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IAClC,gGAAgG;IAChG,QAAQ,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;CACzC;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAoB3E"}
@@ -3,6 +3,7 @@ import { and, eq, inArray, lt, min, or, sql } from "drizzle-orm";
3
3
  import { JOB_STATUSES } from "../contract.js";
4
4
  import { jobs } from "../schema.js";
5
5
  import { getJobsOptions } from "./options.js";
6
+ import { getScheduleStates } from "./schedules.js";
6
7
  const DAY_MS = 24 * 60 * 60 * 1000;
7
8
  /** Rows deleted per statement, so pruning a large backlog never holds one long lock. */
8
9
  const PRUNE_BATCH = 1000;
@@ -25,8 +26,8 @@ export async function pruneJobs(ctx) {
25
26
  }
26
27
  }
27
28
  /**
28
- * Counts per queue: every configured queue, plus any queue that still has rows in the table. For a dashboard, an ops
29
- * script or a health check of the app's own (`ops({ checks })`).
29
+ * Counts per queue: every configured queue, plus any queue that still has rows in the table, with the state of its
30
+ * schedule. For a dashboard, an ops script or a health check of the app's own (`ops({ checks })`).
30
31
  */
31
32
  export async function getQueueStats(ctx) {
32
33
  const now = ctx.clock.now();
@@ -39,13 +40,14 @@ export async function getQueueStats(ctx) {
39
40
  .from(jobs)
40
41
  .where(and(eq(jobs.status, "pending"), sql `${jobs.runAt} <= ${now}`))
41
42
  .groupBy(jobs.queue);
43
+ const scheduleStates = await getScheduleStates(ctx);
42
44
  const names = new Set([...Object.keys(getJobsOptions(ctx.config).queues), ...counted.map((row) => row.queue)]);
43
45
  return [...names].map((queue) => {
44
46
  const counts = Object.fromEntries(JOB_STATUSES.map((status) => [status, 0]));
45
47
  for (const row of counted.filter((candidate) => candidate.queue === queue))
46
48
  counts[row.status] = row.count;
47
49
  const due = backlog.find((row) => row.queue === queue);
48
- return { queue, counts, due: due?.due ?? 0, oldestDueAt: due?.oldestDueAt ?? null };
50
+ return { queue, counts, due: due?.due ?? 0, oldestDueAt: due?.oldestDueAt ?? null, schedule: scheduleStates.get(queue) ?? null };
49
51
  });
50
52
  }
51
53
  //# sourceMappingURL=maintenance.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"maintenance.js","sourceRoot":"","sources":["../../src/server/maintenance.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"maintenance.js","sourceRoot":"","sources":["../../src/server/maintenance.ts"],"names":[],"mappings":"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"}
@@ -21,7 +21,7 @@ export interface RunDueJobsReport {
21
21
  readonly stale: number;
22
22
  }
23
23
  /**
24
- * Claims and runs due jobs until none is due (a retried job is due later, so it waits for the clock). Returns what
24
+ * Enqueues the due runs of the schedules among its queues, then claims and runs due jobs until none is due (a retried job is due later, so it waits for the clock). Returns what
25
25
  * happened. Throws on a handler for a queue the config does not define; database failures propagate.
26
26
  */
27
27
  export declare function runDueJobs(ctx: JobsContext, options: RunDueJobsOptions): Promise<RunDueJobsReport>;
@@ -1 +1 @@
1
- {"version":3,"file":"run-due.d.ts","sourceRoot":"","sources":["../../src/server/run-due.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAqB,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAQjE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,iEAAiE;IACjE,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAC7B,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,oFAAoF;IACpF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;IAC/B,4GAA4G;IAC5G,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAyBxG"}
1
+ {"version":3,"file":"run-due.d.ts","sourceRoot":"","sources":["../../src/server/run-due.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAqB,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AASjE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,iEAAiE;IACjE,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAC7B,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,oFAAoF;IACpF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;IAC/B,4GAA4G;IAC5G,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA0BxG"}
@@ -3,14 +3,16 @@ import { consoleJobsLogger } from "./logger.js";
3
3
  import { getJobsOptions } from "./options.js";
4
4
  import { runClaimedJob } from "./process.js";
5
5
  import { checkHandlers } from "./handler-check.js";
6
+ import { enqueueDueSchedules } from "./schedules.js";
6
7
  const DEFAULT_MAX_JOBS = 1000;
7
8
  const NEVER_ABORTED = new AbortController().signal;
8
9
  /**
9
- * Claims and runs due jobs until none is due (a retried job is due later, so it waits for the clock). Returns what
10
+ * Enqueues the due runs of the schedules among its queues, then claims and runs due jobs until none is due (a retried job is due later, so it waits for the clock). Returns what
10
11
  * happened. Throws on a handler for a queue the config does not define; database failures propagate.
11
12
  */
12
13
  export async function runDueJobs(ctx, options) {
13
14
  const queues = checkHandlers(getJobsOptions(ctx.config), options.handlers, options.queues);
15
+ await enqueueDueSchedules(ctx, { queues });
14
16
  const report = { succeeded: 0, retried: 0, failed: 0, stale: 0 };
15
17
  const maxJobs = options.maxJobs ?? DEFAULT_MAX_JOBS;
16
18
  const runOptions = {
@@ -1 +1 @@
1
- {"version":3,"file":"run-due.js","sourceRoot":"","sources":["../../src/server/run-due.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,iBAAiB,EAAmB,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAC9B,MAAM,aAAa,GAAG,IAAI,eAAe,EAAE,CAAC,MAAM,CAAC;AAuBnD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAgB,EAAE,OAA0B;IAC3E,MAAM,MAAM,GAAG,aAAa,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3F,MAAM,MAAM,GAAG,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IACjE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,gBAAgB,CAAC;IACpD,MAAM,UAAU,GAAG;QACjB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,iBAAiB;QAC3C,MAAM,EAAE,aAAa;QACrB,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM;KACtC,CAAC;IACF,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,UAAU,GAAG,IAAI,CAAC;IACtB,OAAO,UAAU,IAAI,QAAQ,GAAG,OAAO,EAAE,CAAC;QACxC,UAAU,GAAG,KAAK,CAAC;QACnB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,cAAc,EAAE,CAAC,CAAC;YAC1G,IAAI,OAAO,KAAK,SAAS;gBAAE,SAAS;YACpC,UAAU,GAAG,IAAI,CAAC;YAClB,QAAQ,IAAI,CAAC,CAAC;YACd,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;YAC9D,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1B,IAAI,QAAQ,IAAI,OAAO;gBAAE,MAAM;QACjC,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"run-due.js","sourceRoot":"","sources":["../../src/server/run-due.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,iBAAiB,EAAmB,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAErD,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAC9B,MAAM,aAAa,GAAG,IAAI,eAAe,EAAE,CAAC,MAAM,CAAC;AAuBnD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAgB,EAAE,OAA0B;IAC3E,MAAM,MAAM,GAAG,aAAa,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3F,MAAM,mBAAmB,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IACjE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,gBAAgB,CAAC;IACpD,MAAM,UAAU,GAAG;QACjB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,iBAAiB;QAC3C,MAAM,EAAE,aAAa;QACrB,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM;KACtC,CAAC;IACF,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,UAAU,GAAG,IAAI,CAAC;IACtB,OAAO,UAAU,IAAI,QAAQ,GAAG,OAAO,EAAE,CAAC;QACxC,UAAU,GAAG,KAAK,CAAC;QACnB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,cAAc,EAAE,CAAC,CAAC;YAC1G,IAAI,OAAO,KAAK,SAAS;gBAAE,SAAS;YACpC,UAAU,GAAG,IAAI,CAAC;YAClB,QAAQ,IAAI,CAAC,CAAC;YACd,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;YAC9D,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1B,IAAI,QAAQ,IAAI,OAAO;gBAAE,MAAM;QACjC,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,45 @@
1
+ import { type JobScheduleOptions, type JobsOptions } from "../options.js";
2
+ import type { JobsContext } from "./context.js";
3
+ /**
4
+ * The dedup key of every scheduled run: while one run of a schedule is pending or running (retrying a failure, say),
5
+ * the next period joins it instead of piling up a second run behind it.
6
+ */
7
+ export declare const SCHEDULE_DEDUP_KEY = "schedule";
8
+ /** A schedule's health as `getQueueStats` reports it. */
9
+ export interface ScheduleState {
10
+ readonly everySeconds: number;
11
+ /** The start of the latest period a run was enqueued for; null before any worker saw the schedule. */
12
+ readonly lastEnqueuedAt: Date | null;
13
+ /** When a job of the schedule's queue last succeeded; null when none has yet. */
14
+ readonly lastSucceededAt: Date | null;
15
+ /**
16
+ * True when no run succeeded within two periods (counted from when a worker first saw the schedule), or no worker
17
+ * has seen it at all: no worker runs its queue, or its runs keep failing.
18
+ */
19
+ readonly isLate: boolean;
20
+ }
21
+ export interface EnqueueDueSchedulesInput {
22
+ /** Only the schedules of these queues; default every schedule. */
23
+ readonly queues?: readonly string[];
24
+ }
25
+ /** The start of the period `now` falls in. */
26
+ export declare function getScheduleSlot(schedule: JobScheduleOptions, now: Date): Date;
27
+ /**
28
+ * Enqueues a run for every schedule whose current period has none yet, and returns their queue names. Missed periods
29
+ * (no worker ran) collapse into one run for the current period. The worker calls it; an app that drains its queues
30
+ * from a cron (`runDueJobs`) gets it from there. Database failures propagate.
31
+ */
32
+ export declare function enqueueDueSchedules(ctx: JobsContext, input?: EnqueueDueSchedulesInput): Promise<string[]>;
33
+ /**
34
+ * Takes `slot` for the schedule `name` and enqueues its run, in one transaction. False when the schedule already has
35
+ * this period or a later one (another worker took it). Throws on a name that is not a schedule.
36
+ */
37
+ export declare function enqueueScheduledRun(ctx: JobsContext, name: string, slot: Date): Promise<boolean>;
38
+ /** Notes a succeeded job of a scheduled queue (any job of it, a run enqueued by hand too). */
39
+ export declare function recordScheduleSuccess(ctx: JobsContext, queue: string): Promise<void>;
40
+ /** The state of every configured schedule, by queue name. */
41
+ export declare function getScheduleStates(ctx: JobsContext): Promise<Map<string, ScheduleState>>;
42
+ /** The schedules among `queues` (default all), in configuration order. */
43
+ export declare function getScheduleNames(options: JobsOptions, queues: readonly string[] | undefined): string[];
44
+ export declare function getSchedule(options: JobsOptions, name: string): JobScheduleOptions;
45
+ //# sourceMappingURL=schedules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedules.d.ts","sourceRoot":"","sources":["../../src/server/schedules.ts"],"names":[],"mappings":"AAIA,OAAO,EAAqB,KAAK,kBAAkB,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAE7F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAIhD;;;GAGG;AACH,eAAO,MAAM,kBAAkB,aAAa,CAAC;AAE7C,yDAAyD;AACzD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,sGAAsG;IACtG,QAAQ,CAAC,cAAc,EAAE,IAAI,GAAG,IAAI,CAAC;IACrC,iFAAiF;IACjF,QAAQ,CAAC,eAAe,EAAE,IAAI,GAAG,IAAI,CAAC;IACtC;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,wBAAwB;IACvC,kEAAkE;IAClE,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,8CAA8C;AAC9C,wBAAgB,eAAe,CAAC,QAAQ,EAAE,kBAAkB,EAAE,GAAG,EAAE,IAAI,GAAG,IAAI,CAG7E;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,GAAE,wBAA6B,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAQnH;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAiBtG;AAED,8FAA8F;AAC9F,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI1F;AAED,6DAA6D;AAC7D,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAe7F;AAED,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GAAG,MAAM,EAAE,CAEtG;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,kBAAkB,CAIlF"}
@@ -0,0 +1,97 @@
1
+ // Recurring schedules: each schedule's runs start on whole periods counted from the Unix epoch, so every worker
2
+ // computes the same period. A worker takes a period with a conditional upsert of `jobs.schedules` and enqueues its run
3
+ // in the same transaction, so each period is enqueued once however many workers race for it.
4
+ import { eq, inArray, lt } from "drizzle-orm";
5
+ import { parseEverySeconds } from "../options.js";
6
+ import { schedules } from "../schema.js";
7
+ import { enqueueJob } from "./enqueue.js";
8
+ import { getJobsOptions } from "./options.js";
9
+ /**
10
+ * The dedup key of every scheduled run: while one run of a schedule is pending or running (retrying a failure, say),
11
+ * the next period joins it instead of piling up a second run behind it.
12
+ */
13
+ export const SCHEDULE_DEDUP_KEY = "schedule";
14
+ /** The start of the period `now` falls in. */
15
+ export function getScheduleSlot(schedule, now) {
16
+ const periodMs = getEverySeconds(schedule) * 1000;
17
+ return new Date(Math.floor(now.getTime() / periodMs) * periodMs);
18
+ }
19
+ /**
20
+ * Enqueues a run for every schedule whose current period has none yet, and returns their queue names. Missed periods
21
+ * (no worker ran) collapse into one run for the current period. The worker calls it; an app that drains its queues
22
+ * from a cron (`runDueJobs`) gets it from there. Database failures propagate.
23
+ */
24
+ export async function enqueueDueSchedules(ctx, input = {}) {
25
+ const options = getJobsOptions(ctx.config);
26
+ const enqueued = [];
27
+ for (const name of getScheduleNames(options, input.queues)) {
28
+ const slot = getScheduleSlot(getSchedule(options, name), ctx.clock.now());
29
+ if (await enqueueScheduledRun(ctx, name, slot))
30
+ enqueued.push(name);
31
+ }
32
+ return enqueued;
33
+ }
34
+ /**
35
+ * Takes `slot` for the schedule `name` and enqueues its run, in one transaction. False when the schedule already has
36
+ * this period or a later one (another worker took it). Throws on a name that is not a schedule.
37
+ */
38
+ export async function enqueueScheduledRun(ctx, name, slot) {
39
+ const schedule = getSchedule(getJobsOptions(ctx.config), name);
40
+ const now = ctx.clock.now();
41
+ return ctx.db.transaction(async (tx) => {
42
+ const [taken] = await tx
43
+ .insert(schedules)
44
+ .values({ name, lastSlotAt: slot, createdAt: now, updatedAt: now })
45
+ .onConflictDoUpdate({
46
+ target: schedules.name,
47
+ set: { lastSlotAt: slot, updatedAt: now },
48
+ setWhere: lt(schedules.lastSlotAt, slot),
49
+ })
50
+ .returning({ name: schedules.name });
51
+ if (taken === undefined)
52
+ return false;
53
+ await enqueueJob({ ...ctx, db: tx }, { queue: name, payload: schedule.payload, dedupKey: SCHEDULE_DEDUP_KEY });
54
+ return true;
55
+ });
56
+ }
57
+ /** Notes a succeeded job of a scheduled queue (any job of it, a run enqueued by hand too). */
58
+ export async function recordScheduleSuccess(ctx, queue) {
59
+ if (!Object.hasOwn(getJobsOptions(ctx.config).schedules, queue))
60
+ return;
61
+ const now = ctx.clock.now();
62
+ await ctx.db.update(schedules).set({ lastSucceededAt: now, updatedAt: now }).where(eq(schedules.name, queue));
63
+ }
64
+ /** The state of every configured schedule, by queue name. */
65
+ export async function getScheduleStates(ctx) {
66
+ const options = getJobsOptions(ctx.config);
67
+ const names = Object.keys(options.schedules);
68
+ if (names.length === 0)
69
+ return new Map();
70
+ const rows = await ctx.db.select().from(schedules).where(inArray(schedules.name, names));
71
+ const now = ctx.clock.now().getTime();
72
+ return new Map(names.map((name) => {
73
+ const everySeconds = getEverySeconds(getSchedule(options, name));
74
+ const row = rows.find((candidate) => candidate.name === name);
75
+ const since = row?.lastSucceededAt ?? row?.createdAt ?? null;
76
+ const isLate = since === null || now - since.getTime() > 2 * everySeconds * 1000;
77
+ return [name, { everySeconds, lastEnqueuedAt: row?.lastSlotAt ?? null, lastSucceededAt: row?.lastSucceededAt ?? null, isLate }];
78
+ }));
79
+ }
80
+ /** The schedules among `queues` (default all), in configuration order. */
81
+ export function getScheduleNames(options, queues) {
82
+ return Object.keys(options.schedules).filter((name) => queues === undefined || queues.includes(name));
83
+ }
84
+ export function getSchedule(options, name) {
85
+ const schedule = Object.hasOwn(options.schedules, name) ? options.schedules[name] : undefined;
86
+ if (schedule === undefined)
87
+ throw new Error(`@softure-ai/jobs: "${name}" is not a configured schedule`);
88
+ return schedule;
89
+ }
90
+ function getEverySeconds(schedule) {
91
+ const seconds = parseEverySeconds(schedule.every);
92
+ // The options schema refused any other value at startup.
93
+ if (seconds === null)
94
+ throw new Error(`@softure-ai/jobs: invalid schedule period "${schedule.every}"`);
95
+ return seconds;
96
+ }
97
+ //# sourceMappingURL=schedules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedules.js","sourceRoot":"","sources":["../../src/server/schedules.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"run-job-worker.d.ts","sourceRoot":"","sources":["../../src/worker/run-job-worker.ts"],"names":[],"mappings":"AAIA,OAAO,EAAe,KAAK,KAAK,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC/E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAIlD,OAAO,EAAqB,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AASzE,MAAM,WAAW,mBAAmB;IAClC,oHAAoH;IACpH,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,gGAAgG;IAChG,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,wEAAwE;IACxE,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB,yDAAyD;IACzD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,6CAA6C;IAC7C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;IAC/B,kGAAkG;IAClG,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAQD;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4E9E"}
1
+ {"version":3,"file":"run-job-worker.d.ts","sourceRoot":"","sources":["../../src/worker/run-job-worker.ts"],"names":[],"mappings":"AAIA,OAAO,EAAe,KAAK,KAAK,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC/E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAIlD,OAAO,EAAqB,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAUzE,MAAM,WAAW,mBAAmB;IAClC,oHAAoH;IACpH,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,gGAAgG;IAChG,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,wEAAwE;IACxE,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB,yDAAyD;IACzD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,6CAA6C;IAC7C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;IAC/B,kGAAkG;IAClG,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAQD;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0F9E"}
@@ -1,6 +1,6 @@
1
- // The worker loop: claims due jobs of every queue it has a handler for, up to each queue's concurrency, runs them,
2
- // keeps their leases alive, prunes old jobs once an hour, and on abort stops claiming, waits the grace period and
3
- // releases what is still running.
1
+ // The worker loop: enqueues the due runs of the schedules among its queues, claims due jobs of every queue it has a
2
+ // handler for, up to each queue's concurrency, runs them, keeps their leases alive, prunes old jobs once an hour, and
3
+ // on abort stops claiming, waits the grace period and releases what is still running.
4
4
  import { hostname } from "node:os";
5
5
  import { systemClock } from "@softure-ai/core";
6
6
  import { claimJobs, extendJobLease, releaseJob } from "../server/claim.js";
@@ -9,6 +9,7 @@ import { consoleJobsLogger } from "../server/logger.js";
9
9
  import { pruneJobs } from "../server/maintenance.js";
10
10
  import { getJobsOptions, getQueue } from "../server/options.js";
11
11
  import { runClaimedJob } from "../server/process.js";
12
+ import { enqueueScheduledRun, getSchedule, getScheduleNames, getScheduleSlot } from "../server/schedules.js";
12
13
  const PRUNE_INTERVAL_MS = 60 * 60 * 1000;
13
14
  /** A lease is extended three times per lease period, so one slow write does not lose it. */
14
15
  const HEARTBEATS_PER_LEASE = 3;
@@ -30,6 +31,9 @@ export async function runJobWorker(options) {
30
31
  const running = new Map(queues.map((queue) => [queue, new Set()]));
31
32
  const wakeUp = createWakeUp();
32
33
  let lastPruneAt = Number.NEGATIVE_INFINITY;
34
+ // Per schedule, the latest period this worker already settled (enqueued, or found taken), so it writes once per period.
35
+ const settledSlots = new Map();
36
+ const scheduleNames = getScheduleNames(jobsOptions, queues);
33
37
  const idle = Object.keys(jobsOptions.queues).filter((queue) => !queues.includes(queue));
34
38
  if (idle.length > 0 && options.queues === undefined) {
35
39
  logger.warn("configured queues without a handler are not run by this worker", { queues: idle.join(", ") });
@@ -60,6 +64,20 @@ export async function runJobWorker(options) {
60
64
  return entry;
61
65
  };
62
66
  while (!options.signal.aborted) {
67
+ for (const name of scheduleNames) {
68
+ const slot = getScheduleSlot(getSchedule(jobsOptions, name), ctx.clock.now());
69
+ if ((settledSlots.get(name) ?? Number.NEGATIVE_INFINITY) >= slot.getTime())
70
+ continue;
71
+ try {
72
+ const isEnqueued = await enqueueScheduledRun(ctx, name, slot);
73
+ settledSlots.set(name, slot.getTime());
74
+ if (isEnqueued)
75
+ logger.info("scheduled run enqueued", { queue: name, slot: slot.toISOString() });
76
+ }
77
+ catch (error) {
78
+ logger.error("could not enqueue a scheduled run; trying again next round", { queue: name, error });
79
+ }
80
+ }
63
81
  for (const queue of queues) {
64
82
  const slots = running.get(queue) ?? new Set();
65
83
  const free = getQueue(jobsOptions, queue).concurrency - slots.size;
@@ -1 +1 @@
1
- {"version":3,"file":"run-job-worker.js","sourceRoot":"","sources":["../../src/worker/run-job-worker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run-job-worker.js","sourceRoot":"","sources":["../../src/worker/run-job-worker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ -- Recurring schedules: per schedule the last period a worker enqueued a run for, and when a run last succeeded.
2
+ -- Rollback: DROP TABLE jobs.schedules; then
3
+ -- DELETE FROM softure.migrations WHERE module = 'jobs' AND version = 2;
4
+ CREATE TABLE schedules (
5
+ -- The schedule's queue.
6
+ name text PRIMARY KEY CHECK (name ~ '^[a-z][a-z0-9_.-]{0,62}$'),
7
+ -- The start of the latest period a run was enqueued for; a worker takes a period only when it is later than this.
8
+ last_slot_at timestamptz NOT NULL,
9
+ last_succeeded_at timestamptz,
10
+ created_at timestamptz NOT NULL,
11
+ updated_at timestamptz NOT NULL
12
+ );
package/module.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "id": "jobs",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "dependsOn": {},
5
5
  "dbSchema": "jobs",
6
- "tables": ["jobs"],
6
+ "tables": ["jobs", "schedules"],
7
7
  "env": [],
8
8
  "switches": [],
9
9
  "routes": {},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softure-ai/jobs",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "SOFTURE AI jobs module: background jobs in Postgres. Enqueue inside the caller's transaction with an optional dedup key, claim with FOR UPDATE SKIP LOCKED under a lease, fenced completion, retry with exponential backoff and a terminal failed state, a worker process with graceful shutdown, and an in-process runner for tests.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/index.ts CHANGED
@@ -15,10 +15,10 @@ export const MODULE_ID = "jobs";
15
15
  export const jobs = defineModule({
16
16
  manifest: {
17
17
  id: MODULE_ID,
18
- version: "0.1.0",
18
+ version: "0.1.1",
19
19
  dependsOn: {},
20
20
  dbSchema: "jobs",
21
- tables: ["jobs"],
21
+ tables: ["jobs", "schedules"],
22
22
  env: [],
23
23
  switches: [],
24
24
  routes: {},
@@ -40,6 +40,13 @@ export {
40
40
  type JobStatus,
41
41
  } from "./contract.js";
42
42
  export { jobsMessages, type JobsMessages } from "./messages/index.js";
43
- export { jobsOptionsSchema, type JobQueueOptions, type JobsOptions, type JobsOptionsInput } from "./options.js";
43
+ export {
44
+ jobsOptionsSchema,
45
+ type JobQueueOptions,
46
+ type JobScheduleOptions,
47
+ type JobSchedulesInput,
48
+ type JobsOptions,
49
+ type JobsOptionsInput,
50
+ } from "./options.js";
44
51
  export { defineJobHandler, failJob, retryJobLater, type JobHandler, type JobHandlerContext, type JobHandlers } from "./handlers.js";
45
- export { jobs as jobsTable } from "./schema.js";
52
+ export { jobs as jobsTable, schedules as jobSchedulesTable } from "./schema.js";