Skip to content

Commit e573010

Browse files
authored
feat(backoff): add option to specify options for custom backoff strategy
1 parent 0ba93e7 commit e573010

File tree

4 files changed

+87
-4
lines changed

4 files changed

+87
-4
lines changed

PATTERNS.md

+35
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,41 @@ myQueue.add({foo: 'bar'}, {
166166
});
167167
```
168168

169+
You may specify options for your strategy:
170+
```js
171+
var Queue = require('bull');
172+
173+
var myQueue = new Queue("Server B", {
174+
settings: {
175+
backoffStrategies: {
176+
// truncated binary exponential backoff
177+
binaryExponential: function (attemptsMade, err, options) {
178+
// Options can be undefined, you need to handle it by yourself
179+
if (!options) {
180+
options = {}
181+
}
182+
var delay = options.delay || 1000;
183+
var truncate = options.truncate || 1000;
184+
console.error({attemptsMade, err, options});
185+
return Math.round(Math.random() * (Math.pow(2, Math.max(attemptsMade, truncate)) - 1) * delay)
186+
}
187+
}
188+
}
189+
});
190+
191+
myQueue.add({foo: 'bar'}, {
192+
attempts: 10,
193+
backoff: {
194+
type: 'binaryExponential',
195+
options: {
196+
delay: 500,
197+
truncate: 5
198+
}
199+
}
200+
});
201+
202+
```
203+
169204
You may base your backoff strategy on the error that the job throws:
170205
```js
171206
const Queue = require('bull');

lib/backoffs.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,15 @@ module.exports = {
4242
}
4343
},
4444

45-
calculate(backoff, attemptsMade, customStrategies, err) {
45+
calculate(backoff, attemptsMade, customStrategies, err, strategyOptions) {
4646
if (backoff) {
47-
const strategy = lookupStrategy(backoff, customStrategies);
47+
const strategy = lookupStrategy(
48+
backoff,
49+
customStrategies,
50+
strategyOptions
51+
);
4852

49-
return strategy(attemptsMade, err);
53+
return strategy(attemptsMade, err, strategyOptions);
5054
}
5155
}
5256
};

lib/job.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ Job.prototype.moveToFailed = async function(err, ignoreLock) {
274274
err = err || { message: 'Unknown reason' };
275275

276276
this.failedReason = err.message;
277+
277278
await this.queue.isReady();
278279

279280
let command;
@@ -288,7 +289,8 @@ Job.prototype.moveToFailed = async function(err, ignoreLock) {
288289
this.opts.backoff,
289290
this.attemptsMade,
290291
this.queue.settings.backoffStrategies,
291-
err
292+
err,
293+
_.get(this, 'opts.backoff.options', null)
292294
);
293295

294296
if (delay === -1) {

test/test_queue.js

+42
Original file line numberDiff line numberDiff line change
@@ -2273,6 +2273,48 @@ describe('Queue', () => {
22732273
});
22742274
});
22752275

2276+
it('should pass strategy options to custom backoff', function(done) {
2277+
this.timeout(12000);
2278+
queue = utils.buildQueue('test retries and backoffs', {
2279+
settings: {
2280+
backoffStrategies: {
2281+
custom(attemptsMade, err, strategyOptions) {
2282+
expect(strategyOptions.id).to.be.equal('FOO42');
2283+
return attemptsMade * 1000;
2284+
}
2285+
}
2286+
}
2287+
});
2288+
let start;
2289+
queue.isReady().then(() => {
2290+
queue.process((job, jobDone) => {
2291+
if (job.attemptsMade < 2) {
2292+
throw new Error('Not yet!');
2293+
}
2294+
jobDone();
2295+
});
2296+
2297+
start = Date.now();
2298+
queue.add(
2299+
{ foo: 'bar' },
2300+
{
2301+
attempts: 3,
2302+
backoff: {
2303+
type: 'custom',
2304+
options: {
2305+
id: 'FOO42'
2306+
}
2307+
}
2308+
}
2309+
);
2310+
});
2311+
queue.on('completed', () => {
2312+
const elapse = Date.now() - start;
2313+
expect(elapse).to.be.greaterThan(3000);
2314+
done();
2315+
});
2316+
});
2317+
22762318
it('should not retry a job if the custom backoff returns -1', done => {
22772319
queue = utils.buildQueue('test retries and backoffs', {
22782320
settings: {

0 commit comments

Comments
 (0)