sidekiq-ts 1.0.2 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -85,18 +85,23 @@ Inside `perform`, you can access:
85
85
 
86
86
  ```typescript
87
87
  class MyJob extends Job<[string]> {
88
- perform(data: string) {
88
+ async perform(data: string) {
89
89
  // Unique job ID
90
90
  console.log(this.jid);
91
91
 
92
92
  // Check if worker is stopping (for graceful shutdown)
93
- if (this._context?.stopping()) {
93
+ if (this.interrupted()) {
94
94
  return; // Exit early
95
95
  }
96
+
97
+ // Get the AbortSignal for cancellation-aware APIs
98
+ const response = await fetch(url, { signal: this.signal });
96
99
  }
97
100
  }
98
101
  ```
99
102
 
103
+ The `signal` property returns an `AbortSignal` that is aborted when the worker is shutting down. Use it with `fetch()`, streams, database drivers, or any API that supports `AbortSignal` for graceful cancellation.
104
+
100
105
  ## Job Options
101
106
 
102
107
  Configure jobs using the static `sidekiqOptions` property:
@@ -260,9 +265,16 @@ import { Sidekiq } from "sidekiq-ts";
260
265
  import "./jobs/email-job.js";
261
266
  import "./jobs/report-job.js";
262
267
 
268
+ // Start worker with automatic signal handling
269
+ const runner = await Sidekiq.run({ signals: true });
270
+ // SIGINT/SIGTERM will gracefully stop the worker
271
+ ```
272
+
273
+ The `signals: true` option registers handlers for `SIGINT`, `SIGTERM`, and `SIGTSTP` that gracefully shut down the worker. For custom signal handling:
274
+
275
+ ```typescript
263
276
  const runner = await Sidekiq.run();
264
277
 
