queasy 0.3.0 → 0.3.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.
- package/.github/workflows/check.yml +3 -0
- package/.github/workflows/publish.yml +3 -0
- package/CLAUDE.md +5 -4
- package/biome.json +5 -1
- package/dist/client.d.ts +33 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +199 -0
- package/dist/client.js.map +1 -0
- package/dist/constants.d.ts +10 -0
- package/dist/constants.d.ts.map +1 -0
- package/{src → dist}/constants.js +1 -9
- package/dist/constants.js.map +1 -0
- package/dist/errors.d.ts +7 -0
- package/dist/errors.d.ts.map +1 -0
- package/{src → dist}/errors.js +1 -13
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/manager.d.ts +19 -0
- package/dist/manager.d.ts.map +1 -0
- package/dist/manager.js +67 -0
- package/dist/manager.js.map +1 -0
- package/dist/pool.d.ts +29 -0
- package/dist/pool.d.ts.map +1 -0
- package/{src → dist}/pool.js +23 -82
- package/dist/pool.js.map +1 -0
- package/dist/queasy.lua +390 -0
- package/dist/queue.d.ts +22 -0
- package/dist/queue.d.ts.map +1 -0
- package/dist/queue.js +81 -0
- package/dist/queue.js.map +1 -0
- package/dist/types.d.ts +92 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +24 -0
- package/dist/utils.js.map +1 -0
- package/dist/worker.d.ts +2 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +42 -0
- package/dist/worker.js.map +1 -0
- package/fuzztest/{fuzz.js → fuzz.ts} +53 -51
- package/fuzztest/handlers/{cascade-a.js → cascade-a.ts} +11 -15
- package/fuzztest/handlers/{cascade-b.js → cascade-b.ts} +8 -9
- package/fuzztest/handlers/{fail-handler.js → fail-handler.ts} +7 -12
- package/fuzztest/handlers/{periodic.js → periodic.ts} +11 -15
- package/fuzztest/{process.js → process.ts} +15 -15
- package/fuzztest/shared/{chaos.js → chaos.ts} +5 -4
- package/fuzztest/shared/{stream.js → stream.ts} +7 -7
- package/package.json +7 -5
- package/src/{client.js → client.ts} +86 -128
- package/src/constants.ts +33 -0
- package/src/errors.ts +13 -0
- package/src/index.ts +2 -0
- package/src/manager.ts +78 -0
- package/src/pool.ts +129 -0
- package/src/queue.ts +108 -0
- package/src/types.ts +1 -0
- package/src/{utils.js → utils.ts} +3 -20
- package/src/{worker.js → worker.ts} +5 -12
- package/test/{client.test.js → client.test.ts} +6 -7
- package/test/{errors.test.js → errors.test.ts} +1 -1
- package/test/fixtures/always-fail-handler.ts +5 -0
- package/test/fixtures/data-logger-handler.ts +11 -0
- package/test/fixtures/failure-handler.ts +6 -0
- package/test/fixtures/permanent-error-handler.ts +6 -0
- package/test/fixtures/slow-handler.ts +6 -0
- package/test/fixtures/success-handler.js +0 -5
- package/test/fixtures/success-handler.ts +6 -0
- package/test/fixtures/with-failure-handler.ts +5 -0
- package/test/{guards.test.js → guards.test.ts} +9 -12
- package/test/{manager.test.js → manager.test.ts} +23 -33
- package/test/{pool.test.js → pool.test.ts} +10 -14
- package/test/{queue.test.js → queue.test.ts} +16 -17
- package/test/{redis-functions.test.js → redis-functions.test.ts} +14 -20
- package/test/{utils.test.js → utils.test.ts} +1 -1
- package/tsconfig.json +20 -0
- package/jsconfig.json +0 -17
- package/src/index.js +0 -2
- package/src/manager.js +0 -94
- package/src/queue.js +0 -154
- package/test/fixtures/always-fail-handler.js +0 -8
- package/test/fixtures/data-logger-handler.js +0 -19
- package/test/fixtures/failure-handler.js +0 -9
- package/test/fixtures/permanent-error-handler.js +0 -10
- package/test/fixtures/slow-handler.js +0 -9
- package/test/fixtures/with-failure-handler.js +0 -8
- /package/test/fixtures/{no-handle-handler.js → no-handle-handler.ts} +0 -0
package/CLAUDE.md
CHANGED
|
@@ -10,7 +10,8 @@ npm test -- --test-name-pattern="pattern" # Run tests matching a pattern
|
|
|
10
10
|
node --test test/queue.test.js # Run a single test file
|
|
11
11
|
npm run lint # Lint with Biome
|
|
12
12
|
npm run format # Auto-format with Biome
|
|
13
|
-
npm run
|
|
13
|
+
npm run build # Compile TypeScript to dist/
|
|
14
|
+
npm run typecheck # TypeScript type-check without emitting
|
|
14
15
|
npm run docker:up # Start Redis via Docker Compose
|
|
15
16
|
npm run docker:down # Stop Redis
|
|
16
17
|
```
|
|
@@ -21,7 +22,7 @@ Tests require a running Redis instance. Use `docker:up` first if needed.
|
|
|
21
22
|
|
|
22
23
|
Queasy is a Redis-backed job queue with **at-least-once** delivery semantics. The core logic lives in two layers:
|
|
23
24
|
|
|
24
|
-
- **
|
|
25
|
+
- **TypeScript layer** (`src/client.ts`): The `Client` class accepts a `RedisOptions` object and constructs its own node-redis connection via `createClient` (plain object) or `createCluster` (object with `rootNodes`). On construction it connects, then uploads the Lua script to Redis via `FUNCTION LOAD REPLACE`. The connection is torn down in `close()` via `destroy()`. Source compiles to `dist/` via `npm run build`.
|
|
25
26
|
- **Lua layer** (`src/queasy.lua`): All queue state mutations are atomic Redis functions registered under the `queasy` library. No queue logic should be duplicated in JS — the Lua functions are the single source of truth for state transitions.
|
|
26
27
|
|
|
27
28
|
### Redis data structures
|
|
@@ -77,7 +78,7 @@ Queue names in tests use `{curly-brace}` syntax (e.g., `{test-api-queue}`) to ke
|
|
|
77
78
|
## Conventions
|
|
78
79
|
|
|
79
80
|
- ESM modules throughout (`"type": "module"` in package.json).
|
|
80
|
-
-
|
|
81
|
-
- Biome for formatting (
|
|
81
|
+
- TypeScript source in `src/`, compiled output in `dist/`. Run `npm run build` before running tests.
|
|
82
|
+
- Biome for formatting (spaces, single quotes, 100-char width). Run `npm run format` before committing.
|
|
82
83
|
- All Lua booleans arrive as strings (`'true'`/`'false'`) from `redis.fCall` — comparisons in Lua must use string equality.
|
|
83
84
|
- `redis.setresp(3)` is called in each registered function to get RESP3 map responses (needed for `HGETALL` returning `{ map: {...} }` instead of a flat array).
|
package/biome.json
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://biomejs.dev/schemas/2.3.14/schema.json",
|
|
3
|
+
"files": {
|
|
4
|
+
"includes": ["**", "!!dist"]
|
|
5
|
+
},
|
|
3
6
|
"assist": { "actions": { "source": { "organizeImports": "on" } } },
|
|
4
7
|
"linter": {
|
|
5
8
|
"enabled": true,
|
|
@@ -9,7 +12,8 @@
|
|
|
9
12
|
"noForEach": "off"
|
|
10
13
|
},
|
|
11
14
|
"style": {
|
|
12
|
-
"useNodejsImportProtocol": "error"
|
|
15
|
+
"useNodejsImportProtocol": "error",
|
|
16
|
+
"noNonNullAssertion": "off"
|
|
13
17
|
}
|
|
14
18
|
}
|
|
15
19
|
},
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import EventEmitter from 'node:events';
|
|
2
|
+
import { createClient, createCluster } from 'redis';
|
|
3
|
+
import { Manager } from './manager.ts';
|
|
4
|
+
import { Pool } from './pool.ts';
|
|
5
|
+
import { Queue } from './queue.ts';
|
|
6
|
+
import type { Job, RedisOptions } from './types.ts';
|
|
7
|
+
type RedisConnection = ReturnType<typeof createClient> | ReturnType<typeof createCluster>;
|
|
8
|
+
interface QueueEntry {
|
|
9
|
+
queue: Queue;
|
|
10
|
+
bumpTimer?: NodeJS.Timeout;
|
|
11
|
+
}
|
|
12
|
+
export declare function parseJob(jobArray: string[]): Job | null;
|
|
13
|
+
export declare class Client extends EventEmitter {
|
|
14
|
+
redis: RedisConnection;
|
|
15
|
+
clientId: string;
|
|
16
|
+
queues: Record<string, QueueEntry>;
|
|
17
|
+
disconnected: boolean;
|
|
18
|
+
pool: Pool | undefined;
|
|
19
|
+
manager: Manager | undefined;
|
|
20
|
+
constructor(options?: RedisOptions, workerCount?: number, callback?: (client: Client) => unknown);
|
|
21
|
+
queue(name: string, isKey?: boolean): Queue;
|
|
22
|
+
scheduleBump(key: string): void;
|
|
23
|
+
bump(key: string): Promise<void>;
|
|
24
|
+
close(): Promise<void>;
|
|
25
|
+
dispatch(key: string, id: string, runAt: number, data: any, updateData: boolean, updateRunAt: boolean | string, resetCounts: boolean): Promise<void>;
|
|
26
|
+
cancel(key: string, id: string): Promise<boolean>;
|
|
27
|
+
dequeue(key: string, count: number): Promise<Job[]>;
|
|
28
|
+
finish(key: string, jobId: string): Promise<void>;
|
|
29
|
+
fail(key: string, failkey: string, jobId: string, failJobData: any): Promise<void>;
|
|
30
|
+
retry(key: string, jobId: string, retryAt: number): Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,aAAa,CAAC;AAMvC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEpD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AASpD,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AA6B1F,UAAU,UAAU;IAChB,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;CAC9B;AAED,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAG,GAAG,IAAI,CAiBvD;AAED,qBAAa,MAAO,SAAQ,YAAY;IACpC,KAAK,EAAE,eAAe,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACnC,YAAY,EAAE,OAAO,CAAC;IACtB,IAAI,EAAE,IAAI,GAAG,SAAS,CAAC;IACvB,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;gBAGzB,OAAO,GAAE,YAAiB,EAC1B,WAAW,GAAE,MAAyB,EACtC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO;IA6B1C,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,UAAQ,GAAG,KAAK;IAYzC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAMzB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBhC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAStB,QAAQ,CACV,GAAG,EAAE,MAAM,EACX,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EAEb,IAAI,EAAE,GAAG,EACT,UAAU,EAAE,OAAO,EACnB,WAAW,EAAE,OAAO,GAAG,MAAM,EAC7B,WAAW,EAAE,OAAO,GACrB,OAAO,CAAC,IAAI,CAAC;IAeV,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAYjD,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAkBnD,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQjD,IAAI,CACN,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EAEb,WAAW,EAAE,GAAG,GACjB,OAAO,CAAC,IAAI,CAAC;IAcV,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAO1E"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import EventEmitter from 'node:events';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import { dirname, join } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { getEnvironmentData } from 'node:worker_threads';
|
|
7
|
+
import { createClient, createCluster } from 'redis';
|
|
8
|
+
import { HEARTBEAT_INTERVAL, HEARTBEAT_TIMEOUT, LUA_FUNCTIONS_VERSION } from "./constants.js";
|
|
9
|
+
import { Manager } from "./manager.js";
|
|
10
|
+
import { Pool } from "./pool.js";
|
|
11
|
+
import { Queue } from "./queue.js";
|
|
12
|
+
import { compareSemver, generateId, parseVersion } from "./utils.js";
|
|
13
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const luaScript = readFileSync(join(__dirname, 'queasy.lua'), 'utf8').replace('__QUEASY_VERSION__', LUA_FUNCTIONS_VERSION);
|
|
15
|
+
async function installLuaFunctions(redis) {
|
|
16
|
+
const installedVersionString = (await redis
|
|
17
|
+
.fCall('queasy_version', { keys: [], arguments: [] })
|
|
18
|
+
.catch(() => null));
|
|
19
|
+
const installedVersion = parseVersion(installedVersionString);
|
|
20
|
+
const availableVersion = parseVersion(LUA_FUNCTIONS_VERSION);
|
|
21
|
+
if (compareSemver(availableVersion, installedVersion) > 0) {
|
|
22
|
+
await redis.sendCommand([
|
|
23
|
+
'FUNCTION',
|
|
24
|
+
'LOAD',
|
|
25
|
+
'REPLACE',
|
|
26
|
+
luaScript,
|
|
27
|
+
]);
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
return installedVersion[0] > availableVersion[0];
|
|
31
|
+
}
|
|
32
|
+
function buildRedisConnection(options) {
|
|
33
|
+
if ('rootNodes' in options) {
|
|
34
|
+
return createCluster(options);
|
|
35
|
+
}
|
|
36
|
+
return createClient(options);
|
|
37
|
+
}
|
|
38
|
+
export function parseJob(jobArray) {
|
|
39
|
+
if (!jobArray || jobArray.length === 0)
|
|
40
|
+
return null;
|
|
41
|
+
const job = {};
|
|
42
|
+
for (let i = 0; i < jobArray.length; i += 2) {
|
|
43
|
+
const key = jobArray[i];
|
|
44
|
+
const value = jobArray[i + 1];
|
|
45
|
+
job[key] = value;
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
id: job.id,
|
|
49
|
+
data: job.data ? JSON.parse(job.data) : undefined,
|
|
50
|
+
runAt: job.run_at ? Number(job.run_at) : 0,
|
|
51
|
+
retryCount: Number(job.retry_count || 0),
|
|
52
|
+
stallCount: Number(job.stall_count || 0),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export class Client extends EventEmitter {
|
|
56
|
+
redis;
|
|
57
|
+
clientId;
|
|
58
|
+
queues;
|
|
59
|
+
disconnected;
|
|
60
|
+
pool;
|
|
61
|
+
manager;
|
|
62
|
+
constructor(options = {}, workerCount = os.cpus().length, callback) {
|
|
63
|
+
super();
|
|
64
|
+
this.redis = buildRedisConnection(options);
|
|
65
|
+
this.clientId = generateId();
|
|
66
|
+
this.queues = {};
|
|
67
|
+
this.disconnected = false;
|
|
68
|
+
const inWorker = getEnvironmentData('queasy_worker_context');
|
|
69
|
+
this.pool = !inWorker && workerCount !== 0 ? new Pool(workerCount) : undefined;
|
|
70
|
+
if (this.pool)
|
|
71
|
+
this.manager = new Manager(this.pool);
|
|
72
|
+
this.redis
|
|
73
|
+
.connect()
|
|
74
|
+
.then(() => installLuaFunctions(this.redis))
|
|
75
|
+
.then((disconnect) => {
|
|
76
|
+
this.disconnected = disconnect;
|
|
77
|
+
if (disconnect)
|
|
78
|
+
this.emit('disconnected', 'Redis has incompatible queasy version.');
|
|
79
|
+
else {
|
|
80
|
+
this.emit('connected');
|
|
81
|
+
if (callback)
|
|
82
|
+
callback(this);
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
.catch((err) => {
|
|
86
|
+
this.disconnected = true;
|
|
87
|
+
this.emit('disconnected', err.message);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
queue(name, isKey = false) {
|
|
91
|
+
if (this.disconnected)
|
|
92
|
+
throw new Error("Can't add queue: client disconnected");
|
|
93
|
+
const key = isKey ? name : `{${name}}`;
|
|
94
|
+
if (!this.queues[key]) {
|
|
95
|
+
this.queues[key] = {
|
|
96
|
+
queue: new Queue(key, this, this.pool, this.manager),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return this.queues[key].queue;
|
|
100
|
+
}
|
|
101
|
+
scheduleBump(key) {
|
|
102
|
+
const queueEntry = this.queues[key];
|
|
103
|
+
if (queueEntry.bumpTimer)
|
|
104
|
+
clearTimeout(queueEntry.bumpTimer);
|
|
105
|
+
queueEntry.bumpTimer = setTimeout(() => this.bump(key), HEARTBEAT_INTERVAL);
|
|
106
|
+
}
|
|
107
|
+
async bump(key) {
|
|
108
|
+
if (this.disconnected)
|
|
109
|
+
return;
|
|
110
|
+
this.scheduleBump(key);
|
|
111
|
+
const now = Date.now();
|
|
112
|
+
const expiry = now + HEARTBEAT_TIMEOUT;
|
|
113
|
+
const bumped = await this.redis.fCall('queasy_bump', {
|
|
114
|
+
keys: [key],
|
|
115
|
+
arguments: [this.clientId, String(now), String(expiry)],
|
|
116
|
+
});
|
|
117
|
+
if (!bumped) {
|
|
118
|
+
await this.close();
|
|
119
|
+
this.emit('disconnected', 'Lost locks, possible main thread freeze');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
async close() {
|
|
123
|
+
if (this.pool)
|
|
124
|
+
await this.pool.close();
|
|
125
|
+
if (this.manager)
|
|
126
|
+
await this.manager.close();
|
|
127
|
+
this.queues = {};
|
|
128
|
+
this.pool = undefined;
|
|
129
|
+
this.disconnected = true;
|
|
130
|
+
await this.redis.quit().catch(() => { });
|
|
131
|
+
}
|
|
132
|
+
async dispatch(key, id, runAt,
|
|
133
|
+
// biome-ignore lint/suspicious/noExplicitAny: Data is any serializable value
|
|
134
|
+
data, updateData, updateRunAt, resetCounts) {
|
|
135
|
+
await this.redis.fCall('queasy_dispatch', {
|
|
136
|
+
keys: [key],
|
|
137
|
+
arguments: [
|
|
138
|
+
id,
|
|
139
|
+
String(runAt),
|
|
140
|
+
JSON.stringify(data),
|
|
141
|
+
String(updateData),
|
|
142
|
+
String(updateRunAt),
|
|
143
|
+
String(resetCounts),
|
|
144
|
+
],
|
|
145
|
+
});
|
|
146
|
+
this.emit('dispatch', key, { id, runAt, data, updateData, updateRunAt, resetCounts });
|
|
147
|
+
}
|
|
148
|
+
async cancel(key, id) {
|
|
149
|
+
const result = await this.redis.fCall('queasy_cancel', {
|
|
150
|
+
keys: [key],
|
|
151
|
+
arguments: [id],
|
|
152
|
+
});
|
|
153
|
+
this.emit('cancel', key, id);
|
|
154
|
+
return result === 1;
|
|
155
|
+
}
|
|
156
|
+
async dequeue(key, count) {
|
|
157
|
+
const now = Date.now();
|
|
158
|
+
const expiry = now + HEARTBEAT_TIMEOUT;
|
|
159
|
+
const result = (await this.redis.fCall('queasy_dequeue', {
|
|
160
|
+
keys: [key],
|
|
161
|
+
arguments: [this.clientId, String(now), String(expiry), String(count)],
|
|
162
|
+
}));
|
|
163
|
+
this.scheduleBump(key);
|
|
164
|
+
const jobs = result.map((jobArray) => parseJob(jobArray)).filter(Boolean);
|
|
165
|
+
for (const job of jobs)
|
|
166
|
+
this.emit('dequeue', key, job);
|
|
167
|
+
return jobs;
|
|
168
|
+
}
|
|
169
|
+
async finish(key, jobId) {
|
|
170
|
+
await this.redis.fCall('queasy_finish', {
|
|
171
|
+
keys: [key],
|
|
172
|
+
arguments: [jobId, this.clientId, String(Date.now())],
|
|
173
|
+
});
|
|
174
|
+
this.emit('finish', key, jobId);
|
|
175
|
+
}
|
|
176
|
+
async fail(key, failkey, jobId,
|
|
177
|
+
// biome-ignore lint/suspicious/noExplicitAny: Fail job data is any serializable value
|
|
178
|
+
failJobData) {
|
|
179
|
+
await this.redis.fCall('queasy_fail', {
|
|
180
|
+
keys: [key, failkey],
|
|
181
|
+
arguments: [
|
|
182
|
+
jobId,
|
|
183
|
+
this.clientId,
|
|
184
|
+
generateId(),
|
|
185
|
+
JSON.stringify(failJobData),
|
|
186
|
+
String(Date.now()),
|
|
187
|
+
],
|
|
188
|
+
});
|
|
189
|
+
this.emit('fail', key, jobId);
|
|
190
|
+
}
|
|
191
|
+
async retry(key, jobId, retryAt) {
|
|
192
|
+
await this.redis.fCall('queasy_retry', {
|
|
193
|
+
keys: [key],
|
|
194
|
+
arguments: [jobId, this.clientId, String(retryAt), String(Date.now())],
|
|
195
|
+
});
|
|
196
|
+
this.emit('retry', key, jobId);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { HandlerOptions, JobUpdateOptions } from './types.ts';
|
|
2
|
+
export declare const DEFAULT_RETRY_OPTIONS: Required<HandlerOptions>;
|
|
3
|
+
export declare const DEFAULT_UPDATE_OPTIONS: Required<JobUpdateOptions>;
|
|
4
|
+
export declare const FAILJOB_RETRY_OPTIONS: Required<HandlerOptions>;
|
|
5
|
+
export declare const LUA_FUNCTIONS_VERSION = "1.0.1";
|
|
6
|
+
export declare const HEARTBEAT_INTERVAL = 5000;
|
|
7
|
+
export declare const HEARTBEAT_TIMEOUT = 10000;
|
|
8
|
+
export declare const WORKER_CAPACITY = 10;
|
|
9
|
+
export declare const DEQUEUE_INTERVAL = 100;
|
|
10
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnE,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,cAAc,CAQ1D,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAAC,gBAAgB,CAI7D,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,cAAc,CAQ1D,CAAC;AAEF,eAAO,MAAM,qBAAqB,UAAU,CAAC;AAC7C,eAAO,MAAM,kBAAkB,OAAO,CAAC;AACvC,eAAO,MAAM,iBAAiB,QAAQ,CAAC;AACvC,eAAO,MAAM,eAAe,KAAK,CAAC;AAClC,eAAO,MAAM,gBAAgB,MAAM,CAAC"}
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/** @typedef {import('./types').HandlerOptions} HandlerOptions */
|
|
2
|
-
/** @typedef {import('./types').JobUpdateOptions} JobUpdateOptions */
|
|
3
|
-
|
|
4
|
-
/** @type {Required<HandlerOptions>} */
|
|
5
1
|
export const DEFAULT_RETRY_OPTIONS = {
|
|
6
2
|
maxRetries: 10,
|
|
7
3
|
maxStalls: 3,
|
|
@@ -11,15 +7,11 @@ export const DEFAULT_RETRY_OPTIONS = {
|
|
|
11
7
|
timeout: 60_000, // 1 minute
|
|
12
8
|
priority: 100,
|
|
13
9
|
};
|
|
14
|
-
|
|
15
|
-
/** @type {Required<JobUpdateOptions>} */
|
|
16
10
|
export const DEFAULT_UPDATE_OPTIONS = {
|
|
17
11
|
updateData: true,
|
|
18
12
|
updateRunAt: true,
|
|
19
13
|
resetCounts: false,
|
|
20
14
|
};
|
|
21
|
-
|
|
22
|
-
/** @type {Required<HandlerOptions>} */
|
|
23
15
|
export const FAILJOB_RETRY_OPTIONS = {
|
|
24
16
|
maxRetries: 100,
|
|
25
17
|
maxStalls: 3,
|
|
@@ -29,9 +21,9 @@ export const FAILJOB_RETRY_OPTIONS = {
|
|
|
29
21
|
timeout: 60_000,
|
|
30
22
|
priority: 100,
|
|
31
23
|
};
|
|
32
|
-
|
|
33
24
|
export const LUA_FUNCTIONS_VERSION = '1.0.1';
|
|
34
25
|
export const HEARTBEAT_INTERVAL = 5000; // 5 seconds
|
|
35
26
|
export const HEARTBEAT_TIMEOUT = 10000; // 10 seconds
|
|
36
27
|
export const WORKER_CAPACITY = 10;
|
|
37
28
|
export const DEQUEUE_INTERVAL = 100; // ms
|
|
29
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,qBAAqB,GAA6B;IAC3D,UAAU,EAAE,EAAE;IACd,SAAS,EAAE,CAAC;IACZ,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,OAAO,EAAE,YAAY;IACjC,IAAI,EAAE,EAAE;IACR,OAAO,EAAE,MAAM,EAAE,WAAW;IAC5B,QAAQ,EAAE,GAAG;CAChB,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAA+B;IAC9D,UAAU,EAAE,IAAI;IAChB,WAAW,EAAE,IAAI;IACjB,WAAW,EAAE,KAAK;CACrB,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAA6B;IAC3D,UAAU,EAAE,GAAG;IACf,SAAS,EAAE,CAAC;IACZ,UAAU,EAAE,MAAM;IAClB,UAAU,EAAE,OAAO,EAAE,aAAa;IAClC,IAAI,EAAE,CAAC;IACP,OAAO,EAAE,MAAM;IACf,QAAQ,EAAE,GAAG;CAChB,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,OAAO,CAAC;AAC7C,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC,CAAC,YAAY;AACpD,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC,CAAC,aAAa;AACrD,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAClC,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,CAAC,CAAC,KAAK"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,cAAe,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM;CAI9B;AAED,qBAAa,UAAW,SAAQ,KAAK;gBACrB,OAAO,EAAE,MAAM;CAI9B"}
|
package/{src → dist}/errors.js
RENAMED
|
@@ -1,25 +1,13 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Error thrown to indicate a job should not be retried
|
|
3
|
-
*/
|
|
4
1
|
export class PermanentError extends Error {
|
|
5
|
-
/**
|
|
6
|
-
* @param {string} message - Error message
|
|
7
|
-
*/
|
|
8
2
|
constructor(message) {
|
|
9
3
|
super(message);
|
|
10
4
|
this.name = 'PermanentError';
|
|
11
5
|
}
|
|
12
6
|
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Error indicating a job stalled (worker stopped sending heartbeats)
|
|
16
|
-
*/
|
|
17
7
|
export class StallError extends Error {
|
|
18
|
-
/**
|
|
19
|
-
* @param {string} message - Error message
|
|
20
|
-
*/
|
|
21
8
|
constructor(message) {
|
|
22
9
|
super(message);
|
|
23
10
|
this.name = 'StallError';
|
|
24
11
|
}
|
|
25
12
|
}
|
|
13
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,cAAe,SAAQ,KAAK;IACrC,YAAY,OAAe;QACvB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IACjC,CAAC;CACJ;AAED,MAAM,OAAO,UAAW,SAAQ,KAAK;IACjC,YAAY,OAAe;QACvB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC7B,CAAC;CACJ"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Pool } from './pool.ts';
|
|
2
|
+
import type { Queue } from './queue.ts';
|
|
3
|
+
interface QueueEntry {
|
|
4
|
+
queue: Queue;
|
|
5
|
+
lastDequeuedAt: number;
|
|
6
|
+
isBusy: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare class Manager {
|
|
9
|
+
pool: Pool;
|
|
10
|
+
queues: QueueEntry[];
|
|
11
|
+
timer: NodeJS.Timeout | null;
|
|
12
|
+
busyCount: number;
|
|
13
|
+
constructor(pool: Pool);
|
|
14
|
+
addQueue(queue: Queue): void;
|
|
15
|
+
next(): Promise<void>;
|
|
16
|
+
close(): void;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,UAAU,UAAU;IAChB,KAAK,EAAE,KAAK,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;CACnB;AAED,qBAAa,OAAO;IAChB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;gBAEN,IAAI,EAAE,IAAI;IAOtB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAMtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA6B3B,KAAK,IAAI,IAAI;CAGhB"}
|
package/dist/manager.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { DEQUEUE_INTERVAL } from "./constants.js";
|
|
2
|
+
export class Manager {
|
|
3
|
+
pool;
|
|
4
|
+
queues;
|
|
5
|
+
timer;
|
|
6
|
+
busyCount;
|
|
7
|
+
constructor(pool) {
|
|
8
|
+
this.pool = pool;
|
|
9
|
+
this.queues = [];
|
|
10
|
+
this.timer = null;
|
|
11
|
+
this.busyCount = 0;
|
|
12
|
+
}
|
|
13
|
+
addQueue(queue) {
|
|
14
|
+
this.queues.unshift({ queue, lastDequeuedAt: 0, isBusy: false });
|
|
15
|
+
this.busyCount += 1;
|
|
16
|
+
this.next();
|
|
17
|
+
}
|
|
18
|
+
async next() {
|
|
19
|
+
const entry = this.queues.shift();
|
|
20
|
+
if (!entry)
|
|
21
|
+
return;
|
|
22
|
+
if (this.timer) {
|
|
23
|
+
clearTimeout(this.timer);
|
|
24
|
+
this.timer = null;
|
|
25
|
+
}
|
|
26
|
+
const size = entry.queue.handlerOptions.size;
|
|
27
|
+
if (this.pool.capacity < size)
|
|
28
|
+
return;
|
|
29
|
+
const batchSize = Math.max(1, Math.floor(this.pool.capacity / this.busyCount / size));
|
|
30
|
+
entry.lastDequeuedAt = Date.now();
|
|
31
|
+
const { count } = await entry.queue.dequeue(batchSize);
|
|
32
|
+
const nowBusy = count >= batchSize;
|
|
33
|
+
this.busyCount += Number(nowBusy) - Number(entry.isBusy);
|
|
34
|
+
entry.isBusy = nowBusy;
|
|
35
|
+
this.queues.push(entry);
|
|
36
|
+
this.queues.sort(compareQueueEntries);
|
|
37
|
+
if (!this.timer && this.queues.length) {
|
|
38
|
+
const { isBusy, lastDequeuedAt } = this.queues[0];
|
|
39
|
+
const delay = isBusy ? 0 : Math.max(0, lastDequeuedAt - Date.now() + DEQUEUE_INTERVAL);
|
|
40
|
+
this.timer = setTimeout(() => this.next(), delay);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
close() {
|
|
44
|
+
if (this.timer)
|
|
45
|
+
clearTimeout(this.timer);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function compareQueueEntries(a, b) {
|
|
49
|
+
if (a.isBusy > b.isBusy)
|
|
50
|
+
return -1;
|
|
51
|
+
if (a.isBusy < b.isBusy)
|
|
52
|
+
return 1;
|
|
53
|
+
if (a.queue.handlerOptions.priority > b.queue.handlerOptions.priority)
|
|
54
|
+
return 1;
|
|
55
|
+
if (a.queue.handlerOptions.priority < b.queue.handlerOptions.priority)
|
|
56
|
+
return -1;
|
|
57
|
+
if (a.lastDequeuedAt > b.lastDequeuedAt)
|
|
58
|
+
return -1;
|
|
59
|
+
if (a.lastDequeuedAt < b.lastDequeuedAt)
|
|
60
|
+
return 1;
|
|
61
|
+
if (a.queue.handlerOptions.size > b.queue.handlerOptions.size)
|
|
62
|
+
return 1;
|
|
63
|
+
if (a.queue.handlerOptions.size < b.queue.handlerOptions.size)
|
|
64
|
+
return -1;
|
|
65
|
+
return 0;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"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"}
|
package/dist/pool.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Worker } from 'node:worker_threads';
|
|
2
|
+
import type { DoneMessage, Job } from './types.ts';
|
|
3
|
+
interface WorkerEntry {
|
|
4
|
+
worker: Worker;
|
|
5
|
+
capacity: number;
|
|
6
|
+
id: string;
|
|
7
|
+
jobCount: number;
|
|
8
|
+
stalledJobs: Set<string>;
|
|
9
|
+
}
|
|
10
|
+
interface JobEntry {
|
|
11
|
+
resolve: (value: DoneMessage) => void;
|
|
12
|
+
reject: (reason: DoneMessage) => void;
|
|
13
|
+
size: number;
|
|
14
|
+
timer: NodeJS.Timeout;
|
|
15
|
+
}
|
|
16
|
+
export declare class Pool {
|
|
17
|
+
workers: Set<WorkerEntry>;
|
|
18
|
+
activeJobs: Map<string, JobEntry>;
|
|
19
|
+
capacity: number;
|
|
20
|
+
constructor(targetCount?: number | null);
|
|
21
|
+
createWorker(): void;
|
|
22
|
+
handleWorkerMessage(workerEntry: WorkerEntry, message: DoneMessage): void;
|
|
23
|
+
handleTimeout(workerEntry: WorkerEntry, jobId: string): void;
|
|
24
|
+
terminateIfEmpty({ stalledJobs, jobCount, worker }: WorkerEntry): Promise<void>;
|
|
25
|
+
process(handlerPath: string, job: Job, size: number, timeout: number): Promise<DoneMessage>;
|
|
26
|
+
close(): Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=pool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAGnD,UAAU,WAAW;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC5B;AAED,UAAU,QAAQ;IACd,OAAO,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACtC,MAAM,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC;CACzB;AAED,qBAAa,IAAI;IACb,OAAO,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;IAC1B,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC;gBAEL,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IASvC,YAAY,IAAI,IAAI;IAgBpB,mBAAmB,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI;IAoBzE,aAAa,CAAC,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAStD,gBAAgB,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAerF,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAmBrF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAc/B"}
|