Skip to content

Commit fcec3a9

Browse files
committed
fix: use message bus instead of signal to cancel child
1 parent 8dc35f3 commit fcec3a9

File tree

3 files changed

+76
-64
lines changed

3 files changed

+76
-64
lines changed

README.md

+10-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ Since there are a few job queue solutions, here a table comparing them to help y
5252
better suits your needs.
5353

5454
| Feature | Bull | Bee | Agenda | AgendaTS |
55-
|:---------------------------| :-------------: | :------: | :----: | :------: |
55+
| :------------------------- | :-------------: | :------: | :----: | :------: |
5656
| Backend | redis | redis | mongo | mongo |
5757
| Priorities || |||
5858
| Concurrency |||||
@@ -1148,6 +1148,14 @@ childWorker.ts
11481148
```ts
11491149
import 'reflect-metadata';
11501150

1151+
process.on('message', message => {
1152+
if (message === 'cancel') {
1153+
process.exit(2);
1154+
} else {
1155+
console.log('got message', message);
1156+
}
1157+
});
1158+
11511159
(async () => {
11521160
const mongooseConnection = /** connect to database */
11531161

@@ -1204,6 +1212,7 @@ import 'reflect-metadata';
12041212
process.exit(1);
12051213
});
12061214

1215+
12071216
```
12081217

12091218
Ensure to only define job definitions during this step, otherwise you create some

src/Job.ts

+58-63
Original file line numberDiff line numberDiff line change
@@ -360,73 +360,68 @@ export class Job<DATA = unknown | void> {
360360
}
361361
const { forkHelper } = this.agenda;
362362

363-
// console.log('location', location);
364-
let controller: AbortController | undefined;
365-
let signal: AbortSignal | undefined;
366-
if (typeof AbortController !== 'undefined') {
367-
controller = new AbortController();
368-
({ signal } = controller);
369-
} else {
370-
console.warn('AbortController not supported!');
371-
}
372-
373-
await new Promise<void>((resolve, reject) => {
374-
let stillRunning = true;
375-
376-
const child = fork(
377-
forkHelper.path,
378-
[
379-
this.attrs.name,
380-
this.attrs._id!.toString(),
381-
this.agenda.definitions[this.attrs.name].filePath || ''
382-
],
383-
{
384-
...forkHelper.options,
385-
signal
386-
}
387-
);
388-
389-
child.on('close', code => {
390-
stillRunning = false;
391-
if (code) {
392-
console.info(
393-
'fork parameters',
394-
forkHelper,
363+
let stillRunning = true;
364+
try {
365+
await new Promise<void>((resolve, reject) => {
366+
const child = fork(
367+
forkHelper.path,
368+
[
395369
this.attrs.name,
396-
this.attrs._id,
397-
this.agenda.definitions[this.attrs.name].filePath
398-
);
399-
const error = new Error(`child process exited with code: ${code}`);
400-
console.warn(error.message);
401-
reject(error);
402-
} else {
403-
resolve();
404-
}
405-
});
406-
child.on('message', message => {
407-
// console.log(`Message from child.js: ${message}`, JSON.stringify(message));
408-
if (typeof message === 'string') {
409-
try {
410-
reject(JSON.parse(message));
411-
} catch (errJson) {
412-
reject(message);
370+
this.attrs._id!.toString(),
371+
this.agenda.definitions[this.attrs.name].filePath || ''
372+
],
373+
forkHelper.options
374+
);
375+
376+
child.on('close', code => {
377+
stillRunning = false;
378+
if (code) {
379+
console.info(
380+
'fork parameters',
381+
forkHelper,
382+
this.attrs.name,
383+
this.attrs._id,
384+
this.agenda.definitions[this.attrs.name].filePath
385+
);
386+
const error = new Error(`child process exited with code: ${code}`);
387+
console.warn(error.message);
388+
reject(error);
389+
} else {
390+
resolve();
413391
}
414-
} else {
415-
reject(message);
416-
}
417-
});
418-
419-
// check if job is still alive
420-
const checkCancel = () =>
421-
setTimeout(() => {
422-
if (this.canceled) {
423-
controller?.abort(); // Stops the child process
424-
} else if (stillRunning) {
425-
setTimeout(checkCancel, 10000);
392+
});
393+
child.on('message', message => {
394+
// console.log(`Message from child.js: ${message}`, JSON.stringify(message));
395+
if (typeof message === 'string') {
396+
try {
397+
reject(JSON.parse(message));
398+
} catch (errJson) {
399+
reject(message);
400+
}
401+
} else {
402+
reject(message);
426403
}
427404
});
428-
checkCancel();
429-
});
405+
406+
// check if job is still alive
407+
const checkCancel = () =>
408+
setTimeout(() => {
409+
if (this.canceled) {
410+
try {
411+
child.send('cancel');
412+
console.info('canceled child', this.attrs.name, this.attrs._id);
413+
} catch (err) {
414+
console.log('cannot send cancel to child');
415+
}
416+
} else if (stillRunning) {
417+
setTimeout(checkCancel, 10000);
418+
}
419+
});
420+
checkCancel();
421+
});
422+
} finally {
423+
stillRunning = false;
424+
}
430425
} else {
431426
await this.runJob();
432427
}

test/helpers/forkHelper.ts

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
import { Agenda } from '../../src';
22

3+
process.on('message', message => {
4+
if (message === 'cancel') {
5+
process.exit(2);
6+
} else {
7+
console.log('got message', message);
8+
}
9+
});
10+
311
(async () => {
412
/** do other required initializations */
513

0 commit comments

Comments
 (0)