265
- // Handle shutdown signals
266
278
  process.on("SIGTERM", async () => {
267
279
  await runner.stop();
268
280
  process.exit(0);
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Utilities for AbortController-based cancellation.
3
+ */
4
+ /**
5
+ * Sleep that can be interrupted by an AbortSignal.
6
+ * Resolves immediately if signal is already aborted or when aborted during sleep.
7
+ *
8
+ * @param ms - Time to sleep in milliseconds
9
+ * @param signal - Optional AbortSignal to allow early cancellation
10
+ */
11
+ export declare function sleepWithAbort(ms: number, signal: AbortSignal | undefined): Promise<void>;
12
+ //# sourceMappingURL=abort-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abort-utils.d.ts","sourceRoot":"","sources":["../src/abort-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,WAAW,GAAG,SAAS,GAC9B,OAAO,CAAC,IAAI,CAAC,CAqBf"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Utilities for AbortController-based cancellation.
3
+ */
4
+ /**
5
+ * Sleep that can be interrupted by an AbortSignal.
6
+ * Resolves immediately if signal is already aborted or when aborted during sleep.
7
+ *
8
+ * @param ms - Time to sleep in milliseconds
9
+ * @param signal - Optional AbortSignal to allow early cancellation
10
+ */
11
+ export async function sleepWithAbort(ms, signal) {
12
+ if (!signal || signal.aborted) {
13
+ if (signal?.aborted) {
14
+ return;
15
+ }
16
+ // No signal provided, fall back to regular sleep
17
+ await new Promise((resolve) => setTimeout(resolve, ms));
18
+ return;
19
+ }
20
+ await new Promise((resolve) => {
21
+ const timeout = setTimeout(() => {
22
+ signal.removeEventListener("abort", onAbort);
23
+ resolve();
24
+ }, ms);
25
+ const onAbort = () => {
26
+ clearTimeout(timeout);
27
+ signal.removeEventListener("abort", onAbort);
28
+ resolve();
29
+ };
30
+ signal.addEventListener("abort", onAbort, { once: true });
31
+ });
32
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"cli-helpers.d.ts","sourceRoot":"","sources":["../src/cli-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,eAAO,MAAM,mBAAmB,iBAAiB,CAAC;AAElD,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;CACtB;AAWD,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,EAAE,KAAG,UAiH1C,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,SAAS,MAAM,KAAG,MAAM,GAAG,SAKvC,CAAC;AASxB,eAAO,MAAM,eAAe,GAC1B,QAAQ,MAAM,EACd,SAAS,UAAU,EACnB,qBAAoB,MAAM,EAAO,KAChC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAuB1C,CAAC;AAEF,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,cAAc,EAAE,MAAM,OAAO,CAAC;CAC/B;AAED,eAAO,MAAM,qBAAqB,GAAI,MAAM,YAAY,KAAG,eAkB1D,CAAC"}
1
+ {"version":3,"file":"cli-helpers.d.ts","sourceRoot":"","sources":["../src/cli-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,eAAO,MAAM,mBAAmB,iBAAiB,CAAC;AAElD,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;CACtB;AAWD,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,EAAE,KAAG,UAiH1C,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,SAAS,MAAM,KAAG,MAAM,GAAG,SAKvC,CAAC;AASxB,eAAO,MAAM,eAAe,GAC1B,QAAQ,MAAM,EACd,SAAS,UAAU,EACnB,qBAAoB,MAAM,EAAO,KAChC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAuB1C,CAAC;AAEF,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,cAAc,EAAE,MAAM,OAAO,CAAC;CAC/B;AAED,eAAO,MAAM,qBAAqB,GAAI,MAAM,YAAY,KAAG,eA0B1D,CAAC"}
@@ -152,13 +152,21 @@ export const applyCliOptions = (config, options, loadedRequirePaths = []) => {
152
152
  };
153
153
  export const createShutdownHandler = (deps) => {
154
154
  let shuttingDown = false;
155
+ let shutdownStartedAt = 0;
155
156
  const handler = async (signal) => {
156
157
  if (shuttingDown) {
158
+ // Only force exit if more than 500ms has passed since first signal.
159
+ // This prevents duplicate signals from a single Ctrl+C from force-exiting.
160
+ const elapsed = Date.now() - shutdownStartedAt;
161
+ if (elapsed < 500) {
162
+ return;
163
+ }
157
164
  deps.logger.info(() => `Received ${signal}, forcing exit`);
158
165
  deps.exit(1);
159
166
  return;
160
167
  }
161
168
  shuttingDown = true;
169
+ shutdownStartedAt = Date.now();
162
170
  deps.logger.info(() => `Received ${signal}, shutting down`);
163
171
  await deps.stop();
164
172
  deps.exit(0);
package/dist/client.d.ts CHANGED
@@ -20,6 +20,18 @@ export declare class Client {
20
20
  static enqueueToIn<TArgs extends unknown[]>(queue: string, interval: number, klass: JobClassLike, ...args: TArgs): Promise<string | null>;
21
21
  static enqueueIn<TArgs extends unknown[]>(interval: number, klass: JobClassLike, ...args: TArgs): Promise<string | null>;
22
22
  static via<T>(redis: RedisClient, fn: () => Promise<T>): Promise<T>;
23
+ /**
24
+ * Returns the number of jobs currently in the local queue.
25
+ * Jobs are queued locally when Redis is unavailable.
26
+ */
27
+ static localQueueSize(): number;
28
+ /**
29
+ * Clears the local queue. Primarily for testing.
30
+ */
31
+ static clearLocalQueue(): void;
23
32
  private rawPush;
33
+ private pushToRedis;
34
+ private drainLocalQueue;
35
+ private queueLocally;
24
36
  }
25
37
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAS1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAIxE,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAc;gBAE/B,EACV,MAAM,EACN,KAAK,GACN,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,WAAW,CAAA;KAAO;YAKlC,QAAQ;IAQtB,UAAU,CACR,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,kBAAkB,CAAC,KAAK,IAAI,GAC/C,MAAM,CAAC,kBAAkB,CAAC;IAOvB,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAqB9C,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IA0GxD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAc3C,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIrD,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAI/D,MAAM,CAAC,OAAO,CAAC,KAAK,SAAS,OAAO,EAAE,EACpC,KAAK,EAAE,YAAY,EACnB,GAAG,IAAI,EAAE,KAAK,GACb,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIzB,MAAM,CAAC,SAAS,CAAC,KAAK,SAAS,OAAO,EAAE,EACtC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,YAAY,EACnB,GAAG,IAAI,EAAE,KAAK,GACb,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIzB,MAAM,CAAC,WAAW,CAAC,KAAK,SAAS,OAAO,EAAE,EACxC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,YAAY,EACnB,GAAG,IAAI,EAAE,KAAK,GACb,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAUzB,MAAM,CAAC,SAAS,CAAC,KAAK,SAAS,OAAO,EAAE,EACtC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,YAAY,EACnB,GAAG,IAAI,EAAE,KAAK,GACb,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAQzB,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;YAKrD,OAAO;CAoDtB"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAS1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAOxE,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAc;gBAE/B,EACV,MAAM,EACN,KAAK,GACN,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,WAAW,CAAA;KAAO;YAKlC,QAAQ;IAQtB,UAAU,CACR,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,kBAAkB,CAAC,KAAK,IAAI,GAC/C,MAAM,CAAC,kBAAkB,CAAC;IAOvB,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA6B9C,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAkIxD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAc3C,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIrD,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAI/D,MAAM,CAAC,OAAO,CAAC,KAAK,SAAS,OAAO,EAAE,EACpC,KAAK,EAAE,YAAY,EACnB,GAAG,IAAI,EAAE,KAAK,GACb,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIzB,MAAM,CAAC,SAAS,CAAC,KAAK,SAAS,OAAO,EAAE,EACtC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,YAAY,EACnB,GAAG,IAAI,EAAE,KAAK,GACb,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIzB,MAAM,CAAC,WAAW,CAAC,KAAK,SAAS,OAAO,EAAE,EACxC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,YAAY,EACnB,GAAG,IAAI,EAAE,KAAK,GACb,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAUzB,MAAM,CAAC,SAAS,CAAC,KAAK,SAAS,OAAO,EAAE,EACtC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,YAAY,EACnB,GAAG,IAAI,EAAE,KAAK,GACb,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAQzB,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAInE;;;OAGG;IACH,MAAM,CAAC,cAAc,IAAI,MAAM;IAI/B;;OAEG;IACH,MAAM,CAAC,eAAe,IAAI,IAAI;YAIhB,OAAO;YAgCP,WAAW;YAuCX,eAAe;IAgC7B,OAAO,CAAC,YAAY;CAgCrB"}
package/dist/client.js CHANGED
@@ -5,6 +5,8 @@ import { dumpJson } from "./json.js";
5
5
  import { Sidekiq } from "./sidekiq.js";
6
6
  import { Testing } from "./testing.js";
7
7
  const redisContext = new AsyncLocalStorage();
8
+ // Local queue for reliable push - holds jobs when Redis is unavailable
9
+ const localQueue = [];
8
10
  export class Client {
9
11
  config;
10
12
  redisClient;
@@ -26,15 +28,23 @@ export class Client {
26
28
  async push(item) {
27
29
  const normalized = normalizeItem(item, Sidekiq.defaultJobOptions());
28
30
  const queue = normalized.queue ?? "default";
29
- const redis = await this.getRedis();
30
- const result = await this.config.clientMiddleware.invoke(item.class, normalized, queue, redis, async () => normalized);
31
- if (!result) {
32
- return null;
31
+ try {
32
+ const redis = await this.getRedis();
33
+ const result = await this.config.clientMiddleware.invoke(item.class, normalized, queue, redis, async () => normalized);
34
+ if (!result) {
35
+ return null;
36
+ }
37
+ const payload = result;
38
+ verifyJson(payload.args, this.config.strictArgs);
39
+ await this.rawPush([payload]);
40
+ return payload.jid ?? null;
41
+ }
42
+ catch (error) {
43
+ // Redis unavailable - queue locally (skipping middleware)
44
+ verifyJson(normalized.args, this.config.strictArgs);
45
+ this.queueLocally([normalized], error);
46
+ return normalized.jid ?? null;
33
47
  }
34
- const payload = result;
35
- verifyJson(payload.args, this.config.strictArgs);
36
- await this.rawPush([payload]);
37
- return payload.jid ?? null;
38
48
  }
39
49
  // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: bulk push validation is inherently complex
40
50
  async pushBulk(items) {
@@ -82,37 +92,59 @@ export class Client {
82
92
  base.jid = undefined;
83
93
  const normalized = normalizeItem(base, Sidekiq.defaultJobOptions());
84
94
  const results = [];
85
- const redis = await this.getRedis();
86
- for (let i = 0; i < args.length; i += batchSize) {
87
- const slice = args.slice(i, i + batchSize);
88
- if (slice.length === 0) {
89
- break;
90
- }
91
- if (!slice.every((entry) => Array.isArray(entry))) {
92
- throw new Error("Bulk arguments must be an Array of Arrays: [[1], [2]]");
95
+ try {
96
+ const redis = await this.getRedis();
97
+ for (let i = 0; i < args.length; i += batchSize) {
98
+ const slice = args.slice(i, i + batchSize);
99
+ if (slice.length === 0) {
100
+ break;
101
+ }
102
+ if (!slice.every((entry) => Array.isArray(entry))) {
103
+ throw new Error("Bulk arguments must be an Array of Arrays: [[1], [2]]");
104
+ }
105
+ const payloads = await Promise.all(slice.map(async (jobArgs, index) => {
106
+ const payload = {
107
+ ...normalized,
108
+ args: jobArgs,
109
+ jid: generateJid(),
110
+ };
111
+ if (resolvedAt !== undefined) {
112
+ payload.at = Array.isArray(resolvedAt)
113
+ ? resolvedAt[i + index]
114
+ : resolvedAt;
115
+ }
116
+ const result = await this.config.clientMiddleware.invoke(items.class, payload, payload.queue ?? "default", redis, async () => payload);
117
+ if (!result) {
118
+ return null;
119
+ }
120
+ const finalPayload = result;
121
+ verifyJson(finalPayload.args, this.config.strictArgs);
122
+ return finalPayload;
123
+ }));
124
+ const toPush = payloads.filter((payload) => Boolean(payload));
125
+ await this.rawPush(toPush);
126
+ results.push(...payloads.map((payload) => payload?.jid ?? null));
93
127
  }
94
- const payloads = await Promise.all(slice.map(async (jobArgs, index) => {
128
+ }
129
+ catch (error) {
130
+ // Redis unavailable - build payloads without middleware and queue locally
131
+ for (let i = results.length; i < args.length; i++) {
132
+ const jobArgs = args[i];
133
+ if (!Array.isArray(jobArgs)) {
134
+ throw new Error("Bulk arguments must be an Array of Arrays: [[1], [2]]");
135
+ }
95
136
  const payload = {
96
137
  ...normalized,
97
138
  args: jobArgs,
98
139
  jid: generateJid(),
99
140
  };
100
141
  if (resolvedAt !== undefined) {
101
- payload.at = Array.isArray(resolvedAt)
102
- ? resolvedAt[i + index]
103
- : resolvedAt;
104
- }
105
- const result = await this.config.clientMiddleware.invoke(items.class, payload, payload.queue ?? "default", redis, async () => payload);
106
- if (!result) {
107
- return null;
142
+ payload.at = Array.isArray(resolvedAt) ? resolvedAt[i] : resolvedAt;
108
143
  }
109
- const finalPayload = result;
110
- verifyJson(finalPayload.args, this.config.strictArgs);
111
- return finalPayload;
112
- }));
113
- const toPush = payloads.filter((payload) => Boolean(payload));
114
- await this.rawPush(toPush);
115
- results.push(...payloads.map((payload) => payload?.jid ?? null));
144
+ verifyJson(payload.args, this.config.strictArgs);
145
+ this.queueLocally([payload], error);
146
+ results.push(payload.jid ?? null);
147
+ }
116
148
  }
117
149
  return results;
118
150
  }
@@ -123,7 +155,7 @@ export class Client {
123
155
  const pipeline = redis.multi();
124
156
  pipeline.hSetNX(key, "cancelled", now);
125
157
  pipeline.hGet(key, "cancelled");
126
- pipeline.expire(key, ITERATION_STATE_TTL_SECONDS, "NX");
158
+ pipeline.expire(key, ITERATION_STATE_TTL_SECONDS);
127
159
  const result = await pipeline.exec();
128
160
  const cancelled = result?.[1];
129
161
  return Boolean(Number(cancelled));
@@ -159,7 +191,19 @@ export class Client {
159
191
  static via(redis, fn) {
160
192
  return redisContext.run(redis, fn);
161
193
  }
162
- // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: push logic requires handling multiple cases
194
+ /**
195
+ * Returns the number of jobs currently in the local queue.
196
+ * Jobs are queued locally when Redis is unavailable.
197
+ */
198
+ static localQueueSize() {
199
+ return localQueue.length;
200
+ }
201
+ /**
202
+ * Clears the local queue. Primarily for testing.
203
+ */
204
+ static clearLocalQueue() {
205
+ localQueue.length = 0;
206
+ }
163
207
  async rawPush(payloads) {
164
208
  if (payloads.length === 0) {
165
209
  return;
@@ -177,7 +221,19 @@ export class Client {
177
221
  }
178
222
  return;
179
223
  }
180
- const redis = await this.getRedis();
224
+ try {
225
+ const redis = await this.getRedis();
226
+ // Drain any locally queued jobs first
227
+ await this.drainLocalQueue(redis);
228
+ // Push the current batch
229
+ await this.pushToRedis(redis, payloads);
230
+ }
231
+ catch (error) {
232
+ // Queue locally on Redis failure (silent success)
233
+ this.queueLocally(payloads, error);
234
+ }
235
+ }
236
+ async pushToRedis(redis, payloads) {
181
237
  const pipeline = redis.multi();
182
238
  if (payloads[0].at !== undefined) {
183
239
  for (const payload of payloads) {
@@ -209,4 +265,52 @@ export class Client {
209
265
  }
210
266
  await pipeline.exec();
211
267
  }
268
+ async drainLocalQueue(redis) {
269
+ if (localQueue.length === 0) {
270
+ return;
271
+ }
272
+ const drainCount = localQueue.length;
273
+ this.config.logger.info(() => `Draining ${drainCount} locally queued jobs to Redis`);
274
+ // Process in batches to avoid huge pipelines
275
+ while (localQueue.length > 0) {
276
+ const batch = localQueue.splice(0, 100);
277
+ try {
278
+ // Separate scheduled and immediate jobs
279
+ const scheduled = batch.filter((p) => p.at !== undefined);
280
+ const immediate = batch.filter((p) => p.at === undefined);
281
+ if (scheduled.length > 0) {
282
+ await this.pushToRedis(redis, scheduled);
283
+ }
284
+ if (immediate.length > 0) {
285
+ await this.pushToRedis(redis, immediate);
286
+ }
287
+ }
288
+ catch {
289
+ // Put back and abort drain - Redis still unavailable
290
+ localQueue.unshift(...batch);
291
+ throw new Error("Failed to drain local queue");
292
+ }
293
+ }
294
+ }
295
+ queueLocally(payloads, error) {
296
+ const maxQueue = this.config.reliableClientMaxQueue;
297
+ if (maxQueue === 0) {
298
+ // Reliability disabled - re-throw
299
+ throw error;
300
+ }
301
+ const available = maxQueue - localQueue.length;
302
+ if (available <= 0) {
303
+ this.config.logger.warn(() => `Local queue full (${maxQueue} jobs), dropping ${payloads.length} jobs`);
304
+ return;
305
+ }
306
+ const toQueue = payloads.slice(0, available);
307
+ localQueue.push(...toQueue);
308
+ const dropped = payloads.length - toQueue.length;
309
+ if (dropped > 0) {
310
+ this.config.logger.warn(() => `Queued ${toQueue.length} jobs locally, dropped ${dropped} (queue full at ${maxQueue})`);
311
+ }
312
+ else {
313
+ this.config.logger.warn(() => `Redis unavailable, queued ${toQueue.length} jobs locally (${localQueue.length}/${maxQueue})`);
314
+ }
315
+ }
212
316
  }
package/dist/config.d.ts CHANGED
@@ -36,6 +36,7 @@ export declare class Config {
36
36
  ], JobPayload | false | null | undefined>;
37
37
  serverMiddleware: MiddlewareChain<[unknown, JobPayload, string], unknown>;
38
38
  leaderElection: LeaderElectionConfig;
39
+ reliableClientMaxQueue: number;
39
40
  private redisClient?;
40
41
  constructor(options?: ConfigOptions);
41
42
  getRedisClient(): Promise<RedisClient>;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAIhD,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,UAAU,EACV,oBAAoB,EACpB,eAAe,EACf,cAAc,EACf,MAAM,YAAY,CAAC;AAapB,qBAAa,MAAM;IACjB,KAAK,EAAE,kBAAkB,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,4BAA4B,EAAE,MAAM,CAAC;IACrC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,gBAAgB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC;IACpD,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,UAAU,EAAE,cAAc,CAAC;IAC3B,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,eAAe,EAAE,eAAe,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,SAAS,EAAE,SAAS,CAAC;IACrB,gBAAgB,EAAE,eAAe,CAC/B;QAAC,MAAM,GAAG,OAAO;QAAE,UAAU;QAAE,MAAM;QAAE,WAAW;KAAC,EACnD,UAAU,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,CACtC,CAAC;IACF,gBAAgB,EAAE,eAAe,CAAC,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;IAC1E,cAAc,EAAE,oBAAoB,CAAC;IACrC,OAAO,CAAC,WAAW,CAAC,CAAc;gBAGtB,OAAO,GAAE,aAAkB;IAgDjC,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC;IAatC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B,UAAU,IAAI,MAAM,EAAE;IAatB;;;;;;;;OAQG;IACG,SAAS,CACb,KAAK,EAAE,MAAM,eAAe,EAC5B,OAAO,GAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAO,GACxE,OAAO,CAAC,IAAI,CAAC;CA+BjB"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAIhD,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,UAAU,EACV,oBAAoB,EACpB,eAAe,EACf,cAAc,EACf,MAAM,YAAY,CAAC;AAapB,qBAAa,MAAM;IACjB,KAAK,EAAE,kBAAkB,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,4BAA4B,EAAE,MAAM,CAAC;IACrC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,gBAAgB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC;IACpD,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,UAAU,EAAE,cAAc,CAAC;IAC3B,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,eAAe,EAAE,eAAe,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,SAAS,EAAE,SAAS,CAAC;IACrB,gBAAgB,EAAE,eAAe,CAC/B;QAAC,MAAM,GAAG,OAAO;QAAE,UAAU;QAAE,MAAM;QAAE,WAAW;KAAC,EACnD,UAAU,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,CACtC,CAAC;IACF,gBAAgB,EAAE,eAAe,CAAC,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;IAC1E,cAAc,EAAE,oBAAoB,CAAC;IACrC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,OAAO,CAAC,WAAW,CAAC,CAAc;gBAGtB,OAAO,GAAE,aAAkB;IAiDjC,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC;IAatC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B,UAAU,IAAI,MAAM,EAAE;IAatB;;;;;;;;OAQG;IACG,SAAS,CACb,KAAK,EAAE,MAAM,eAAe,EAC5B,OAAO,GAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAO,GACxE,OAAO,CAAC,IAAI,CAAC;CA2BjB"}
package/dist/config.js CHANGED
@@ -41,6 +41,7 @@ export class Config {
41
41
  clientMiddleware;
42
42
  serverMiddleware;
43
43
  leaderElection;
44
+ reliableClientMaxQueue;
44
45
  redisClient;
45
46
  // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: config initialization requires many defaults
46
47
  constructor(options = {}) {
@@ -79,6 +80,7 @@ export class Config {
79
80
  this.clientMiddleware = new MiddlewareChain(this);
80
81
  this.serverMiddleware = new MiddlewareChain(this);
81
82
  this.leaderElection = options.leaderElection ?? {};
83
+ this.reliableClientMaxQueue = options.reliableClientMaxQueue ?? 1000;
82
84
  if (this.errorHandlers.length === 0) {
83
85
  this.errorHandlers.push((error, context) => {
84
86
  Context.with(context, () => {
@@ -129,9 +131,6 @@ export class Config {
129
131
  */
130
132
  async fireEvent(event, options = {}) {
131
133
  const { oneshot = true, reverse = false, reraise = false } = options;
132
- if (oneshot) {
133
- this.logger.debug(() => `Firing ${event} event`);
134
- }
135
134
  const handlers = [...this.lifecycleEvents[event]];
136
135
  if (reverse) {
137
136
  handlers.reverse();
package/dist/iterable.js CHANGED
@@ -42,7 +42,7 @@ export class IterableJob extends Job {
42
42
  const pipeline = redis.multi();
43
43
  pipeline.hSetNX(key, "cancelled", String(now));
44
44
  pipeline.hGet(key, "cancelled");
45
- pipeline.expire(key, ITERATION_STATE_TTL_SECONDS, "NX");
45
+ pipeline.expire(key, ITERATION_STATE_TTL_SECONDS);
46
46
  const result = await pipeline.exec();
47
47
  const cancelled = result?.[1] ?? null;
48
48
  this.cancelledValue = cancelled ? Number(cancelled) : null;
@@ -269,7 +269,7 @@ export class IterableJob extends Job {
269
269
  };
270
270
  const pipeline = redis.multi();
271
271
  pipeline.hSet(key, state);
272
- pipeline.expire(key, ITERATION_STATE_TTL_SECONDS, "NX");
272
+ pipeline.expire(key, ITERATION_STATE_TTL_SECONDS);
273
273
  pipeline.hGet(key, "cancelled");
274
274
  const result = await pipeline.exec();
275
275
  const cancelled = result?.[2] ?? null;
package/dist/job.d.ts CHANGED
@@ -31,6 +31,7 @@ export declare abstract class Job<TArgs extends unknown[] = unknown[]> {
31
31
  jid?: string;
32
32
  _context?: {
33
33
  stopping: () => boolean;
34
+ signal?: AbortSignal;
34
35
  };
35
36
  static getSidekiqOptions(this: JobConstructor): JobOptions;
36
37
  static setSidekiqOptions(this: JobConstructor, options: JobOptions): void;
@@ -53,6 +54,12 @@ export declare abstract class Job<TArgs extends unknown[] = unknown[]> {
53
54
  static clientPush(this: JobConstructor, item: JobPayload): Promise<string | null>;
54
55
  logger(): import("./logger.js").Logger;
55
56
  interrupted(): boolean;
57
+ /**
58
+ * Get the AbortSignal for this job.
59
+ * Can be used with fetch(), streams, or any AbortSignal-compatible API.
60
+ * The signal is aborted when the runner is shutting down.
61
+ */
62
+ get signal(): AbortSignal | undefined;
56
63
  abstract perform(...args: TArgs): Promise<void> | void;
57
64
  }
58
65
  export type RetryInHandler = (count: number, error: Error, payload: JobPayload) => number | "discard" | "kill" | "default";
package/dist/job.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"job.d.ts","sourceRoot":"","sources":["../src/job.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"job.d.ts","sourceRoot":"","sources":["../src/job.ts"],"names":[],"mappings":"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"}
package/dist/job.js CHANGED
@@ -112,6 +112,14 @@ export class Job {
112
112
  interrupted() {
113
113
  return this._context?.stopping() ?? false;
114
114
  }
115
+ /**
116
+ * Get the AbortSignal for this job.
117
+ * Can be used with fetch(), streams, or any AbortSignal-compatible API.
118
+ * The signal is aborted when the runner is shutting down.
119
+ */
120
+ get signal() {
121
+ return this._context?.signal;
122
+ }
115
123
  }
116
124
  export class JobSetter {
117
125
  klass;
package/dist/leader.d.ts CHANGED
@@ -58,6 +58,5 @@ export declare class LeaderElector {
58
58
  * Background loop for leader election.
59
59
  */
60
60
  private leaderLoop;
61
- private sleepWithAbort;
62
61
  }
63
62
  //# sourceMappingURL=leader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"leader.d.ts","sourceRoot":"","sources":["../src/leader.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAe1C,MAAM,WAAW,oBAAoB;IACnC,+DAA+D;IAC/D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8CAA8C;IAC9C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAE7B,OAAO,CAAC,KAAK,CAAC,CAAc;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAC,CAAgB;IACpC,OAAO,CAAC,cAAc,CAAC,CAAkB;gBAE7B,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB;IAS9D;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA4B3B;;OAEG;IACH,MAAM,IAAI,OAAO;IAIjB;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAK7C;;OAEG;YACW,UAAU;IA4BxB;;OAEG;YACW,UAAU;IAmBxB;;OAEG;YACW,UAAU;YAkCV,cAAc;CAkB7B"}
1
+ {"version":3,"file":"leader.d.ts","sourceRoot":"","sources":["../src/leader.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAe1C,MAAM,WAAW,oBAAoB;IACnC,+DAA+D;IAC/D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8CAA8C;IAC9C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAE7B,OAAO,CAAC,KAAK,CAAC,CAAc;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAC,CAAgB;IACpC,OAAO,CAAC,cAAc,CAAC,CAAkB;gBAE7B,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB;IAS9D;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA4B3B;;OAEG;IACH,MAAM,IAAI,OAAO;IAIjB;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAK7C;;OAEG;YACW,UAAU;IA4BxB;;OAEG;YACW,UAAU;IAmBxB;;OAEG;YACW,UAAU;CAiCzB"}
package/dist/leader.js CHANGED
@@ -8,6 +8,7 @@
8
8
  * - 20 second TTL on leader key for automatic failover
9
9
  */
10
10
  import { hostname } from "node:os";
11
+ import { sleepWithAbort } from "./abort-utils.js";
11
12
  const LEADER_KEY = "leader";
12
13
  const LEADER_TTL_SECONDS = 20;
13
14
  const LEADER_REFRESH_INTERVAL_MS = 15_000;
@@ -169,25 +170,7 @@ export class LeaderElector {
169
170
  const interval = this.isLeader
170
171
  ? this.refreshInterval
171
172
  : this.checkInterval;
172
- await this.sleepWithAbort(interval);
173
+ await sleepWithAbort(interval, this.stopController?.signal);
173
174
  }
174
175
  }
175
- async sleepWithAbort(ms) {
176
- const controller = this.stopController;
177
- if (!controller || controller.signal.aborted) {
178
- return;
179
- }
180
- await new Promise((resolve) => {
181
- const timeout = setTimeout(() => {
182
- controller.signal.removeEventListener("abort", onAbort);
183
- resolve();
184
- }, ms);
185
- const onAbort = () => {
186
- clearTimeout(timeout);
187
- controller.signal.removeEventListener("abort", onAbort);
188
- resolve();
189
- };
190
- controller.signal.addEventListener("abort", onAbort, { once: true });
191
- });
192
- }
193
176
  }
@@ -34,6 +34,7 @@ export declare class PeriodicScheduler {
34
34
  private redis?;
35
35
  private running;
36
36
  private loopPromise?;
37
+ private stopController?;
37
38
  constructor(config: Config, leaderElector: LeaderElector);
38
39
  /**
39
40
  * Register a periodic job.
@@ -1 +1 @@
1
- {"version":3,"file":"periodic.d.ts","sourceRoot":"","sources":["../src/periodic.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAQ7C,MAAM,WAAW,kBAAmB,SAAQ,UAAU;IACpD,oBAAoB;IACpB,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,8CAA8C;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,mBAAmB;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,oBAAoB;IACpB,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,6BAA6B;IAC7B,OAAO,EAAE,kBAAkB,CAAC;CAC7B;AAQD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyC;IAC9D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC,OAAO,CAAC,KAAK,CAAC,CAAc;IAC5B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAC,CAAgB;gBAExB,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa;IAMxD;;;;;;;OAOG;IACH,QAAQ,CACN,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,cAAc,EACxB,OAAO,GAAE,kBAAuB,GAC/B,MAAM;IA2BT;;OAEG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAQhC;;OAEG;IACH,IAAI,IAAI,iBAAiB,EAAE;IAI3B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAe5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB3B;;OAEG;IACH,OAAO,CAAC,WAAW;IAiBnB;;OAEG;YACW,WAAW;IAoBzB;;OAEG;YAEW,YAAY;IA2C1B;;OAEG;YACW,kBAAkB;CAmCjC"}
1
+ {"version":3,"file":"periodic.d.ts","sourceRoot":"","sources":["../src/periodic.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAM7C,MAAM,WAAW,kBAAmB,SAAQ,UAAU;IACpD,oBAAoB;IACpB,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,8CAA8C;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,mBAAmB;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,oBAAoB;IACpB,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,6BAA6B;IAC7B,OAAO,EAAE,kBAAkB,CAAC;CAC7B;AAQD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyC;IAC9D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC,OAAO,CAAC,KAAK,CAAC,CAAc;IAC5B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAC,CAAgB;IACpC,OAAO,CAAC,cAAc,CAAC,CAAkB;gBAE7B,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa;IAMxD;;;;;;;OAOG;IACH,QAAQ,CACN,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,cAAc,EACxB,OAAO,GAAE,kBAAuB,GAC/B,MAAM;IA2BT;;OAEG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAQhC;;OAEG;IACH,IAAI,IAAI,iBAAiB,EAAE;IAI3B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB3B;;OAEG;IACH,OAAO,CAAC,WAAW;IAiBnB;;OAEG;YACW,WAAW;IAoBzB;;OAEG;YAEW,YAAY;IA2C1B;;OAEG;YACW,kBAAkB;CAmCjC"}
package/dist/periodic.js CHANGED
@@ -4,13 +4,13 @@
4
4
  * Allows registering jobs that run on a cron schedule.
5
5
  * Only the leader process enqueues periodic jobs to prevent duplicates.
6
6
  */
7
+ import { sleepWithAbort } from "./abort-utils.js";
7
8
  import { Client } from "./client.js";
8
9
  import { parseCron, shouldRunAt } from "./cron.js";
9
10
  import { dumpJson } from "./json.js";
10
11
  const CRON_KEY = "cron";
11
12
  const CRON_LOCK_PREFIX = "cron:lock:";
12
13
  const CRON_LOCK_TTL_SECONDS = 60;
13
- const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
14
14
  export class PeriodicScheduler {
15
15
  config;
16
16
  leaderElector;
@@ -19,6 +19,7 @@ export class PeriodicScheduler {
19
19
  redis;
20
20
  running = false;
21
21
  loopPromise;
22
+ stopController;
22
23
  constructor(config, leaderElector) {
23
24
  this.config = config;
24
25
  this.leaderElector = leaderElector;
@@ -75,6 +76,7 @@ export class PeriodicScheduler {
75
76
  }
76
77
  this.redis = await this.config.getRedisClient();
77
78
  this.running = true;
79
+ this.stopController = new AbortController();
78
80
  // Persist job configs to Redis for visibility
79
81
  await this.syncToRedis();
80
82
  // Start the background loop
@@ -88,6 +90,7 @@ export class PeriodicScheduler {
88
90
  return;
89
91
  }
90
92
  this.running = false;
93
+ this.stopController?.abort();
91
94
  // Remove job configs from Redis
92
95
  if (this.redis && this.jobs.size > 0) {
93
96
  try {
@@ -141,14 +144,14 @@ export class PeriodicScheduler {
141
144
  // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: scheduler loop requires multiple conditional checks
142
145
  async periodicLoop() {
143
146
  // Wait for initial sync with jitter to avoid thundering herd
144
- await sleep(Math.random() * 5000);
147
+ await sleepWithAbort(Math.random() * 5000, this.stopController?.signal);
145
148
  while (this.running) {
146
149
  // Wait until the next minute boundary plus jitter
147
150
  const now = Date.now();
148
151
  const nextMinute = Math.ceil(now / 60_000) * 60_000;
149
152
  const jitter = Math.random() * 2000; // 0-2 seconds
150
153
  const waitMs = Math.max(0, nextMinute - now + jitter);
151
- await sleep(waitMs);
154
+ await sleepWithAbort(waitMs, this.stopController?.signal);
152
155
  if (!this.running) {
153
156
  break;
154
157
  }
package/dist/runner.d.ts CHANGED
@@ -14,9 +14,11 @@ export declare class Runner {
14
14
  private quieting;
15
15
  private stopping;
16
16
  private readonly workers;
17
- private schedulerHandle?;
18
17
  private schedulerRunning;
19
- private heartbeatHandle?;
18
+ private schedulerController?;
19
+ private heartbeatController?;
20
+ private heartbeatLoopPromise?;
21
+ private jobController?;
20
22
  private readonly queueStrategy;
21
23
  private baseRedis?;
22
24
  private readonly workerRedis;
@@ -63,6 +65,7 @@ export declare class Runner {
63
65
  private runWithProfiler;
64
66
  private cleanupProcesses;
65
67
  private startHeartbeat;
68
+ private heartbeatLoop;
66
69
  private stopHeartbeat;
67
70
  private enqueueScheduled;
68
71
  private workLoop;
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAU1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAsG7C,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,OAAO,CAAC,eAAe,CAAC,CAAiB;IACzC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,eAAe,CAAC,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,SAAS,CAAC,CAAgD;IAClE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAEnB;IACT,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAGtB;IACJ,OAAO,CAAC,QAAQ,CAAC,UAAU,CAGvB;IACJ,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAgB;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,OAAO,CAAC,aAAa,CAAC,CAAgB;IACtC,OAAO,CAAC,kBAAkB,CAAC,CAAoB;gBAEnC,MAAM,EAAE,MAAM;IAQpB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA8BtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAKtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAoD3B;;OAEG;IACH,MAAM,IAAI,OAAO;IAIjB;;OAEG;IACH,IAAI,iBAAiB,IAAI,iBAAiB,GAAG,SAAS,CAErD;IAED,YAAY,IAAI,YAAY,EAAE;IAsB9B,OAAO,CAAC,cAAc;YAKR,gBAAgB;YAWhB,WAAW;YAoBX,YAAY;IAM1B,OAAO,CAAC,kBAAkB;YAIZ,kBAAkB;IAqBhC,OAAO,CAAC,aAAa;YAQP,SAAS;YA0DT,YAAY;IAoB1B,OAAO,CAAC,aAAa;YAkBP,cAAc;IAa5B,OAAO,CAAC,WAAW;YAcL,QAAQ;IAWtB,OAAO,CAAC,SAAS;YAoBH,YAAY;YAMZ,cAAc;YAQd,iBAAiB;YAkBjB,eAAe;YAWf,eAAe;YAWf,gBAAgB;IA8B9B,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,aAAa;YAOP,gBAAgB;YA6BhB,QAAQ;YAiCR,SAAS;YA4BT,UAAU;YAwEV,aAAa;IA2H3B,OAAO,CAAC,WAAW;YAoBL,gBAAgB;YA8BhB,YAAY;YAYZ,gBAAgB;YAmBhB,gBAAgB;IAsB9B,OAAO,CAAC,iBAAiB;IAmBzB,OAAO,CAAC,gBAAgB;YAQV,UAAU;CAczB"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAU1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA8G7C,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,mBAAmB,CAAC,CAAkB;IAC9C,OAAO,CAAC,mBAAmB,CAAC,CAAkB;IAC9C,OAAO,CAAC,oBAAoB,CAAC,CAAgB;IAC7C,OAAO,CAAC,aAAa,CAAC,CAAkB;IACxC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,SAAS,CAAC,CAAgD;IAClE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAEnB;IACT,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAGtB;IACJ,OAAO,CAAC,QAAQ,CAAC,UAAU,CAGvB;IACJ,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAgB;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,OAAO,CAAC,aAAa,CAAC,CAAgB;IACtC,OAAO,CAAC,kBAAkB,CAAC,CAAoB;gBAEnC,MAAM,EAAE,MAAM;IAQpB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA+BtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAKtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA0D3B;;OAEG;IACH,MAAM,IAAI,OAAO;IAIjB;;OAEG;IACH,IAAI,iBAAiB,IAAI,iBAAiB,GAAG,SAAS,CAErD;IAED,YAAY,IAAI,YAAY,EAAE;IAsB9B,OAAO,CAAC,cAAc;YAMR,gBAAgB;YAWhB,WAAW;YAuBX,YAAY;IAM1B,OAAO,CAAC,kBAAkB;YAIZ,kBAAkB;IAqBhC,OAAO,CAAC,aAAa;YAKP,SAAS;YA0DT,YAAY;IAoB1B,OAAO,CAAC,aAAa;YAkBP,cAAc;IAa5B,OAAO,CAAC,WAAW;YAcL,QAAQ;IAWtB,OAAO,CAAC,SAAS;YAoBH,YAAY;YAMZ,cAAc;YAQd,iBAAiB;YAkBjB,eAAe;YAWf,eAAe;YAWf,gBAAgB;IA8B9B,OAAO,CAAC,cAAc;YAKR,aAAa;IAW3B,OAAO,CAAC,aAAa;YAIP,gBAAgB;YA8BhB,QAAQ;YAwCR,SAAS;YA4BT,UAAU;YA2EV,aAAa;IA2H3B,OAAO,CAAC,WAAW;YAoBL,gBAAgB;YA8BhB,YAAY;YAYZ,gBAAgB;YAmBhB,gBAAgB;IAsB9B,OAAO,CAAC,iBAAiB;IAmBzB,OAAO,CAAC,gBAAgB;YAQV,UAAU;CAczB"}
package/dist/runner.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { hostname } from "node:os";
2
+ import { sleepWithAbort } from "./abort-utils.js";
2
3
  import { compressBacktrace, extractBacktrace } from "./backtrace.js";
3
- import { Client } from "./client.js";
4
4
  import { ensureInterruptHandler } from "./interrupt-handler.js";
5
5
  import { JobSkipError } from "./iterable-errors.js";
6
6
  import { dumpJson, loadJson } from "./json.js";
@@ -11,11 +11,19 @@ const FETCH_TIMEOUT_SECONDS = 2;
11
11
  const STATS_TTL_SECONDS = 5 * 365 * 24 * 60 * 60;
12
12
  const INITIAL_WAIT_SECONDS = 10;
13
13
  const PAUSE_TIME_MS = 500;
14
- const LUA_ZPOPBYSCORE = `
15
- local key, now = KEYS[1], ARGV[1]
16
- local jobs = redis.call("zrange", key, "-inf", now, "byscore", "limit", 0, 1)
14
+ // Reliable scheduler: atomically pop from sorted set AND enqueue to queue
15
+ // This eliminates the data loss window between pop and push operations
16
+ const LUA_RELIABLE_ENQUEUE = `
17
+ local key, now_seconds, now_millis = KEYS[1], ARGV[1], ARGV[2]
18
+ local jobs = redis.call("zrange", key, "-inf", now_seconds, "byscore", "limit", 0, 1)
17
19
  if jobs[1] then
18
20
  redis.call("zrem", key, jobs[1])
21
+ local job = cjson.decode(jobs[1])
22
+ local queue = job.queue or "default"
23
+ job.enqueued_at = tonumber(now_millis)
24
+ local payload = cjson.encode(job)
25
+ redis.call("sadd", "queues", queue)
26
+ redis.call("lpush", "queue:" .. queue, payload)
19
27
  return jobs[1]
20
28
  end
21
29
  `;
@@ -99,9 +107,11 @@ export class Runner {
99
107
  quieting = false;
100
108
  stopping = false;
101
109
  workers = [];
102
- schedulerHandle;
103
110
  schedulerRunning = false;
104
- heartbeatHandle;
111
+ schedulerController;
112
+ heartbeatController;
113
+ heartbeatLoopPromise;
114
+ jobController;
105
115
  queueStrategy;
106
116
  baseRedis;
107
117
  workerRedis = [];
@@ -123,6 +133,7 @@ export class Runner {
123
133
  }
124
134
  async start() {
125
135
  this.baseRedis = await this.config.getRedisClient();
136
+ this.jobController = new AbortController();
126
137
  ensureInterruptHandler(this.config);
127
138
  // Start leader election
128
139
  this.leaderElector = new LeaderElector(this.config, {
@@ -153,14 +164,19 @@ export class Runner {
153
164
  await this.quiet();
154
165
  }
155
166
  this.stopping = true;
167
+ this.jobController?.abort();
156
168
  await this.config.fireEvent("shutdown", { reverse: true });
157
169
  // Stop periodic scheduler and leader election
158
170
  await this._periodicScheduler?.stop();
159
171
  await this.leaderElector?.stop();
160
172
  this.stopHeartbeat();
161
173
  this.stopScheduler();
174
+ // Wait for heartbeat loop to finish
175
+ if (this.heartbeatLoopPromise) {
176
+ await this.heartbeatLoopPromise;
177
+ }
162
178
  // Brief pause to allow idle processors to finish
163
- await sleep(PAUSE_TIME_MS);
179
+ await sleepWithAbort(PAUSE_TIME_MS, undefined);
164
180
  const deadline = Date.now() + this.config.timeout * 1000;
165
181
  // Early exit if no jobs are running
166
182
  if (this.inProgress.size === 0) {
@@ -224,6 +240,7 @@ export class Runner {
224
240
  }
225
241
  startScheduler() {
226
242
  this.schedulerRunning = true;
243
+ this.schedulerController = new AbortController();
227
244
  this.runSchedulerLoop().catch(() => undefined);
228
245
  }
229
246
  async runSchedulerLoop() {
@@ -232,7 +249,7 @@ export class Runner {
232
249
  while (this.schedulerRunning && !this.stopping) {
233
250
  await this.enqueueScheduled().catch(() => undefined);
234
251
  const intervalMs = await this.randomPollInterval();
235
- await sleep(intervalMs);
252
+ await sleepWithAbort(intervalMs, this.schedulerController?.signal);
236
253
  }
237
254
  }
238
255
  async initialWait() {
@@ -245,7 +262,7 @@ export class Runner {
245
262
  }
246
263
  waitSeconds += Math.random() * 5; // 0-5 seconds jitter
247
264
  if (waitSeconds > 0) {
248
- await sleep(waitSeconds * 1000);
265
+ await sleepWithAbort(waitSeconds * 1000, this.schedulerController?.signal);
249
266
  }
250
267
  // Run cleanup after initial wait
251
268
  const redis = this.baseRedis ?? (await this.config.getRedisClient());
@@ -279,10 +296,7 @@ export class Runner {
279
296
  }
280
297
  stopScheduler() {
281
298
  this.schedulerRunning = false;
282
- if (this.schedulerHandle) {
283
- clearInterval(this.schedulerHandle);
284
- this.schedulerHandle = undefined;
285
- }
299
+ this.schedulerController?.abort();
286
300
  }
287
301
  async heartbeat() {
288
302
  if (this.stopping) {
@@ -490,44 +504,55 @@ export class Runner {
490
504
  }
491
505
  }
492
506
  startHeartbeat() {
507
+ this.heartbeatController = new AbortController();
508
+ this.heartbeatLoopPromise = this.heartbeatLoop();
509
+ }
510
+ async heartbeatLoop() {
493
511
  const intervalMs = this.config.heartbeatInterval * 1000;
494
- this.heartbeatHandle = setInterval(() => {
495
- this.heartbeat().catch(() => undefined);
496
- }, intervalMs);
512
+ while (!this.stopping) {
513
+ await sleepWithAbort(intervalMs, this.heartbeatController?.signal);
514
+ if (this.stopping) {
515
+ break;
516
+ }
517
+ await this.heartbeat().catch(() => undefined);
518
+ }
497
519
  }
498
520
  stopHeartbeat() {
499
- if (this.heartbeatHandle) {
500
- clearInterval(this.heartbeatHandle);
501
- this.heartbeatHandle = undefined;
502
- }
521
+ this.heartbeatController?.abort();
503
522
  }
504
523
  async enqueueScheduled() {
505
524
  if (this.stopping) {
506
525
  return;
507
526
  }
508
527
  const redis = this.baseRedis ?? (await this.config.getRedisClient());
509
- const client = new Client({ config: this.config });
510
- const now = Date.now() / 1000;
528
+ const nowMs = Date.now();
529
+ const nowSeconds = nowMs / 1000;
511
530
  const sets = ["schedule", "retry"];
512
531
  for (const set of sets) {
513
532
  while (!this.stopping) {
533
+ // Atomic operation: pop from sorted set AND push to queue in one step
534
+ // This eliminates data loss if process crashes between operations
514
535
  const job = (await redis.sendCommand([
515
536
  "EVAL",
516
- LUA_ZPOPBYSCORE,
537
+ LUA_RELIABLE_ENQUEUE,
517
538
  "1",
518
539
  set,
519
- String(now),
540
+ String(nowSeconds),
541
+ String(nowMs),
520
542
  ]));
521
543
  if (!job) {
522
544
  break;
523
545
  }
524
- const payload = loadJson(job);
525
- await client.push(payload);
546
+ // Job was atomically moved to its queue - no additional action needed
526
547
  }
527
548
  }
528
549
  }
529
550
  async workLoop(index) {
530
- while (!this.stopping) {
551
+ while (true) {
552
+ // Check stopping BEFORE fetching - don't start new work
553
+ if (this.stopping) {
554
+ break;
555
+ }
531
556
  if (this.quieting) {
532
557
  await sleep(50);
533
558
  continue;
@@ -536,6 +561,8 @@ export class Runner {
536
561
  if (!unit) {
537
562
  continue;
538
563
  }
564
+ // Process the job - even if stopping became true during fetchWork
565
+ // Once we've popped a job from Redis, we MUST process it
539
566
  const workerId = `worker-${index}`;
540
567
  this.inProgress.set(workerId, {
541
568
  queue: unit.queue,
@@ -599,7 +626,10 @@ export class Runner {
599
626
  }
600
627
  const job = new klass();
601
628
  job.jid = payload.jid;
602
- job._context = { stopping: () => this.stopping };
629
+ job._context = {
630
+ stopping: () => this.stopping,
631
+ signal: this.jobController?.signal,
632
+ };
603
633
  try {
604
634
  let executed = false;
605
635
  await this.jobLogger.prepare(payload, async () => {
package/dist/sidekiq.d.ts CHANGED
@@ -2,7 +2,13 @@ import { Config } from "./config.js";
2
2
  import type { MiddlewareConstructor } from "./middleware.js";
3
3
  import type { RedisClient } from "./redis.js";
4
4
  import { type RegisteredJobClass } from "./registry.js";
5
+ import type { Runner } from "./runner.js";
5
6
  import type { ConfigOptions, JobOptions, JobPayload, SidekiqEventHandler, SidekiqEventName, StrictArgsMode } from "./types.js";
7
+ interface RunOptions {
8
+ config?: Config;
9
+ /** Auto-register SIGINT/SIGTERM handlers for graceful shutdown */
10
+ signals?: boolean;
11
+ }
6
12
  export declare class Sidekiq {
7
13
  static readonly NAME = "Sidekiq";
8
14
  static readonly LICENSE = "See LICENSE and the LGPL-3.0 for licensing details.";
@@ -36,8 +42,8 @@ export declare class Sidekiq {
36
42
  static redis<T>(fn: (client: Awaited<ReturnType<Config["getRedisClient"]>>) => Promise<T>): Promise<T>;
37
43
  static registerJob(klass: RegisteredJobClass): void;
38
44
  static registeredJobClass(name: string): RegisteredJobClass | undefined;
39
- static run({ config }?: {
40
- config?: Config;
41
- }): Promise<import("./runner.js").Runner>;
45
+ static run({ config, signals }?: RunOptions): Promise<Runner>;
46
+ private static registerSignalHandlers;
42
47
  }
48
+ export {};
43
49
  //# sourceMappingURL=sidekiq.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sidekiq.d.ts","sourceRoot":"","sources":["../src/sidekiq.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EACL,KAAK,kBAAkB,EAGxB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EACV,aAAa,EAGb,UAAU,EACV,UAAU,EAGV,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACf,MAAM,YAAY,CAAC;AAGpB,qBAAa,OAAO;IAClB,MAAM,CAAC,QAAQ,CAAC,IAAI,aAAa;IACjC,MAAM,CAAC,QAAQ,CAAC,OAAO,yDACiC;IAExD,OAAO,CAAC,MAAM,CAAC,MAAM,CAAgB;IACrC,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAuB;IACvD,OAAO,CAAC,MAAM,CAAC,YAAY,CAAS;IACpC,OAAO,CAAC,MAAM,CAAC,cAAc,CAG3B;IAEF,MAAM,KAAK,oBAAoB,IAAI,MAAM,CAExC;IAED,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAOpD,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAMpD,MAAM,CAAC,EAAE,CAAC,MAAM,SAAS,gBAAgB,EACvC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,mBAAmB,CAAC,MAAM,CAAC,GACnC,IAAI;IAcP,MAAM,CAAC,mBAAmB,CACxB,KAAK,EAAE,qBAAqB,CAC1B;QAAC,MAAM,GAAG,OAAO;QAAE,UAAU;QAAE,MAAM;QAAE,WAAW;KAAC,EACnD,UAAU,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,CACtC,EACD,GAAG,IAAI,EAAE,OAAO,EAAE,GACjB,IAAI;IAIP,MAAM,CAAC,mBAAmB,CACxB,KAAK,EAAE,qBAAqB,CAAC,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EACpE,GAAG,IAAI,EAAE,OAAO,EAAE,GACjB,IAAI;IAIP,MAAM,CAAC,cAAc,IAAI,IAAI;IAO7B,MAAM,CAAC,iBAAiB,IAAI,UAAU;IAItC,MAAM,CAAC,oBAAoB,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI;IAOtD,MAAM,CAAC,UAAU,CAAC,IAAI,GAAE,cAAwB,GAAG,IAAI;IAIvD,MAAM,CAAC,MAAM;IAIb,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAMjC,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAqEjC,OAAO,CAAC,MAAM,CAAC,mBAAmB;IASlC,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAepC,OAAO,CAAC,MAAM,CAAC,YAAY;IAS3B,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM;IAIvC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;WAI1B,KAAK,CAAC,CAAC,EAClB,EAAE,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GACxE,OAAO,CAAC,CAAC,CAAC;IAKb,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAInD,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;WAI1D,GAAG,CAAC,EAAE,MAAM,EAAE,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO;CAUtD"}
1
+ {"version":3,"file":"sidekiq.d.ts","sourceRoot":"","sources":["../src/sidekiq.ts"],"names":[],"mappings":"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"}
package/dist/sidekiq.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { createShutdownHandler } from "./cli-helpers.js";
1
2
  import { Config } from "./config.js";
2
3
  import { dumpJson, loadJson } from "./json.js";
3
4
  import { registeredJob, registerJob, } from "./registry.js";
@@ -176,7 +177,7 @@ export class Sidekiq {
176
177
  static registeredJobClass(name) {
177
178
  return registeredJob(name);
178
179
  }
179
- static async run({ config } = {}) {
180
+ static async run({ config, signals } = {}) {
180
181
  if (config) {
181
182
  this.config = config;
182
183
  }
@@ -184,6 +185,29 @@ export class Sidekiq {
184
185
  const { Runner } = await import("./runner.js");
185
186
  const runner = new Runner(this.config);
186
187
  await runner.start();
188
+ if (signals) {
189
+ this.registerSignalHandlers(runner);
190
+ }
187
191
  return runner;
188
192
  }
193
+ static registerSignalHandlers(runner) {
194
+ const shutdown = createShutdownHandler({
195
+ logger: this.config.logger,
196
+ stop: () => runner.stop(),
197
+ exit: (code) => process.exit(code),
198
+ });
199
+ const registerSignal = (signal, handler) => {
200
+ try {
201
+ process.on(signal, () => {
202
+ Promise.resolve(handler()).catch(() => undefined);
203
+ });
204
+ }
205
+ catch {
206
+ // Signal not supported on this platform
207
+ }
208
+ };
209
+ registerSignal("SIGINT", () => shutdown("SIGINT"));
210
+ registerSignal("SIGTERM", () => shutdown("SIGTERM"));
211
+ registerSignal("SIGTSTP", () => runner.quiet());
212
+ }
189
213
  }
package/dist/types.d.ts CHANGED
@@ -52,6 +52,8 @@ export interface ConfigOptions {
52
52
  redisIdleTimeout?: number | null;
53
53
  /** Leader election configuration */
54
54
  leaderElection?: LeaderElectionConfig;
55
+ /** Maximum jobs to hold locally when Redis is unavailable (default: 1000, 0 to disable) */
56
+ reliableClientMaxQueue?: number;
55
57
  }
56
58
  export type JobRetryOption = boolean | number;
57
59
  export interface JobOptions {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sidekiq-ts",
3
- "version": "1.0.2",
3
+ "version": "1.0.5",
4
4
  "description": "TypeScript client for Sidekiq job processing",
5
5
  "license": "MIT",
6
6
  "keywords": [