bunqueue 1.6.2 → 1.6.3

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.
@@ -20,10 +20,12 @@
20
20
  */
21
21
  export { Queue } from './queue';
22
22
  export { Worker } from './worker';
23
+ export { SandboxedWorker } from './sandboxedWorker';
23
24
  export { QueueEvents } from './events';
24
25
  export { QueueGroup } from './queueGroup';
25
26
  export { FlowProducer } from './flow';
26
27
  export { shutdownManager } from './manager';
27
28
  export type { Job, JobOptions, QueueOptions, WorkerOptions, Processor, StallConfig, DlqConfig, DlqEntry, DlqStats, DlqFilter, FailureReason, } from './types';
28
29
  export type { FlowStep, FlowResult } from './flow';
30
+ export type { SandboxedWorkerOptions } from './sandboxedWorker';
29
31
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,YAAY,EACV,GAAG,EACH,UAAU,EACV,YAAY,EACZ,aAAa,EACb,SAAS,EACT,WAAW,EACX,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,YAAY,EACV,GAAG,EACH,UAAU,EACV,YAAY,EACZ,aAAa,EACb,SAAS,EACT,WAAW,EACX,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACnD,YAAY,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -20,6 +20,7 @@
20
20
  */
21
21
  export { Queue } from './queue';
22
22
  export { Worker } from './worker';
23
+ export { SandboxedWorker } from './sandboxedWorker';
23
24
  export { QueueEvents } from './events';
24
25
  export { QueueGroup } from './queueGroup';
25
26
  export { FlowProducer } from './flow';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC"}
@@ -2,6 +2,8 @@
2
2
  * Shared QueueManager singleton
3
3
  */
4
4
  import { QueueManager } from '../application/queueManager';
5
+ /** Shared manager type export */
6
+ export type SharedManager = QueueManager;
5
7
  /** Get shared QueueManager instance */
6
8
  export declare function getSharedManager(): QueueManager;
7
9
  /** Shutdown shared manager */
