sidekiq-ts 1.0.0 → 1.0.2
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 +25 -7
- package/dist/cli-helpers.d.ts +11 -0
- package/dist/cli-helpers.d.ts.map +1 -1
- package/dist/cli-helpers.js +16 -0
- package/dist/cli.js +6 -11
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +16 -0
- package/package.json +13 -4
package/README.md
CHANGED
|
@@ -272,7 +272,7 @@ process.on("SIGTERM", async () => {
|
|
|
272
272
|
### CLI
|
|
273
273
|
|
|
274
274
|
```bash
|
|
275
|
-
sidekiq
|
|
275
|
+
npx sidekiq [options]
|
|
276
276
|
```
|
|
277
277
|
|
|
278
278
|
**Options:**
|
|
@@ -294,13 +294,13 @@ sidekiq-ts [options]
|
|
|
294
294
|
|
|
295
295
|
```bash
|
|
296
296
|
# Basic usage
|
|
297
|
-
sidekiq
|
|
297
|
+
npx sidekiq -r ./dist/jobs.js
|
|
298
298
|
|
|
299
299
|
# Multiple queues with weights
|
|
300
|
-
sidekiq
|
|
300
|
+
npx sidekiq -q critical,5 -q default,2 -q background -c 10
|
|
301
301
|
|
|
302
302
|
# With config file
|
|
303
|
-
sidekiq
|
|
303
|
+
npx sidekiq -C config/sidekiq.json -e production
|
|
304
304
|
```
|
|
305
305
|
|
|
306
306
|
## Configuration File
|
|
@@ -640,7 +640,7 @@ After=network.target redis.service
|
|
|
640
640
|
Type=simple
|
|
641
641
|
User=app
|
|
642
642
|
WorkingDirectory=/app
|
|
643
|
-
ExecStart=/usr/bin/
|
|
643
|
+
ExecStart=/usr/bin/npx sidekiq -C /app/sidekiq.json
|
|
644
644
|
Restart=always
|
|
645
645
|
RestartSec=5
|
|
646
646
|
|
|
@@ -655,14 +655,32 @@ WantedBy=multi-user.target
|
|
|
655
655
|
module.exports = {
|
|
656
656
|
apps: [{
|
|
657
657
|
name: "sidekiq-worker",
|
|
658
|
-
script: "
|
|
659
|
-
args: "-C sidekiq.json",
|
|
658
|
+
script: "npx",
|
|
659
|
+
args: "sidekiq -C sidekiq.json",
|
|
660
660
|
instances: 2,
|
|
661
661
|
exec_mode: "cluster",
|
|
662
662
|
}]
|
|
663
663
|
};
|
|
664
664
|
```
|
|
665
665
|
|
|
666
|
+
**Docker example:**
|
|
667
|
+
|
|
668
|
+
```dockerfile
|
|
669
|
+
FROM node:24-alpine
|
|
670
|
+
WORKDIR /app
|
|
671
|
+
COPY package*.json ./
|
|
672
|
+
RUN npm ci --omit=dev
|
|
673
|
+
COPY dist ./dist
|
|
674
|
+
COPY sidekiq.json ./
|
|
675
|
+
CMD ["npx", "sidekiq", "-C", "sidekiq.json"]
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
```bash
|
|
679
|
+
# Build and run
|
|
680
|
+
docker build -t my-worker .
|
|
681
|
+
docker run -e REDIS_URL=redis://host:6379 my-worker
|
|
682
|
+
```
|
|
683
|
+
|
|
666
684
|
### Redis Configuration
|
|
667
685
|
|
|
668
686
|
For production Redis:
|
package/dist/cli-helpers.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Config } from "./config.js";
|
|
2
|
+
import type { Logger } from "./logger.js";
|
|
2
3
|
export declare const DEFAULT_CONFIG_PATH = "sidekiq.json";
|
|
3
4
|
export interface CliOptions {
|
|
4
5
|
configPath: string;
|
|
@@ -19,4 +20,14 @@ export declare const applyCliOptions: (config: Config, options: CliOptions, load
|
|
|
19
20
|
config: Config;
|
|
20
21
|
requirePaths: string[];
|
|
21
22
|
};
|
|
23
|
+
export interface ShutdownDeps {
|
|
24
|
+
logger: Logger;
|
|
25
|
+
stop: () => Promise<void>;
|
|
26
|
+
exit: (code: number) => void;
|
|
27
|
+
}
|
|
28
|
+
export interface ShutdownHandler {
|
|
29
|
+
(signal: string): Promise<void>;
|
|
30
|
+
isShuttingDown: () => boolean;
|
|
31
|
+
}
|
|
32
|
+
export declare const createShutdownHandler: (deps: ShutdownDeps) => ShutdownHandler;
|
|
22
33
|
//# sourceMappingURL=cli-helpers.d.ts.map
|
|
@@ -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;
|
|
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"}
|
package/dist/cli-helpers.js
CHANGED
|
@@ -150,3 +150,19 @@ export const applyCliOptions = (config, options, loadedRequirePaths = []) => {
|
|
|
150
150
|
}
|
|
151
151
|
return { config, requirePaths };
|
|
152
152
|
};
|
|
153
|
+
export const createShutdownHandler = (deps) => {
|
|
154
|
+
let shuttingDown = false;
|
|
155
|
+
const handler = async (signal) => {
|
|
156
|
+
if (shuttingDown) {
|
|
157
|
+
deps.logger.info(() => `Received ${signal}, forcing exit`);
|
|
158
|
+
deps.exit(1);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
shuttingDown = true;
|
|
162
|
+
deps.logger.info(() => `Received ${signal}, shutting down`);
|
|
163
|
+
await deps.stop();
|
|
164
|
+
deps.exit(0);
|
|
165
|
+
};
|
|
166
|
+
handler.isShuttingDown = () => shuttingDown;
|
|
167
|
+
return handler;
|
|
168
|
+
};
|
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import { access } from "node:fs/promises";
|
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { resolve } from "node:path";
|
|
5
5
|
import { pathToFileURL } from "node:url";
|
|
6
|
-
import { applyCliOptions, parseArgs, resolveEnvironment, } from "./cli-helpers.js";
|
|
6
|
+
import { applyCliOptions, createShutdownHandler, parseArgs, resolveEnvironment, } from "./cli-helpers.js";
|
|
7
7
|
import { Config } from "./config.js";
|
|
8
8
|
import { loadConfigFile } from "./config-loader.js";
|
|
9
9
|
import { Sidekiq } from "./sidekiq.js";
|
|
@@ -80,17 +80,12 @@ const main = async () => {
|
|
|
80
80
|
await import(pathToFileURL(fullPath).href);
|
|
81
81
|
}
|
|
82
82
|
const runner = await Sidekiq.run({ config });
|
|
83
|
-
let shuttingDown = false;
|
|
84
83
|
let quieting = false;
|
|
85
|
-
const shutdown =
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
config.logger.info(() => `Received ${signal}, shutting down`);
|
|
91
|
-
await runner.stop();
|
|
92
|
-
process.exit(0);
|
|
93
|
-
};
|
|
84
|
+
const shutdown = createShutdownHandler({
|
|
85
|
+
logger: config.logger,
|
|
86
|
+
stop: () => runner.stop(),
|
|
87
|
+
exit: (code) => process.exit(code),
|
|
88
|
+
});
|
|
94
89
|
const quiet = async (signal) => {
|
|
95
90
|
if (quieting) {
|
|
96
91
|
return;
|
package/dist/runner.d.ts.map
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/runner.js
CHANGED
|
@@ -10,6 +10,7 @@ import { resolveJob } from "./registry.js";
|
|
|
10
10
|
const FETCH_TIMEOUT_SECONDS = 2;
|
|
11
11
|
const STATS_TTL_SECONDS = 5 * 365 * 24 * 60 * 60;
|
|
12
12
|
const INITIAL_WAIT_SECONDS = 10;
|
|
13
|
+
const PAUSE_TIME_MS = 500;
|
|
13
14
|
const LUA_ZPOPBYSCORE = `
|
|
14
15
|
local key, now = KEYS[1], ARGV[1]
|
|
15
16
|
local jobs = redis.call("zrange", key, "-inf", now, "byscore", "limit", 0, 1)
|
|
@@ -158,7 +159,22 @@ export class Runner {
|
|
|
158
159
|
await this.leaderElector?.stop();
|
|
159
160
|
this.stopHeartbeat();
|
|
160
161
|
this.stopScheduler();
|
|
162
|
+
// Brief pause to allow idle processors to finish
|
|
163
|
+
await sleep(PAUSE_TIME_MS);
|
|
161
164
|
const deadline = Date.now() + this.config.timeout * 1000;
|
|
165
|
+
// Early exit if no jobs are running
|
|
166
|
+
if (this.inProgress.size === 0) {
|
|
167
|
+
await this.waitForWorkers(deadline);
|
|
168
|
+
await this.clearHeartbeat();
|
|
169
|
+
await Promise.all(this.workerRedis.map(async (client) => {
|
|
170
|
+
if (client.isOpen) {
|
|
171
|
+
await client.quit();
|
|
172
|
+
}
|
|
173
|
+
}));
|
|
174
|
+
await this.config.fireEvent("exit", { reverse: true });
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
this.config.logger.info(() => "Pausing to allow jobs to finish...");
|
|
162
178
|
await this.waitForDrain(deadline);
|
|
163
179
|
if (this.inProgress.size > 0) {
|
|
164
180
|
await this.requeueInProgress();
|
package/package.json
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sidekiq-ts",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "TypeScript client for Sidekiq job processing",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"keywords": [
|
|
6
|
+
"keywords": [
|
|
7
|
+
"sidekiq",
|
|
8
|
+
"redis",
|
|
9
|
+
"job",
|
|
10
|
+
"queue",
|
|
11
|
+
"worker",
|
|
12
|
+
"typescript"
|
|
13
|
+
],
|
|
7
14
|
"type": "module",
|
|
8
15
|
"main": "dist/index.js",
|
|
9
16
|
"types": "dist/index.d.ts",
|
|
@@ -16,7 +23,9 @@
|
|
|
16
23
|
"bin": {
|
|
17
24
|
"sidekiq": "dist/cli.js"
|
|
18
25
|
},
|
|
19
|
-
"files": [
|
|
26
|
+
"files": [
|
|
27
|
+
"dist"
|
|
28
|
+
],
|
|
20
29
|
"engines": {
|
|
21
30
|
"node": ">=24.12.0"
|
|
22
31
|
},
|
|
@@ -37,6 +46,6 @@
|
|
|
37
46
|
"tsx": "^4.19.2",
|
|
38
47
|
"typescript": "^5.7.2",
|
|
39
48
|
"ultracite": "^6.5.0",
|
|
40
|
-
"vitest": "^
|
|
49
|
+
"vitest": "^4.0.16"
|
|
41
50
|
}
|
|
42
51
|
}
|