@c9up/bay 0.1.11 → 0.1.12
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/dist/QueueManager.d.ts +0 -4
- package/dist/QueueManager.d.ts.map +1 -1
- package/dist/QueueManager.js +26 -26
- package/dist/QueueManager.js.map +1 -1
- package/package.json +1 -1
- package/src/QueueManager.ts +29 -27
package/dist/QueueManager.d.ts
CHANGED
|
@@ -37,10 +37,6 @@ export interface QueueDriver {
|
|
|
37
37
|
}
|
|
38
38
|
export declare class QueueManager {
|
|
39
39
|
#private;
|
|
40
|
-
private driver;
|
|
41
|
-
private handlers;
|
|
42
|
-
private running;
|
|
43
|
-
private inflightPromise;
|
|
44
40
|
constructor(driver: QueueDriver);
|
|
45
41
|
/** Register a job handler. */
|
|
46
42
|
register(name: string, handler: JobHandler | (new () => JobHandler)): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueueManager.d.ts","sourceRoot":"","sources":["../src/QueueManager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,GAAG;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,SAAS,GAAG,YAAY,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IAC1B,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,WAAW;IAC3B,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,GAAG,IAAI,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IAC3B,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,KAAK,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACzB,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACxB;;;;OAIG;IACH,YAAY,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CACjC;AAED,qBAAa,YAAY;;
|
|
1
|
+
{"version":3,"file":"QueueManager.d.ts","sourceRoot":"","sources":["../src/QueueManager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,GAAG;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,SAAS,GAAG,YAAY,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IAC1B,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,WAAW;IAC3B,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,GAAG,IAAI,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IAC3B,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,KAAK,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACzB,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACxB;;;;OAIG;IACH,YAAY,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CACjC;AAED,qBAAa,YAAY;;gBAMZ,MAAM,EAAE,WAAW;IAI/B,8BAA8B;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,CAAC,UAAU,UAAU,CAAC,GAAG,IAAI;IAI1E,mCAAmC;IAC7B,QAAQ,CACb,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAChC,OAAO,CAAC,MAAM,CAAC;IAkBlB,yCAAyC;IACnC,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IA2CpC;;;;;OAKG;IACG,IAAI,CAAC,cAAc,SAAO,EAAE,cAAc,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IA8CzE;;;;;OAKG;IACG,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAIrC,wDAAwD;IAClD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B,uBAAuB;IACjB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B,uBAAuB;IACjB,UAAU,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAIlC,sBAAsB;IAChB,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;CAG7B"}
|
package/dist/QueueManager.js
CHANGED
|
@@ -7,16 +7,16 @@
|
|
|
7
7
|
* queue.work()
|
|
8
8
|
*/
|
|
9
9
|
export class QueueManager {
|
|
10
|
-
driver;
|
|
11
|
-
handlers = new Map();
|
|
12
|
-
running = false;
|
|
13
|
-
inflightPromise = null;
|
|
10
|
+
#driver;
|
|
11
|
+
#handlers = new Map();
|
|
12
|
+
#running = false;
|
|
13
|
+
#inflightPromise = null;
|
|
14
14
|
constructor(driver) {
|
|
15
|
-
this
|
|
15
|
+
this.#driver = driver;
|
|
16
16
|
}
|
|
17
17
|
/** Register a job handler. */
|
|
18
18
|
register(name, handler) {
|
|
19
|
-
this
|
|
19
|
+
this.#handlers.set(name, handler);
|
|
20
20
|
}
|
|
21
21
|
/** Dispatch a job to the queue. */
|
|
22
22
|
async dispatch(name, payload, options) {
|
|
@@ -33,18 +33,18 @@ export class QueueManager {
|
|
|
33
33
|
status: "pending",
|
|
34
34
|
createdAt: Date.now(),
|
|
35
35
|
};
|
|
36
|
-
await this
|
|
36
|
+
await this.#driver.push(job);
|
|
37
37
|
return id;
|
|
38
38
|
}
|
|
39
39
|
/** Process the next job in the queue. */
|
|
40
40
|
async processOne() {
|
|
41
|
-
const job = await this
|
|
41
|
+
const job = await this.#driver.pop();
|
|
42
42
|
if (!job)
|
|
43
43
|
return false;
|
|
44
|
-
const handlerOrClass = this
|
|
44
|
+
const handlerOrClass = this.#handlers.get(job.name);
|
|
45
45
|
if (!handlerOrClass) {
|
|
46
46
|
process.stderr.write(`QueueManager: no handler registered for job '${job.name}'\n`);
|
|
47
|
-
await this
|
|
47
|
+
await this.#driver.fail(job, `No handler registered for job: ${job.name}`);
|
|
48
48
|
return true;
|
|
49
49
|
}
|
|
50
50
|
const handler = typeof handlerOrClass === "function"
|
|
@@ -56,18 +56,18 @@ export class QueueManager {
|
|
|
56
56
|
try {
|
|
57
57
|
await handler.handle(job.payload);
|
|
58
58
|
job.status = "completed";
|
|
59
|
-
await this
|
|
59
|
+
await this.#driver.complete(job);
|
|
60
60
|
}
|
|
61
61
|
catch (err) {
|
|
62
62
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
63
63
|
if (job.attempts < job.maxAttempts) {
|
|
64
64
|
job.status = "pending";
|
|
65
|
-
await this
|
|
65
|
+
await this.#driver.retry(job);
|
|
66
66
|
}
|
|
67
67
|
else {
|
|
68
68
|
job.status = "failed";
|
|
69
69
|
job.error = errorMsg;
|
|
70
|
-
await this
|
|
70
|
+
await this.#driver.fail(job, errorMsg);
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
return true;
|
|
@@ -85,16 +85,16 @@ export class QueueManager {
|
|
|
85
85
|
if (recoverStaleMs <= 0) {
|
|
86
86
|
throw new Error("recoverStaleMs must be positive");
|
|
87
87
|
}
|
|
88
|
-
if (this
|
|
88
|
+
if (this.#running) {
|
|
89
89
|
throw new Error("QueueManager is already running");
|
|
90
90
|
}
|
|
91
|
-
this
|
|
91
|
+
this.#running = true;
|
|
92
92
|
await this.#tryRecoverStale();
|
|
93
93
|
let lastRecover = Date.now();
|
|
94
|
-
while (this
|
|
94
|
+
while (this.#running) {
|
|
95
95
|
try {
|
|
96
|
-
this
|
|
97
|
-
const processed = await this
|
|
96
|
+
this.#inflightPromise = this.processOne();
|
|
97
|
+
const processed = await this.#inflightPromise;
|
|
98
98
|
if (!processed) {
|
|
99
99
|
await new Promise((r) => setTimeout(r, pollIntervalMs));
|
|
100
100
|
}
|
|
@@ -104,9 +104,9 @@ export class QueueManager {
|
|
|
104
104
|
await new Promise((r) => setTimeout(r, pollIntervalMs));
|
|
105
105
|
}
|
|
106
106
|
finally {
|
|
107
|
-
this
|
|
107
|
+
this.#inflightPromise = null;
|
|
108
108
|
}
|
|
109
|
-
if (this
|
|
109
|
+
if (this.#running && Date.now() - lastRecover >= recoverStaleMs) {
|
|
110
110
|
await this.#tryRecoverStale();
|
|
111
111
|
lastRecover = Date.now();
|
|
112
112
|
}
|
|
@@ -128,26 +128,26 @@ export class QueueManager {
|
|
|
128
128
|
* Called automatically by work(); also safe to schedule manually.
|
|
129
129
|
*/
|
|
130
130
|
async recoverStale() {
|
|
131
|
-
return (await this
|
|
131
|
+
return (await this.#driver.recoverStale?.()) ?? 0;
|
|
132
132
|
}
|
|
133
133
|
/** Await the currently in-flight processOne, if any. */
|
|
134
134
|
async drain() {
|
|
135
|
-
if (this
|
|
136
|
-
await this
|
|
135
|
+
if (this.#inflightPromise) {
|
|
136
|
+
await this.#inflightPromise.catch(() => { });
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
/** Stop the worker. */
|
|
140
140
|
async stop() {
|
|
141
|
-
this
|
|
141
|
+
this.#running = false;
|
|
142
142
|
await this.drain();
|
|
143
143
|
}
|
|
144
144
|
/** Get failed jobs. */
|
|
145
145
|
async failedJobs() {
|
|
146
|
-
return this
|
|
146
|
+
return this.#driver.failed();
|
|
147
147
|
}
|
|
148
148
|
/** Get queue size. */
|
|
149
149
|
async size() {
|
|
150
|
-
return this
|
|
150
|
+
return this.#driver.size();
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
153
|
//# sourceMappingURL=QueueManager.js.map
|
package/dist/QueueManager.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueueManager.js","sourceRoot":"","sources":["../src/QueueManager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAkCH,MAAM,OAAO,YAAY;
|
|
1
|
+
{"version":3,"file":"QueueManager.js","sourceRoot":"","sources":["../src/QueueManager.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/QueueManager.ts
CHANGED
|
@@ -40,19 +40,18 @@ export interface QueueDriver {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
export class QueueManager {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
private inflightPromise: Promise<boolean> | null = null;
|
|
43
|
+
#driver: QueueDriver;
|
|
44
|
+
#handlers: Map<string, JobHandler | (new () => JobHandler)> = new Map();
|
|
45
|
+
#running = false;
|
|
46
|
+
#inflightPromise: Promise<boolean> | null = null;
|
|
48
47
|
|
|
49
48
|
constructor(driver: QueueDriver) {
|
|
50
|
-
this
|
|
49
|
+
this.#driver = driver;
|
|
51
50
|
}
|
|
52
51
|
|
|
53
52
|
/** Register a job handler. */
|
|
54
53
|
register(name: string, handler: JobHandler | (new () => JobHandler)): void {
|
|
55
|
-
this
|
|
54
|
+
this.#handlers.set(name, handler);
|
|
56
55
|
}
|
|
57
56
|
|
|
58
57
|
/** Dispatch a job to the queue. */
|
|
@@ -74,21 +73,24 @@ export class QueueManager {
|
|
|
74
73
|
status: "pending",
|
|
75
74
|
createdAt: Date.now(),
|
|
76
75
|
};
|
|
77
|
-
await this
|
|
76
|
+
await this.#driver.push(job);
|
|
78
77
|
return id;
|
|
79
78
|
}
|
|
80
79
|
|
|
81
80
|
/** Process the next job in the queue. */
|
|
82
81
|
async processOne(): Promise<boolean> {
|
|
83
|
-
const job = await this
|
|
82
|
+
const job = await this.#driver.pop();
|
|
84
83
|
if (!job) return false;
|
|
85
84
|
|
|
86
|
-
const handlerOrClass = this
|
|
85
|
+
const handlerOrClass = this.#handlers.get(job.name);
|
|
87
86
|
if (!handlerOrClass) {
|
|
88
87
|
process.stderr.write(
|
|
89
88
|
`QueueManager: no handler registered for job '${job.name}'\n`,
|
|
90
89
|
);
|
|
91
|
-
await this
|
|
90
|
+
await this.#driver.fail(
|
|
91
|
+
job,
|
|
92
|
+
`No handler registered for job: ${job.name}`,
|
|
93
|
+
);
|
|
92
94
|
return true;
|
|
93
95
|
}
|
|
94
96
|
|
|
@@ -103,16 +105,16 @@ export class QueueManager {
|
|
|
103
105
|
try {
|
|
104
106
|
await handler.handle(job.payload);
|
|
105
107
|
job.status = "completed";
|
|
106
|
-
await this
|
|
108
|
+
await this.#driver.complete(job);
|
|
107
109
|
} catch (err) {
|
|
108
110
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
109
111
|
if (job.attempts < job.maxAttempts) {
|
|
110
112
|
job.status = "pending";
|
|
111
|
-
await this
|
|
113
|
+
await this.#driver.retry(job);
|
|
112
114
|
} else {
|
|
113
115
|
job.status = "failed";
|
|
114
116
|
job.error = errorMsg;
|
|
115
|
-
await this
|
|
117
|
+
await this.#driver.fail(job, errorMsg);
|
|
116
118
|
}
|
|
117
119
|
}
|
|
118
120
|
|
|
@@ -132,16 +134,16 @@ export class QueueManager {
|
|
|
132
134
|
if (recoverStaleMs <= 0) {
|
|
133
135
|
throw new Error("recoverStaleMs must be positive");
|
|
134
136
|
}
|
|
135
|
-
if (this
|
|
137
|
+
if (this.#running) {
|
|
136
138
|
throw new Error("QueueManager is already running");
|
|
137
139
|
}
|
|
138
|
-
this
|
|
140
|
+
this.#running = true;
|
|
139
141
|
await this.#tryRecoverStale();
|
|
140
142
|
let lastRecover = Date.now();
|
|
141
|
-
while (this
|
|
143
|
+
while (this.#running) {
|
|
142
144
|
try {
|
|
143
|
-
this
|
|
144
|
-
const processed = await this
|
|
145
|
+
this.#inflightPromise = this.processOne();
|
|
146
|
+
const processed = await this.#inflightPromise;
|
|
145
147
|
if (!processed) {
|
|
146
148
|
await new Promise((r) => setTimeout(r, pollIntervalMs));
|
|
147
149
|
}
|
|
@@ -151,9 +153,9 @@ export class QueueManager {
|
|
|
151
153
|
);
|
|
152
154
|
await new Promise((r) => setTimeout(r, pollIntervalMs));
|
|
153
155
|
} finally {
|
|
154
|
-
this
|
|
156
|
+
this.#inflightPromise = null;
|
|
155
157
|
}
|
|
156
|
-
if (this
|
|
158
|
+
if (this.#running && Date.now() - lastRecover >= recoverStaleMs) {
|
|
157
159
|
await this.#tryRecoverStale();
|
|
158
160
|
lastRecover = Date.now();
|
|
159
161
|
}
|
|
@@ -178,29 +180,29 @@ export class QueueManager {
|
|
|
178
180
|
* Called automatically by work(); also safe to schedule manually.
|
|
179
181
|
*/
|
|
180
182
|
async recoverStale(): Promise<number> {
|
|
181
|
-
return (await this
|
|
183
|
+
return (await this.#driver.recoverStale?.()) ?? 0;
|
|
182
184
|
}
|
|
183
185
|
|
|
184
186
|
/** Await the currently in-flight processOne, if any. */
|
|
185
187
|
async drain(): Promise<void> {
|
|
186
|
-
if (this
|
|
187
|
-
await this
|
|
188
|
+
if (this.#inflightPromise) {
|
|
189
|
+
await this.#inflightPromise.catch(() => {});
|
|
188
190
|
}
|
|
189
191
|
}
|
|
190
192
|
|
|
191
193
|
/** Stop the worker. */
|
|
192
194
|
async stop(): Promise<void> {
|
|
193
|
-
this
|
|
195
|
+
this.#running = false;
|
|
194
196
|
await this.drain();
|
|
195
197
|
}
|
|
196
198
|
|
|
197
199
|
/** Get failed jobs. */
|
|
198
200
|
async failedJobs(): Promise<Job[]> {
|
|
199
|
-
return this
|
|
201
|
+
return this.#driver.failed();
|
|
200
202
|
}
|
|
201
203
|
|
|
202
204
|
/** Get queue size. */
|
|
203
205
|
async size(): Promise<number> {
|
|
204
|
-
return this
|
|
206
|
+
return this.#driver.size();
|
|
205
207
|
}
|
|
206
208
|
}
|