@@ -1 +1 @@
1
- {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/client/manager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAI3D,uCAAuC;AACvC,wBAAgB,gBAAgB,IAAI,YAAY,CAG/C;AAED,8BAA8B;AAC9B,wBAAgB,eAAe,IAAI,IAAI,CAKtC"}
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/client/manager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,iCAAiC;AACjC,MAAM,MAAM,aAAa,GAAG,YAAY,CAAC;AAIzC,uCAAuC;AACvC,wBAAgB,gBAAgB,IAAI,YAAY,CAG/C;AAED,8BAA8B;AAC9B,wBAAgB,eAAe,IAAI,IAAI,CAKtC"}
@@ -1 +1 @@
1
- {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/client/manager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,IAAI,QAAQ,GAAwB,IAAI,CAAC;AAEzC,uCAAuC;AACvC,MAAM,UAAU,gBAAgB;IAC9B,QAAQ,KAAK,IAAI,YAAY,EAAE,CAAC;IAChC,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,8BAA8B;AAC9B,MAAM,UAAU,eAAe;IAC7B,IAAI,QAAQ,EAAE,CAAC;QACb,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACpB,QAAQ,GAAG,IAAI,CAAC;IAClB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/client/manager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAK3D,IAAI,QAAQ,GAAwB,IAAI,CAAC;AAEzC,uCAAuC;AACvC,MAAM,UAAU,gBAAgB;IAC9B,QAAQ,KAAK,IAAI,YAAY,EAAE,CAAC;IAChC,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,8BAA8B;AAC9B,MAAM,UAAU,eAAe;IAC7B,IAAI,QAAQ,EAAE,CAAC;QACb,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACpB,QAAQ,GAAG,IAAI,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Sandboxed Worker
3
+ * Runs job processors in isolated Bun Worker processes
4
+ */
5
+ import { type SharedManager } from './manager';
6
+ /** Sandboxed worker configuration */
7
+ export interface SandboxedWorkerOptions {
8
+ /** Path to processor file (must export default async function) */
9
+ processor: string;
10
+ /** Number of worker processes (default: 1) */
11
+ concurrency?: number;
12
+ /** Max memory per worker in MB - uses smol mode if <= 64 (default: 256) */
13
+ maxMemory?: number;
14
+ /** Job timeout in ms (default: 30000) */
15
+ timeout?: number;
16
+ /** Auto-restart crashed workers (default: true) */
17
+ autoRestart?: boolean;
18
+ /** Max restarts before giving up (default: 10) */
19
+ maxRestarts?: number;
20
+ /** Poll interval when no workers are idle (default: 10ms) */
21
+ pollInterval?: number;
22
+ /** Custom QueueManager (for testing, defaults to shared manager) */
23
+ manager?: SharedManager;
24
+ }
25
+ /**
26
+ * Sandboxed Worker - runs processors in isolated Bun Worker processes
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * import { Queue, SandboxedWorker } from 'bunqueue/client';
31
+ *
32
+ * const queue = new Queue('cpu-intensive');
33
+ *
34
+ * // Create processor file: processor.ts
35
+ * // export default async (job) => {
36
+ * // const result = heavyComputation(job.data);
37
+ * // return result;
38
+ * // };
39
+ *
40
+ * const worker = new SandboxedWorker('cpu-intensive', {
41
+ * processor: './processor.ts',
42
+ * concurrency: 4,
43
+ * timeout: 60000,
44
+ * });
45
+ *
46
+ * await worker.start();
47
+ * // Workers process jobs in isolated processes
48
+ * // If one crashes, others continue working
49
+ * ```
50
+ */
51
+ export declare class SandboxedWorker {
52
+ private readonly queueName;
53
+ private readonly options;
54
+ private readonly workers;
55
+ private running;
56
+ private pullPromise;
57
+ private wrapperPath;
58
+ private readonly manager;
59
+ constructor(queueName: string, options: SandboxedWorkerOptions);
60
+ /** Start the sandboxed worker pool */
61
+ start(): void;
62
+ /** Stop all workers gracefully */
63
+ stop(): Promise<void>;
64
+ /** Get worker pool stats */
65
+ getStats(): {
66
+ total: number;
67
+ busy: number;
68
+ idle: number;
69
+ restarts: number;
70
+ };
71
+ /** Create wrapper script file that loads the processor */
72
+ private createWrapperScript;
73
+ /** Spawn a single worker process */
74
+ private spawnWorker;
75
+ /** Main loop - pull jobs and dispatch to workers */
76
+ private pullLoop;
77
+ /** Dispatch job to a worker process */
78
+ private dispatchJob;
79
+ /** Handle message from worker */
80
+ private handleWorkerMessage;
81
+ /** Complete a job successfully */
82
+ private completeJob;
83
+ /** Fail a job */
84
+ private failJob;
85
+ /** Handle job timeout */
86
+ private handleJobTimeout;
87
+ /** Handle worker crash and potentially restart */
88
+ private handleWorkerCrash;
89
+ }
90
+ //# sourceMappingURL=sandboxedWorker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandboxedWorker.d.ts","sourceRoot":"","sources":["../../src/client/sandboxedWorker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAMjE,qCAAqC;AACrC,MAAM,WAAW,sBAAsB;IACrC,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6DAA6D;IAC7D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AA+BD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoD;IAC5E,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;gBAE5B,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB;IAc9D,sCAAsC;IACtC,KAAK,IAAI,IAAI;IAgBb,kCAAkC;IAC5B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA+B3B,4BAA4B;IAC5B,QAAQ,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;IAW3E,0DAA0D;IAC1D,OAAO,CAAC,mBAAmB;IA+C3B,oCAAoC;IACpC,OAAO,CAAC,WAAW;IAiCnB,oDAAoD;YACtC,QAAQ;IAkBtB,uCAAuC;IACvC,OAAO,CAAC,WAAW;IAsBnB,iCAAiC;IACjC,OAAO,CAAC,mBAAmB;IAkB3B,kCAAkC;IAClC,OAAO,CAAC,WAAW;IAiBnB,iBAAiB;IACjB,OAAO,CAAC,OAAO;IAiBf,yBAAyB;IACzB,OAAO,CAAC,gBAAgB;IAgBxB,kDAAkD;IAClD,OAAO,CAAC,iBAAiB;CAoB1B"}
@@ -0,0 +1,299 @@
1
+ /**
2
+ * Sandboxed Worker
3
+ * Runs job processors in isolated Bun Worker processes
4
+ */
5
+ import { getSharedManager } from './manager';
6
+ import { join } from 'path';
7
+ import { writeFileSync, unlinkSync, existsSync, mkdirSync } from 'fs';
8
+ import { tmpdir } from 'os';
9
+ /**
10
+ * Sandboxed Worker - runs processors in isolated Bun Worker processes
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { Queue, SandboxedWorker } from 'bunqueue/client';
15
+ *
16
+ * const queue = new Queue('cpu-intensive');
17
+ *
18
+ * // Create processor file: processor.ts
19
+ * // export default async (job) => {
20
+ * // const result = heavyComputation(job.data);
21
+ * // return result;
22
+ * // };
23
+ *
24
+ * const worker = new SandboxedWorker('cpu-intensive', {
25
+ * processor: './processor.ts',
26
+ * concurrency: 4,
27
+ * timeout: 60000,
28
+ * });
29
+ *
30
+ * await worker.start();
31
+ * // Workers process jobs in isolated processes
32
+ * // If one crashes, others continue working
33
+ * ```
34
+ */
35
+ export class SandboxedWorker {
36
+ queueName;
37
+ options;
38
+ workers = [];
39
+ running = false;
40
+ pullPromise = null;
41
+ wrapperPath = null;
42
+ manager;
43
+ constructor(queueName, options) {
44
+ this.queueName = queueName;
45
+ this.manager = options.manager ?? getSharedManager();
46
+ this.options = {
47
+ processor: options.processor,
48
+ concurrency: options.concurrency ?? 1,
49
+ maxMemory: options.maxMemory ?? 256,
50
+ timeout: options.timeout ?? 30000,
51
+ autoRestart: options.autoRestart ?? true,
52
+ maxRestarts: options.maxRestarts ?? 10,
53
+ pollInterval: options.pollInterval ?? 10,
54
+ };
55
+ }
56
+ /** Start the sandboxed worker pool */
57
+ start() {
58
+ if (this.running)
59
+ return;
60
+ this.running = true;
61
+ // Create wrapper script for workers
62
+ this.wrapperPath = this.createWrapperScript();
63
+ // Spawn worker processes
64
+ for (let i = 0; i < this.options.concurrency; i++) {
65
+ this.spawnWorker(i);
66
+ }
67
+ // Start pulling jobs
68
+ this.pullPromise = this.pullLoop();
69
+ }
70
+ /** Stop all workers gracefully */
71
+ async stop() {
72
+ this.running = false;
73
+ // Clear all timeouts
74
+ for (const wp of this.workers) {
75
+ if (wp.timeoutId) {
76
+ clearTimeout(wp.timeoutId);
77
+ }
78
+ }
79
+ // Terminate all workers
80
+ for (const wp of this.workers) {
81
+ wp.worker.terminate();
82
+ }
83
+ this.workers.length = 0;
84
+ // Wait for pull loop to finish
85
+ if (this.pullPromise) {
86
+ await this.pullPromise;
87
+ }
88
+ // Cleanup wrapper script
89
+ if (this.wrapperPath && existsSync(this.wrapperPath)) {
90
+ try {
91
+ unlinkSync(this.wrapperPath);
92
+ }
93
+ catch {
94
+ // Ignore cleanup errors
95
+ }
96
+ }
97
+ }
98
+ /** Get worker pool stats */
99
+ getStats() {
100
+ const busy = this.workers.filter((w) => w.busy).length;
101
+ const restarts = this.workers.reduce((sum, w) => sum + w.restarts, 0);
102
+ return {
103
+ total: this.workers.length,
104
+ busy,
105
+ idle: this.workers.length - busy,
106
+ restarts,
107
+ };
108
+ }
109
+ /** Create wrapper script file that loads the processor */
110
+ createWrapperScript() {
111
+ const processorPath = this.options.processor.startsWith('/')
112
+ ? this.options.processor
113
+ : join(process.cwd(), this.options.processor);
114
+ const wrapperCode = `
115
+ // Sandboxed Worker Wrapper
116
+ const processor = (await import('${processorPath}')).default;
117
+
118
+ self.onmessage = async (event) => {
119
+ const { type, job } = event.data;
120
+ if (type !== 'job') return;
121
+
122
+ try {
123
+ const result = await processor({
124
+ id: job.id,
125
+ data: job.data,
126
+ queue: job.queue,
127
+ attempts: job.attempts,
128
+ progress: (value) => {
129
+ self.postMessage({ type: 'progress', jobId: job.id, progress: value });
130
+ },
131
+ });
132
+
133
+ self.postMessage({ type: 'result', jobId: job.id, result });
134
+ } catch (err) {
135
+ self.postMessage({
136
+ type: 'error',
137
+ jobId: job.id,
138
+ error: err instanceof Error ? err.message : String(err),
139
+ });
140
+ }
141
+ };
142
+ `;
143
+ // Write to temp file
144
+ const tempDir = join(tmpdir(), 'bunqueue-workers');
145
+ if (!existsSync(tempDir)) {
146
+ mkdirSync(tempDir, { recursive: true });
147
+ }
148
+ const wrapperPath = join(tempDir, `worker-${this.queueName}-${Date.now()}.ts`);
149
+ writeFileSync(wrapperPath, wrapperCode);
150
+ return wrapperPath;
151
+ }
152
+ /** Spawn a single worker process */
153
+ spawnWorker(index) {
154
+ if (!this.wrapperPath)
155
+ return;
156
+ const worker = new Worker(this.wrapperPath, {
157
+ smol: this.options.maxMemory <= 64,
158
+ });
159
+ const wp = {
160
+ worker,
161
+ busy: false,
162
+ currentJob: null,
163
+ restarts: this.workers[index]?.restarts ?? 0,
164
+ timeoutId: null,
165
+ };
166
+ // Handle messages from worker
167
+ worker.onmessage = (event) => {
168
+ this.handleWorkerMessage(wp, event.data);
169
+ };
170
+ // Handle worker errors/crashes
171
+ worker.onerror = (error) => {
172
+ console.error(`[SandboxedWorker] Worker ${index} error:`, error.message);
173
+ this.handleWorkerCrash(wp, index);
174
+ };
175
+ if (this.workers[index]) {
176
+ this.workers[index] = wp;
177
+ }
178
+ else {
179
+ this.workers.push(wp);
180
+ }
181
+ }
182
+ /** Main loop - pull jobs and dispatch to workers */
183
+ async pullLoop() {
184
+ while (this.running) {
185
+ // Find idle worker
186
+ const idleWorker = this.workers.find((w) => !w.busy);
187
+ if (!idleWorker) {
188
+ await Bun.sleep(this.options.pollInterval);
189
+ continue;
190
+ }
191
+ // Pull job from queue using manager
192
+ const job = await this.manager.pull(this.queueName, 1000);
193
+ if (!job)
194
+ continue;
195
+ // Dispatch to worker
196
+ this.dispatchJob(idleWorker, job);
197
+ }
198
+ }
199
+ /** Dispatch job to a worker process */
200
+ dispatchJob(wp, job) {
201
+ wp.busy = true;
202
+ wp.currentJob = job;
203
+ // Set timeout
204
+ wp.timeoutId = setTimeout(() => {
205
+ this.handleJobTimeout(wp, job);
206
+ }, this.options.timeout);
207
+ // Send job to worker
208
+ const request = {
209
+ type: 'job',
210
+ job: {
211
+ id: String(job.id),
212
+ data: job.data,
213
+ queue: job.queue,
214
+ attempts: job.attempts,
215
+ },
216
+ };
217
+ wp.worker.postMessage(request);
218
+ }
219
+ /** Handle message from worker */
220
+ handleWorkerMessage(wp, msg) {
221
+ if (!wp.currentJob || msg.jobId !== String(wp.currentJob.id))
222
+ return;
223
+ switch (msg.type) {
224
+ case 'result':
225
+ this.completeJob(wp, msg.result);
226
+ break;
227
+ case 'error':
228
+ this.failJob(wp, msg.error ?? 'Unknown error');
229
+ break;
230
+ case 'progress':
231
+ if (msg.progress !== undefined) {
232
+ this.manager.updateProgress(wp.currentJob.id, msg.progress).catch(() => { });
233
+ }
234
+ break;
235
+ }
236
+ }
237
+ /** Complete a job successfully */
238
+ completeJob(wp, result) {
239
+ if (wp.timeoutId) {
240
+ clearTimeout(wp.timeoutId);
241
+ wp.timeoutId = null;
242
+ }
243
+ if (wp.currentJob) {
244
+ const jobId = wp.currentJob.id;
245
+ this.manager.ack(jobId, result).catch((err) => {
246
+ console.error(`[SandboxedWorker] Failed to ack job ${jobId}:`, err);
247
+ });
248
+ }
249
+ wp.busy = false;
250
+ wp.currentJob = null;
251
+ }
252
+ /** Fail a job */
253
+ failJob(wp, error) {
254
+ if (wp.timeoutId) {
255
+ clearTimeout(wp.timeoutId);
256
+ wp.timeoutId = null;
257
+ }
258
+ if (wp.currentJob) {
259
+ const jobId = wp.currentJob.id;
260
+ this.manager.fail(jobId, error).catch((err) => {
261
+ console.error(`[SandboxedWorker] Failed to fail job ${jobId}:`, err);
262
+ });
263
+ }
264
+ wp.busy = false;
265
+ wp.currentJob = null;
266
+ }
267
+ /** Handle job timeout */
268
+ handleJobTimeout(wp, job) {
269
+ console.error(`[SandboxedWorker] Job ${job.id} timed out after ${this.options.timeout}ms`);
270
+ // Terminate the stuck worker
271
+ wp.worker.terminate();
272
+ // Fail the job
273
+ this.manager.fail(job.id, `Job timed out after ${this.options.timeout}ms`).catch(() => { });
274
+ // Restart worker if allowed
275
+ const index = this.workers.indexOf(wp);
276
+ if (index !== -1) {
277
+ this.handleWorkerCrash(wp, index);
278
+ }
279
+ }
280
+ /** Handle worker crash and potentially restart */
281
+ handleWorkerCrash(wp, index) {
282
+ // Fail current job if any
283
+ if (wp.currentJob) {
284
+ this.manager.fail(wp.currentJob.id, 'Worker crashed').catch(() => { });
285
+ }
286
+ wp.busy = false;
287
+ wp.currentJob = null;
288
+ wp.restarts++;
289
+ // Check if we should restart
290
+ if (this.options.autoRestart && wp.restarts < this.options.maxRestarts && this.running) {
291
+ console.log(`[SandboxedWorker] Restarting worker ${index} (attempt ${wp.restarts})`);
292
+ this.spawnWorker(index);
293
+ }
294
+ else if (wp.restarts >= this.options.maxRestarts) {
295
+ console.error(`[SandboxedWorker] Worker ${index} exceeded max restarts (${this.options.maxRestarts})`);
296
+ }
297
+ }
298
+ }
299
+ //# sourceMappingURL=sandboxedWorker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandboxedWorker.js","sourceRoot":"","sources":["../../src/client/sandboxedWorker.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bunqueue",
3
- "version": "1.6.2",
3
+ "version": "1.6.3",
4
4
  "description": "High-performance job queue server written in Bun. SQLite persistence, cron scheduling, priorities, retries, DLQ, webhooks. Minimal dependencies.",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",