forked from mirrors/action-gh-release
node_modules
This commit is contained in:
parent
0e414c630a
commit
78c309ef59
555 changed files with 103819 additions and 1 deletions
148
node_modules/bottleneck/test/DLList.js
generated
vendored
Normal file
148
node_modules/bottleneck/test/DLList.js
generated
vendored
Normal file
|
@ -0,0 +1,148 @@
|
|||
var DLList = require('../lib/DLList')
|
||||
var assert = require('assert')
|
||||
var c = require('./context')({datastore: 'local'})
|
||||
|
||||
var fakeQueues = function () {
|
||||
this._length = 0
|
||||
this.incr = () => this._length++
|
||||
this.decr = () => this._length--
|
||||
this.fns = [this.incr, this.decr]
|
||||
}
|
||||
|
||||
describe('DLList', function () {
|
||||
|
||||
it('Should be created and be empty', function () {
|
||||
var queues = new fakeQueues()
|
||||
var list = new DLList()
|
||||
c.mustEqual(list.getArray().length, 0)
|
||||
})
|
||||
|
||||
it('Should be possible to append once', function () {
|
||||
var queues = new fakeQueues()
|
||||
var list = new DLList(...queues.fns)
|
||||
list.push(5)
|
||||
var arr = list.getArray()
|
||||
c.mustEqual(arr.length, 1)
|
||||
c.mustEqual(list.length, 1)
|
||||
c.mustEqual(queues._length, 1)
|
||||
c.mustEqual(arr[0], 5)
|
||||
})
|
||||
|
||||
it('Should be possible to append multiple times', function () {
|
||||
var queues = new fakeQueues()
|
||||
var list = new DLList(...queues.fns)
|
||||
list.push(5)
|
||||
list.push(6)
|
||||
var arr = list.getArray()
|
||||
c.mustEqual(arr.length, 2)
|
||||
c.mustEqual(list.length, 2)
|
||||
c.mustEqual(queues._length, 2)
|
||||
c.mustEqual(arr[0], 5)
|
||||
c.mustEqual(arr[1], 6)
|
||||
|
||||
list.push(10)
|
||||
|
||||
arr = list.getArray()
|
||||
c.mustEqual(arr.length, 3)
|
||||
c.mustEqual(list.length, 3)
|
||||
c.mustEqual(arr[0], 5)
|
||||
c.mustEqual(arr[1], 6)
|
||||
c.mustEqual(arr[2], 10)
|
||||
})
|
||||
|
||||
it('Should be possible to shift an empty list', function () {
|
||||
var queues = new fakeQueues()
|
||||
var list = new DLList(...queues.fns)
|
||||
c.mustEqual(list.length, 0)
|
||||
assert(list.shift() === undefined)
|
||||
var arr = list.getArray()
|
||||
c.mustEqual(arr.length, 0)
|
||||
c.mustEqual(list.length, 0)
|
||||
assert(list.shift() === undefined)
|
||||
arr = list.getArray()
|
||||
c.mustEqual(arr.length, 0)
|
||||
c.mustEqual(list.length, 0)
|
||||
c.mustEqual(queues._length, 0)
|
||||
})
|
||||
|
||||
it('Should be possible to append then shift once', function () {
|
||||
var queues = new fakeQueues()
|
||||
var list = new DLList(...queues.fns)
|
||||
list.push(5)
|
||||
c.mustEqual(list.length, 1)
|
||||
c.mustEqual(list.shift(), 5)
|
||||
var arr = list.getArray()
|
||||
c.mustEqual(arr.length, 0)
|
||||
c.mustEqual(list.length, 0)
|
||||
c.mustEqual(queues._length, 0)
|
||||
})
|
||||
|
||||
it('Should be possible to append then shift multiple times', function () {
|
||||
var queues = new fakeQueues()
|
||||
var list = new DLList(...queues.fns)
|
||||
list.push(5)
|
||||
c.mustEqual(list.length, 1)
|
||||
c.mustEqual(list.shift(), 5)
|
||||
c.mustEqual(list.length, 0)
|
||||
|
||||
list.push(6)
|
||||
c.mustEqual(list.length, 1)
|
||||
c.mustEqual(list.shift(), 6)
|
||||
c.mustEqual(list.length, 0)
|
||||
c.mustEqual(queues._length, 0)
|
||||
})
|
||||
|
||||
it('Should pass a full test', function () {
|
||||
var queues = new fakeQueues()
|
||||
var list = new DLList(...queues.fns)
|
||||
list.push(10)
|
||||
c.mustEqual(list.length, 1)
|
||||
list.push("11")
|
||||
c.mustEqual(list.length, 2)
|
||||
list.push(12)
|
||||
c.mustEqual(list.length, 3)
|
||||
c.mustEqual(queues._length, 3)
|
||||
|
||||
c.mustEqual(list.shift(), 10)
|
||||
c.mustEqual(list.length, 2)
|
||||
c.mustEqual(list.shift(),"11")
|
||||
c.mustEqual(list.length, 1)
|
||||
|
||||
list.push(true)
|
||||
c.mustEqual(list.length, 2)
|
||||
|
||||
var arr = list.getArray()
|
||||
c.mustEqual(arr[0], 12)
|
||||
c.mustEqual(arr[1], true)
|
||||
c.mustEqual(arr.length, 2)
|
||||
c.mustEqual(queues._length, 2)
|
||||
})
|
||||
|
||||
it('Should return the first value without shifting', function () {
|
||||
var queues = new fakeQueues()
|
||||
var list = new DLList(...queues.fns)
|
||||
assert(list.first() === undefined)
|
||||
assert(list.first() === undefined)
|
||||
|
||||
list.push(1)
|
||||
c.mustEqual(list.first(), 1)
|
||||
c.mustEqual(list.first(), 1)
|
||||
|
||||
list.push(2)
|
||||
c.mustEqual(list.first(), 1)
|
||||
c.mustEqual(list.first(), 1)
|
||||
|
||||
c.mustEqual(list.shift(), 1)
|
||||
c.mustEqual(list.first(), 2)
|
||||
c.mustEqual(list.first(), 2)
|
||||
|
||||
c.mustEqual(list.shift(), 2)
|
||||
assert(list.first() === undefined)
|
||||
assert(list.first() === undefined)
|
||||
|
||||
assert(list.first() === undefined)
|
||||
assert(list.shift() === undefined)
|
||||
assert(list.first() === undefined)
|
||||
})
|
||||
|
||||
})
|
209
node_modules/bottleneck/test/batcher.js
generated
vendored
Normal file
209
node_modules/bottleneck/test/batcher.js
generated
vendored
Normal file
|
@ -0,0 +1,209 @@
|
|||
var makeTest = require('./context')
|
||||
var Bottleneck = require('./bottleneck')
|
||||
var assert = require('assert')
|
||||
|
||||
describe('Batcher', function () {
|
||||
var c
|
||||
|
||||
afterEach(function () {
|
||||
return c.limiter.disconnect(false)
|
||||
})
|
||||
|
||||
it('Should batch by time and size', function () {
|
||||
c = makeTest()
|
||||
var batcher = new Bottleneck.Batcher({
|
||||
maxTime: 50,
|
||||
maxSize: 3
|
||||
})
|
||||
var t0 = Date.now()
|
||||
var batches = []
|
||||
|
||||
batcher.on('batch', function (batcher) {
|
||||
batches.push(batcher)
|
||||
})
|
||||
|
||||
return Promise.all([
|
||||
batcher.add(1).then((x) => c.limiter.schedule(c.promise, null, Date.now() - t0, 1)),
|
||||
batcher.add(2).then((x) => c.limiter.schedule(c.promise, null, Date.now() - t0, 2)),
|
||||
batcher.add(3).then((x) => c.limiter.schedule(c.promise, null, Date.now() - t0, 3)),
|
||||
batcher.add(4).then((x) => c.limiter.schedule(c.promise, null, Date.now() - t0, 4)),
|
||||
batcher.add(5).then((x) => c.limiter.schedule(c.promise, null, Date.now() - t0, 5))
|
||||
])
|
||||
.then(function (data) {
|
||||
c.mustEqual(
|
||||
data.map((([t, x]) => [Math.floor(t / 50), x])),
|
||||
[[0, 1], [0, 2], [0, 3], [1, 4], [1, 5]]
|
||||
)
|
||||
|
||||
return c.last()
|
||||
})
|
||||
.then(function (results) {
|
||||
c.checkDuration(50, 20)
|
||||
c.mustEqual(batches, [[1, 2, 3], [4, 5]])
|
||||
})
|
||||
})
|
||||
|
||||
it('Should batch by time', function () {
|
||||
c = makeTest()
|
||||
var batcher = new Bottleneck.Batcher({
|
||||
maxTime: 50
|
||||
})
|
||||
var t0 = Date.now()
|
||||
var batches = []
|
||||
|
||||
batcher.on('batch', function (batcher) {
|
||||
batches.push(batcher)
|
||||
})
|
||||
|
||||
return Promise.all([
|
||||
batcher.add(1).then((x) => c.limiter.schedule(c.promise, null, Date.now() - t0, 1)),
|
||||
batcher.add(2).then((x) => c.limiter.schedule(c.promise, null, Date.now() - t0, 2))
|
||||
])
|
||||
.then(function (data) {
|
||||
c.mustEqual(
|
||||
data.map((([t, x]) => [Math.floor(t / 50), x])),
|
||||
[[1, 1], [1, 2]]
|
||||
)
|
||||
|
||||
return Promise.all([
|
||||
batcher.add(3).then((x) => c.limiter.schedule(c.promise, null, Date.now() - t0, 3)),
|
||||
batcher.add(4).then((x) => c.limiter.schedule(c.promise, null, Date.now() - t0, 4))
|
||||
])
|
||||
})
|
||||
.then(function (data) {
|
||||
c.mustEqual(
|
||||
data.map((([t, x]) => [Math.floor(t / 50), x])),
|
||||
[[2, 3], [2, 4]]
|
||||
)
|
||||
|
||||
return c.last()
|
||||
})
|
||||
.then(function (results) {
|
||||
c.checkDuration(100)
|
||||
c.mustEqual(batches, [[1, 2], [3, 4]])
|
||||
})
|
||||
})
|
||||
|
||||
it('Should batch by size', function () {
|
||||
c = makeTest()
|
||||
var batcher = new Bottleneck.Batcher({
|
||||
maxSize: 2
|
||||
})
|
||||
var batches = []
|
||||
|
||||
batcher.on('batch', function (batcher) {
|
||||
batches.push(batcher)
|
||||
})
|
||||
|
||||
return Promise.all([
|
||||
batcher.add(1).then((x) => c.limiter.schedule(c.promise, null, 1)),
|
||||
batcher.add(2).then((x) => c.limiter.schedule(c.promise, null, 2))
|
||||
])
|
||||
.then(function () {
|
||||
return Promise.all([
|
||||
batcher.add(3).then((x) => c.limiter.schedule(c.promise, null, 3)),
|
||||
batcher.add(4).then((x) => c.limiter.schedule(c.promise, null, 4))
|
||||
])
|
||||
})
|
||||
.then(c.last)
|
||||
.then(function (results) {
|
||||
c.checkDuration(0)
|
||||
c.mustEqual(batches, [[1, 2], [3, 4]])
|
||||
})
|
||||
})
|
||||
|
||||
it('Should stagger flushes', function () {
|
||||
c = makeTest()
|
||||
var batcher = new Bottleneck.Batcher({
|
||||
maxTime: 50,
|
||||
maxSize: 3
|
||||
})
|
||||
var t0 = Date.now()
|
||||
var batches = []
|
||||
|
||||
batcher.on('batch', function (batcher) {
|
||||
batches.push(batcher)
|
||||
})
|
||||
|
||||
return Promise.all([
|
||||
batcher.add(1).then((x) => c.limiter.schedule(c.promise, null, Date.now() - t0, 1)),
|
||||
batcher.add(2).then((x) => c.limiter.schedule(c.promise, null, Date.now() - t0, 2))
|
||||
])
|
||||
.then(function (data) {
|
||||
c.mustEqual(
|
||||
data.map((([t, x]) => [Math.floor(t / 50), x])),
|
||||
[[1, 1], [1, 2]]
|
||||
)
|
||||
|
||||
var promises = []
|
||||
promises.push(batcher.add(3).then((x) => c.limiter.schedule(c.promise, null, Date.now() - t0, 3)))
|
||||
|
||||
return c.wait(10)
|
||||
.then(function () {
|
||||
promises.push(batcher.add(4).then((x) => c.limiter.schedule(c.promise, null, Date.now() - t0, 4)))
|
||||
|
||||
return Promise.all(promises)
|
||||
})
|
||||
})
|
||||
.then(function (data) {
|
||||
c.mustEqual(
|
||||
data.map((([t, x]) => [Math.floor(t / 50), x])),
|
||||
[[2, 3], [2, 4]]
|
||||
)
|
||||
|
||||
return c.last()
|
||||
})
|
||||
.then(function (results) {
|
||||
c.checkDuration(120, 20)
|
||||
c.mustEqual(batches, [[1, 2], [3, 4]])
|
||||
})
|
||||
})
|
||||
|
||||
it('Should force then stagger flushes', function () {
|
||||
c = makeTest()
|
||||
var batcher = new Bottleneck.Batcher({
|
||||
maxTime: 50,
|
||||
maxSize: 3
|
||||
})
|
||||
var t0 = Date.now()
|
||||
var batches = []
|
||||
|
||||
batcher.on('batch', function (batcher) {
|
||||
batches.push(batcher)
|
||||
})
|
||||
|
||||
var promises = []
|
||||
promises.push(batcher.add(1).then((x) => c.limiter.schedule(c.promise, null, Date.now() - t0, 1)))
|
||||
promises.push(batcher.add(2).then((x) => c.limiter.schedule(c.promise, null, Date.now() - t0, 2)))
|
||||
|
||||
return c.wait(10)
|
||||
.then(function () {
|
||||
promises.push(batcher.add(3).then((x) => c.limiter.schedule(c.promise, null, Date.now() - t0, 3)))
|
||||
|
||||
return Promise.all(promises)
|
||||
})
|
||||
.then(function (data) {
|
||||
c.mustEqual(
|
||||
data.map((([t, x]) => [Math.floor(t / 50), x])),
|
||||
[[0, 1], [0, 2], [0, 3]]
|
||||
)
|
||||
|
||||
return Promise.all([
|
||||
batcher.add(4).then((x) => c.limiter.schedule(c.promise, null, Date.now() - t0, 4)),
|
||||
batcher.add(5).then((x) => c.limiter.schedule(c.promise, null, Date.now() - t0, 5)),
|
||||
])
|
||||
})
|
||||
.then(function (data) {
|
||||
c.mustEqual(
|
||||
data.map((([t, x]) => [Math.floor(t / 50), x])),
|
||||
[[1, 4], [1, 5]]
|
||||
)
|
||||
|
||||
return c.last()
|
||||
})
|
||||
.then(function (results) {
|
||||
c.checkDuration(85, 25)
|
||||
c.mustEqual(batches, [[1, 2, 3], [4, 5]])
|
||||
})
|
||||
})
|
||||
})
|
7
node_modules/bottleneck/test/bottleneck.js
generated
vendored
Normal file
7
node_modules/bottleneck/test/bottleneck.js
generated
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
if (process.env.BUILD === 'es5') {
|
||||
module.exports = require('../es5.js')
|
||||
} else if (process.env.BUILD === 'light') {
|
||||
module.exports = require('../light.js')
|
||||
} else {
|
||||
module.exports = require('../lib/index.js')
|
||||
}
|
1549
node_modules/bottleneck/test/cluster.js
generated
vendored
Normal file
1549
node_modules/bottleneck/test/cluster.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
142
node_modules/bottleneck/test/context.js
generated
vendored
Normal file
142
node_modules/bottleneck/test/context.js
generated
vendored
Normal file
|
@ -0,0 +1,142 @@
|
|||
global.TEST = true
|
||||
var Bottleneck = require('./bottleneck')
|
||||
var assert = require('assert')
|
||||
|
||||
module.exports = function (options={}) {
|
||||
var mustEqual = function (a, b) {
|
||||
var strA = JSON.stringify(a)
|
||||
var strB = JSON.stringify(b)
|
||||
if (strA !== strB) {
|
||||
console.log(strA + ' !== ' + strB, (new Error('').stack))
|
||||
assert(strA === strB)
|
||||
}
|
||||
}
|
||||
|
||||
var start
|
||||
var calls = []
|
||||
|
||||
// set options.datastore
|
||||
var setRedisClientOptions = function (options) {
|
||||
options.clearDatastore = true
|
||||
if (options.clientOptions == null) {
|
||||
options.clientOptions = {
|
||||
host: process.env.REDIS_HOST,
|
||||
port: process.env.REDIS_PORT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (options.datastore == null && process.env.DATASTORE === 'redis') {
|
||||
options.datastore = 'redis'
|
||||
setRedisClientOptions(options)
|
||||
} else if (options.datastore == null && process.env.DATASTORE === 'ioredis') {
|
||||
options.datastore = 'ioredis'
|
||||
setRedisClientOptions(options)
|
||||
} else {
|
||||
options.datastore = 'local'
|
||||
}
|
||||
|
||||
var limiter = new Bottleneck(options)
|
||||
// limiter.on("debug", function (str, args) { console.log(`${Date.now()-start} ${str} ${JSON.stringify(args)}`) })
|
||||
if (!options.errorEventsExpected) {
|
||||
limiter.on("error", function (err) {
|
||||
console.log('(CONTEXT) ERROR EVENT', err)
|
||||
})
|
||||
}
|
||||
limiter.ready().then(function (client) {
|
||||
start = Date.now()
|
||||
})
|
||||
var getResults = function () {
|
||||
return {
|
||||
elapsed: Date.now() - start,
|
||||
callsDuration: calls.length > 0 ? calls[calls.length - 1].time : null,
|
||||
calls: calls
|
||||
}
|
||||
}
|
||||
|
||||
var context = {
|
||||
job: function (err, ...result) {
|
||||
var cb = result.pop()
|
||||
calls.push({err: err, result: result, time: Date.now()-start})
|
||||
if (process.env.DEBUG) console.log(result, calls)
|
||||
cb.apply({}, [err].concat(result))
|
||||
},
|
||||
slowJob: function (duration, err, ...result) {
|
||||
setTimeout(function () {
|
||||
var cb = result.pop()
|
||||
calls.push({err: err, result: result, time: Date.now()-start})
|
||||
if (process.env.DEBUG) console.log(result, calls)
|
||||
cb.apply({}, [err].concat(result))
|
||||
}, duration)
|
||||
},
|
||||
promise: function (err, ...result) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
if (process.env.DEBUG) console.log('In c.promise. Result: ', result)
|
||||
calls.push({err: err, result: result, time: Date.now()-start})
|
||||
if (process.env.DEBUG) console.log(result, calls)
|
||||
if (err === null) {
|
||||
return resolve(result)
|
||||
} else {
|
||||
return reject(err)
|
||||
}
|
||||
})
|
||||
},
|
||||
slowPromise: function (duration, err, ...result) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
setTimeout(function () {
|
||||
if (process.env.DEBUG) console.log('In c.slowPromise. Result: ', result)
|
||||
calls.push({err: err, result: result, time: Date.now()-start})
|
||||
if (process.env.DEBUG) console.log(result, calls)
|
||||
if (err === null) {
|
||||
return resolve(result)
|
||||
} else {
|
||||
return reject(err)
|
||||
}
|
||||
}, duration)
|
||||
})
|
||||
},
|
||||
pNoErrVal: function (promise, ...expected) {
|
||||
if (process.env.DEBUG) console.log('In c.pNoErrVal. Expected:', expected)
|
||||
return promise.then(function (actual) {
|
||||
mustEqual(actual, expected)
|
||||
})
|
||||
},
|
||||
noErrVal: function (...expected) {
|
||||
return function (err, ...actual) {
|
||||
mustEqual(err, null)
|
||||
mustEqual(actual, expected)
|
||||
}
|
||||
},
|
||||
last: function (options) {
|
||||
var opt = options != null ? options : {}
|
||||
return limiter.schedule(opt, function () { return Promise.resolve(getResults()) })
|
||||
.catch(function (err) { console.error("Error in context.last:", err)})
|
||||
},
|
||||
wait: function (wait) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
setTimeout(resolve, wait)
|
||||
})
|
||||
},
|
||||
limiter: limiter,
|
||||
mustEqual: mustEqual,
|
||||
mustExist: function (a) { assert(a != null) },
|
||||
results: getResults,
|
||||
checkResultsOrder: function (order) {
|
||||
mustEqual(order.length, calls.length)
|
||||
for (var i = 0; i < Math.max(calls.length, order.length); i++) {
|
||||
mustEqual(order[i], calls[i].result)
|
||||
}
|
||||
},
|
||||
checkDuration: function (shouldBe, minBound = 10) {
|
||||
var results = getResults()
|
||||
var min = shouldBe - minBound
|
||||
var max = shouldBe + 50
|
||||
if (!(results.callsDuration > min && results.callsDuration < max)) {
|
||||
console.error('Duration not around ' + shouldBe + '. Was ' + results.callsDuration)
|
||||
}
|
||||
assert(results.callsDuration > min && results.callsDuration < max)
|
||||
}
|
||||
}
|
||||
|
||||
return context
|
||||
}
|
867
node_modules/bottleneck/test/general.js
generated
vendored
Normal file
867
node_modules/bottleneck/test/general.js
generated
vendored
Normal file
|
@ -0,0 +1,867 @@
|
|||
var makeTest = require('./context')
|
||||
var Bottleneck = require('./bottleneck')
|
||||
var assert = require('assert')
|
||||
var child_process = require('child_process')
|
||||
|
||||
describe('General', function () {
|
||||
var c
|
||||
|
||||
afterEach(function () {
|
||||
return c.limiter.disconnect(false)
|
||||
})
|
||||
|
||||
if (
|
||||
process.env.DATASTORE !== 'redis' && process.env.DATASTORE !== 'ioredis' &&
|
||||
process.env.BUILD !== 'es5' && process.env.BUILD !== 'light'
|
||||
) {
|
||||
it('Should not leak memory on instantiation', async function () {
|
||||
c = makeTest()
|
||||
this.timeout(8000)
|
||||
const { iterate } = require('leakage')
|
||||
|
||||
const result = await iterate.async(async () => {
|
||||
const limiter = new Bottleneck({ datastore: 'local' })
|
||||
await limiter.ready()
|
||||
return limiter.disconnect(false)
|
||||
}, { iterations: 25 })
|
||||
|
||||
})
|
||||
|
||||
it('Should not leak memory running jobs', async function () {
|
||||
c = makeTest()
|
||||
this.timeout(12000)
|
||||
const { iterate } = require('leakage')
|
||||
const limiter = new Bottleneck({ datastore: 'local', maxConcurrent: 1, minTime: 10 })
|
||||
await limiter.ready()
|
||||
var ctr = 0
|
||||
var i = 0
|
||||
|
||||
const result = await iterate.async(async () => {
|
||||
await limiter.schedule(function (zero, one) {
|
||||
i = i + zero + one
|
||||
}, 0, 1)
|
||||
await limiter.schedule(function (zero, one) {
|
||||
i = i + zero + one
|
||||
}, 0, 1)
|
||||
}, { iterations: 25 })
|
||||
c.mustEqual(i, 302)
|
||||
})
|
||||
}
|
||||
|
||||
it('Should prompt to upgrade', function () {
|
||||
c = makeTest()
|
||||
try {
|
||||
var limiter = new Bottleneck(1, 250)
|
||||
} catch (err) {
|
||||
c.mustEqual(err.message, 'Bottleneck v2 takes a single object argument. Refer to https://github.com/SGrondin/bottleneck#upgrading-to-v2 if you\'re upgrading from Bottleneck v1.')
|
||||
}
|
||||
})
|
||||
|
||||
it('Should allow null capacity', function () {
|
||||
c = makeTest({ id: 'null', minTime: 0 })
|
||||
return c.limiter.updateSettings({ minTime: 10 })
|
||||
})
|
||||
|
||||
it('Should keep scope', async function () {
|
||||
c = makeTest({ maxConcurrent: 1 })
|
||||
|
||||
class Job {
|
||||
constructor() {
|
||||
this.value = 5
|
||||
}
|
||||
action(x) {
|
||||
return this.value + x
|
||||
}
|
||||
}
|
||||
var job = new Job()
|
||||
|
||||
c.mustEqual(6, await c.limiter.schedule(() => job.action.bind(job)(1)))
|
||||
c.mustEqual(7, await c.limiter.wrap(job.action.bind(job))(2))
|
||||
})
|
||||
|
||||
it('Should pass multiple arguments back even on errors when using submit()', function (done) {
|
||||
c = makeTest({ maxConcurrent: 1 })
|
||||
|
||||
c.limiter.submit(c.job, new Error('welp'), 1, 2, function (err, x, y) {
|
||||
c.mustEqual(err.message, 'welp')
|
||||
c.mustEqual(x, 1)
|
||||
c.mustEqual(y, 2)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('Should expose the Events library', function (cb) {
|
||||
c = makeTest()
|
||||
|
||||
class Hello {
|
||||
constructor() {
|
||||
this.emitter = new Bottleneck.Events(this)
|
||||
}
|
||||
|
||||
doSomething() {
|
||||
this.emitter.trigger('info', 'hello', 'world', 123)
|
||||
return 5
|
||||
}
|
||||
}
|
||||
|
||||
const myObject = new Hello();
|
||||
myObject.on('info', (...args) => {
|
||||
c.mustEqual(args, ['hello', 'world', 123])
|
||||
cb()
|
||||
})
|
||||
myObject.doSomething()
|
||||
c.mustEqual(myObject.emitter.listenerCount('info'), 1)
|
||||
c.mustEqual(myObject.emitter.listenerCount('nothing'), 0)
|
||||
|
||||
myObject.on('blah', '')
|
||||
myObject.on('blah', null)
|
||||
myObject.on('blah')
|
||||
return myObject.emitter.trigger('blah')
|
||||
})
|
||||
|
||||
describe('Counts and statuses', function () {
|
||||
it('Should check() and return the queued count with and without a priority value', async function () {
|
||||
c = makeTest({maxConcurrent: 1, minTime: 100})
|
||||
|
||||
c.mustEqual(await c.limiter.check(), true)
|
||||
|
||||
c.mustEqual(c.limiter.queued(), 0)
|
||||
c.mustEqual(await c.limiter.clusterQueued(), 0)
|
||||
|
||||
await c.limiter.submit({id: 1}, c.slowJob, 50, null, 1, c.noErrVal(1))
|
||||
c.mustEqual(c.limiter.queued(), 0) // It's already running
|
||||
|
||||
c.mustEqual(await c.limiter.check(), false)
|
||||
|
||||
await c.limiter.submit({id: 2}, c.slowJob, 50, null, 2, c.noErrVal(2))
|
||||
c.mustEqual(c.limiter.queued(), 1)
|
||||
c.mustEqual(await c.limiter.clusterQueued(), 1)
|
||||
c.mustEqual(c.limiter.queued(1), 0)
|
||||
c.mustEqual(c.limiter.queued(5), 1)
|
||||
|
||||
await c.limiter.submit({id: 3}, c.slowJob, 50, null, 3, c.noErrVal(3))
|
||||
c.mustEqual(c.limiter.queued(), 2)
|
||||
c.mustEqual(await c.limiter.clusterQueued(), 2)
|
||||
c.mustEqual(c.limiter.queued(1), 0)
|
||||
c.mustEqual(c.limiter.queued(5), 2)
|
||||
|
||||
await c.limiter.submit({id: 4}, c.slowJob, 50, null, 4, c.noErrVal(4))
|
||||
c.mustEqual(c.limiter.queued(), 3)
|
||||
c.mustEqual(await c.limiter.clusterQueued(), 3)
|
||||
c.mustEqual(c.limiter.queued(1), 0)
|
||||
c.mustEqual(c.limiter.queued(5), 3)
|
||||
|
||||
await c.limiter.submit({priority: 1, id: 5}, c.job, null, 5, c.noErrVal(5))
|
||||
c.mustEqual(c.limiter.queued(), 4)
|
||||
c.mustEqual(await c.limiter.clusterQueued(), 4)
|
||||
c.mustEqual(c.limiter.queued(1), 1)
|
||||
c.mustEqual(c.limiter.queued(5), 3)
|
||||
|
||||
var results = await c.last()
|
||||
c.mustEqual(c.limiter.queued(), 0)
|
||||
c.mustEqual(await c.limiter.clusterQueued(), 0)
|
||||
c.checkResultsOrder([[1], [5], [2], [3], [4]])
|
||||
c.checkDuration(450)
|
||||
})
|
||||
|
||||
it('Should return the running and done counts', function () {
|
||||
c = makeTest({maxConcurrent: 5, minTime: 0})
|
||||
|
||||
return Promise.all([c.limiter.running(), c.limiter.done()])
|
||||
.then(function ([running, done]) {
|
||||
c.mustEqual(running, 0)
|
||||
c.mustEqual(done, 0)
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 1 }, c.slowPromise, 100, null, 1), 1)
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 3, id: 2 }, c.slowPromise, 200, null, 2), 2)
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 3 }, c.slowPromise, 100, null, 3), 3)
|
||||
|
||||
return c.limiter.schedule({ weight: 0, id: 4 }, c.promise, null)
|
||||
})
|
||||
.then(function () {
|
||||
return Promise.all([c.limiter.running(), c.limiter.done()])
|
||||
})
|
||||
.then(function ([running, done]) {
|
||||
c.mustEqual(running, 5)
|
||||
c.mustEqual(done, 0)
|
||||
return c.wait(125)
|
||||
})
|
||||
.then(function () {
|
||||
return Promise.all([c.limiter.running(), c.limiter.done()])
|
||||
})
|
||||
.then(function ([running, done]) {
|
||||
c.mustEqual(running, 3)
|
||||
c.mustEqual(done, 2)
|
||||
return c.wait(100)
|
||||
})
|
||||
.then(function () {
|
||||
return Promise.all([c.limiter.running(), c.limiter.done()])
|
||||
})
|
||||
.then(function ([running, done]) {
|
||||
c.mustEqual(running, 0)
|
||||
c.mustEqual(done, 5)
|
||||
return c.last()
|
||||
})
|
||||
.then(function (results) {
|
||||
c.checkDuration(200)
|
||||
c.checkResultsOrder([[], [1], [3], [2]])
|
||||
})
|
||||
})
|
||||
|
||||
it('Should refuse duplicate Job IDs', async function () {
|
||||
c = makeTest({maxConcurrent: 2, minTime: 100, trackDoneStatus: true})
|
||||
|
||||
try {
|
||||
await c.limiter.schedule({ id: 'a' }, c.promise, null, 1)
|
||||
await c.limiter.schedule({ id: 'b' }, c.promise, null, 2)
|
||||
await c.limiter.schedule({ id: 'a' }, c.promise, null, 3)
|
||||
} catch (e) {
|
||||
c.mustEqual(e.message, 'A job with the same id already exists (id=a)')
|
||||
}
|
||||
})
|
||||
|
||||
it('Should return job statuses', function () {
|
||||
c = makeTest({maxConcurrent: 2, minTime: 100})
|
||||
|
||||
c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 0, RUNNING: 0, EXECUTING: 0 })
|
||||
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 1 }, c.slowPromise, 100, null, 1), 1)
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 2 }, c.slowPromise, 200, null, 2), 2)
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 2, id: 3 }, c.slowPromise, 100, null, 3), 3)
|
||||
c.mustEqual(c.limiter.counts(), { RECEIVED: 3, QUEUED: 0, RUNNING: 0, EXECUTING: 0 })
|
||||
|
||||
return c.wait(50)
|
||||
.then(function () {
|
||||
c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 1, RUNNING: 1, EXECUTING: 1 })
|
||||
c.mustEqual(c.limiter.jobStatus(1), 'EXECUTING')
|
||||
c.mustEqual(c.limiter.jobStatus(2), 'RUNNING')
|
||||
c.mustEqual(c.limiter.jobStatus(3), 'QUEUED')
|
||||
|
||||
return c.last()
|
||||
})
|
||||
.then(function (results) {
|
||||
c.checkDuration(400)
|
||||
c.checkResultsOrder([[1], [2], [3]])
|
||||
})
|
||||
})
|
||||
|
||||
it('Should return job statuses, including DONE', function () {
|
||||
c = makeTest({maxConcurrent: 2, minTime: 100, trackDoneStatus: true})
|
||||
|
||||
c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 0, RUNNING: 0, EXECUTING: 0, DONE: 0 })
|
||||
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 1 }, c.slowPromise, 100, null, 1), 1)
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 2 }, c.slowPromise, 200, null, 2), 2)
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 2, id: 3 }, c.slowPromise, 100, null, 3), 3)
|
||||
c.mustEqual(c.limiter.counts(), { RECEIVED: 3, QUEUED: 0, RUNNING: 0, EXECUTING: 0, DONE: 0 })
|
||||
|
||||
return c.wait(50)
|
||||
.then(function () {
|
||||
c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 1, RUNNING: 1, EXECUTING: 1, DONE: 0 })
|
||||
c.mustEqual(c.limiter.jobStatus(1), 'EXECUTING')
|
||||
c.mustEqual(c.limiter.jobStatus(2), 'RUNNING')
|
||||
c.mustEqual(c.limiter.jobStatus(3), 'QUEUED')
|
||||
|
||||
return c.wait(100)
|
||||
})
|
||||
.then(function () {
|
||||
c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 1, RUNNING: 0, EXECUTING: 1, DONE: 1 })
|
||||
c.mustEqual(c.limiter.jobStatus(1), 'DONE')
|
||||
c.mustEqual(c.limiter.jobStatus(2), 'EXECUTING')
|
||||
c.mustEqual(c.limiter.jobStatus(3), 'QUEUED')
|
||||
|
||||
return c.last()
|
||||
})
|
||||
.then(function (results) {
|
||||
c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 0, RUNNING: 0, EXECUTING: 0, DONE: 4 })
|
||||
c.checkDuration(400)
|
||||
c.checkResultsOrder([[1], [2], [3]])
|
||||
})
|
||||
})
|
||||
|
||||
it('Should return jobs for a status', function () {
|
||||
c = makeTest({maxConcurrent: 2, minTime: 100, trackDoneStatus: true})
|
||||
|
||||
c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 0, RUNNING: 0, EXECUTING: 0, DONE: 0 })
|
||||
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 1 }, c.slowPromise, 100, null, 1), 1)
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 2 }, c.slowPromise, 200, null, 2), 2)
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 2, id: 3 }, c.slowPromise, 100, null, 3), 3)
|
||||
c.mustEqual(c.limiter.counts(), { RECEIVED: 3, QUEUED: 0, RUNNING: 0, EXECUTING: 0, DONE: 0 })
|
||||
|
||||
c.mustEqual(c.limiter.jobs(), ['1', '2', '3'])
|
||||
c.mustEqual(c.limiter.jobs('RECEIVED'), ['1', '2', '3'])
|
||||
|
||||
return c.wait(50)
|
||||
.then(function () {
|
||||
c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 1, RUNNING: 1, EXECUTING: 1, DONE: 0 })
|
||||
c.mustEqual(c.limiter.jobs('EXECUTING'), ['1'])
|
||||
c.mustEqual(c.limiter.jobs('RUNNING'), ['2'])
|
||||
c.mustEqual(c.limiter.jobs('QUEUED'), ['3'])
|
||||
|
||||
return c.wait(100)
|
||||
})
|
||||
.then(function () {
|
||||
c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 1, RUNNING: 0, EXECUTING: 1, DONE: 1 })
|
||||
c.mustEqual(c.limiter.jobs('DONE'), ['1'])
|
||||
c.mustEqual(c.limiter.jobs('EXECUTING'), ['2'])
|
||||
c.mustEqual(c.limiter.jobs('QUEUED'), ['3'])
|
||||
|
||||
return c.last()
|
||||
})
|
||||
.then(function (results) {
|
||||
c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 0, RUNNING: 0, EXECUTING: 0, DONE: 4 })
|
||||
c.checkDuration(400)
|
||||
c.checkResultsOrder([[1], [2], [3]])
|
||||
})
|
||||
})
|
||||
|
||||
it('Should trigger events on status changes', function () {
|
||||
c = makeTest({maxConcurrent: 2, minTime: 100, trackDoneStatus: true})
|
||||
var onReceived = 0
|
||||
var onQueued = 0
|
||||
var onScheduled = 0
|
||||
var onExecuting = 0
|
||||
var onDone = 0
|
||||
c.limiter.on('received', (info) => {
|
||||
c.mustEqual(Object.keys(info).sort(), ['args', 'options'])
|
||||
onReceived++
|
||||
})
|
||||
c.limiter.on('queued', (info) => {
|
||||
c.mustEqual(Object.keys(info).sort(), ['args', 'blocked', 'options', 'reachedHWM'])
|
||||
onQueued++
|
||||
})
|
||||
c.limiter.on('scheduled', (info) => {
|
||||
c.mustEqual(Object.keys(info).sort(), ['args', 'options'])
|
||||
onScheduled++
|
||||
})
|
||||
c.limiter.on('executing', (info) => {
|
||||
c.mustEqual(Object.keys(info).sort(), ['args', 'options', 'retryCount'])
|
||||
onExecuting++
|
||||
})
|
||||
c.limiter.on('done', (info) => {
|
||||
c.mustEqual(Object.keys(info).sort(), ['args', 'options', 'retryCount'])
|
||||
onDone++
|
||||
})
|
||||
|
||||
c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 0, RUNNING: 0, EXECUTING: 0, DONE: 0 })
|
||||
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 1 }, c.slowPromise, 100, null, 1), 1)
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 2 }, c.slowPromise, 200, null, 2), 2)
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 2, id: 3 }, c.slowPromise, 100, null, 3), 3)
|
||||
c.mustEqual(c.limiter.counts(), { RECEIVED: 3, QUEUED: 0, RUNNING: 0, EXECUTING: 0, DONE: 0 })
|
||||
|
||||
c.mustEqual([onReceived, onQueued, onScheduled, onExecuting, onDone], [3, 0, 0, 0, 0])
|
||||
|
||||
return c.wait(50)
|
||||
.then(function () {
|
||||
c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 1, RUNNING: 1, EXECUTING: 1, DONE: 0 })
|
||||
c.mustEqual([onReceived, onQueued, onScheduled, onExecuting, onDone], [3, 3, 2, 1, 0])
|
||||
|
||||
return c.wait(100)
|
||||
})
|
||||
.then(function () {
|
||||
c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 1, RUNNING: 0, EXECUTING: 1, DONE: 1 })
|
||||
c.mustEqual(c.limiter.jobs('DONE'), ['1'])
|
||||
c.mustEqual(c.limiter.jobs('EXECUTING'), ['2'])
|
||||
c.mustEqual(c.limiter.jobs('QUEUED'), ['3'])
|
||||
c.mustEqual([onReceived, onQueued, onScheduled, onExecuting, onDone], [3, 3, 2, 2, 1])
|
||||
|
||||
return c.last()
|
||||
})
|
||||
.then(function (results) {
|
||||
c.mustEqual(c.limiter.counts(), { RECEIVED: 0, QUEUED: 0, RUNNING: 0, EXECUTING: 0, DONE: 4 })
|
||||
c.mustEqual([onReceived, onQueued, onScheduled, onExecuting, onDone], [4, 4, 4, 4, 4])
|
||||
c.checkDuration(400)
|
||||
c.checkResultsOrder([[1], [2], [3]])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Events', function () {
|
||||
it('Should return itself', function () {
|
||||
c = makeTest({ id: 'test-limiter' })
|
||||
|
||||
var returned = c.limiter.on('ready', function () { })
|
||||
c.mustEqual(returned.id, 'test-limiter')
|
||||
})
|
||||
|
||||
it('Should fire events on empty queue', function () {
|
||||
c = makeTest({maxConcurrent: 1, minTime: 100})
|
||||
var calledEmpty = 0
|
||||
var calledIdle = 0
|
||||
var calledDepleted = 0
|
||||
|
||||
c.limiter.on('empty', function () { calledEmpty++ })
|
||||
c.limiter.on('idle', function () { calledIdle++ })
|
||||
c.limiter.on('depleted', function () { calledDepleted++ })
|
||||
|
||||
return c.pNoErrVal(c.limiter.schedule({id: 1}, c.slowPromise, 50, null, 1), 1)
|
||||
.then(function () {
|
||||
c.mustEqual(calledEmpty, 1)
|
||||
c.mustEqual(calledIdle, 1)
|
||||
return Promise.all([
|
||||
c.pNoErrVal(c.limiter.schedule({id: 2}, c.slowPromise, 50, null, 2), 2),
|
||||
c.pNoErrVal(c.limiter.schedule({id: 3}, c.slowPromise, 50, null, 3), 3)
|
||||
])
|
||||
})
|
||||
.then(function () {
|
||||
return c.limiter.submit({id: 4}, c.slowJob, 50, null, 4, null)
|
||||
})
|
||||
.then(function () {
|
||||
c.checkDuration(250)
|
||||
c.checkResultsOrder([[1], [2], [3]])
|
||||
c.mustEqual(calledEmpty, 3)
|
||||
c.mustEqual(calledIdle, 2)
|
||||
c.mustEqual(calledDepleted, 0)
|
||||
return c.last()
|
||||
})
|
||||
})
|
||||
|
||||
it('Should fire events once', function () {
|
||||
c = makeTest({maxConcurrent: 1, minTime: 100})
|
||||
var calledEmptyOnce = 0
|
||||
var calledIdleOnce = 0
|
||||
var calledEmpty = 0
|
||||
var calledIdle = 0
|
||||
var calledDepleted = 0
|
||||
|
||||
c.limiter.once('empty', function () { calledEmptyOnce++ })
|
||||
c.limiter.once('idle', function () { calledIdleOnce++ })
|
||||
c.limiter.on('empty', function () { calledEmpty++ })
|
||||
c.limiter.on('idle', function () { calledIdle++ })
|
||||
c.limiter.on('depleted', function () { calledDepleted++ })
|
||||
|
||||
c.pNoErrVal(c.limiter.schedule(c.slowPromise, 50, null, 1), 1)
|
||||
|
||||
return c.pNoErrVal(c.limiter.schedule(c.promise, null, 2), 2)
|
||||
.then(function () {
|
||||
c.mustEqual(calledEmptyOnce, 1)
|
||||
c.mustEqual(calledIdleOnce, 1)
|
||||
c.mustEqual(calledEmpty, 1)
|
||||
c.mustEqual(calledIdle, 1)
|
||||
return c.pNoErrVal(c.limiter.schedule(c.promise, null, 3), 3)
|
||||
})
|
||||
.then(function () {
|
||||
c.checkDuration(200)
|
||||
c.checkResultsOrder([[1], [2], [3]])
|
||||
c.mustEqual(calledEmptyOnce, 1)
|
||||
c.mustEqual(calledIdleOnce, 1)
|
||||
c.mustEqual(calledEmpty, 2)
|
||||
c.mustEqual(calledIdle, 2)
|
||||
c.mustEqual(calledDepleted, 0)
|
||||
})
|
||||
})
|
||||
|
||||
it('Should support faulty event listeners', function (done) {
|
||||
c = makeTest({maxConcurrent: 1, minTime: 100, errorEventsExpected: true})
|
||||
var calledError = 0
|
||||
|
||||
c.limiter.on('error', function (err) {
|
||||
calledError++
|
||||
if (err.message === 'Oh noes!' && calledError === 1) {
|
||||
done()
|
||||
}
|
||||
})
|
||||
c.limiter.on('empty', function () {
|
||||
throw new Error('Oh noes!')
|
||||
})
|
||||
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 1), 1)
|
||||
})
|
||||
|
||||
it('Should wait for async event listeners', function (done) {
|
||||
c = makeTest({maxConcurrent: 1, minTime: 100, errorEventsExpected: true})
|
||||
var calledError = 0
|
||||
|
||||
c.limiter.on('error', function (err) {
|
||||
calledError++
|
||||
if (err.message === 'It broke!' && calledError === 1) {
|
||||
done()
|
||||
}
|
||||
})
|
||||
c.limiter.on('empty', function () {
|
||||
return c.slowPromise(100, null, 1, 2)
|
||||
.then(function (x) {
|
||||
c.mustEqual(x, [1, 2])
|
||||
return Promise.reject(new Error('It broke!'))
|
||||
})
|
||||
})
|
||||
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 1), 1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('High water limit', function () {
|
||||
it('Should support highWater set to 0', function () {
|
||||
c = makeTest({maxConcurrent: 1, minTime: 0, highWater: 0, rejectOnDrop: false})
|
||||
|
||||
var first = c.pNoErrVal(c.limiter.schedule(c.slowPromise, 50, null, 1), 1)
|
||||
c.pNoErrVal(c.limiter.schedule(c.slowPromise, 50, null, 2), 2)
|
||||
c.pNoErrVal(c.limiter.schedule(c.slowPromise, 50, null, 3), 3)
|
||||
c.pNoErrVal(c.limiter.schedule(c.slowPromise, 50, null, 4), 4)
|
||||
|
||||
return first
|
||||
.then(function () {
|
||||
return c.last({ weight: 0 })
|
||||
})
|
||||
.then(function (results) {
|
||||
c.checkDuration(50)
|
||||
c.checkResultsOrder([[1]])
|
||||
})
|
||||
})
|
||||
|
||||
it('Should support highWater set to 1', function () {
|
||||
c = makeTest({maxConcurrent: 1, minTime: 0, highWater: 1, rejectOnDrop: false})
|
||||
|
||||
var first = c.pNoErrVal(c.limiter.schedule(c.slowPromise, 50, null, 1), 1)
|
||||
c.pNoErrVal(c.limiter.schedule(c.slowPromise, 50, null, 2), 2)
|
||||
c.pNoErrVal(c.limiter.schedule(c.slowPromise, 50, null, 3), 3)
|
||||
var last = c.pNoErrVal(c.limiter.schedule(c.slowPromise, 50, null, 4), 4)
|
||||
|
||||
return Promise.all([first, last])
|
||||
.then(function () {
|
||||
return c.last({ weight: 0 })
|
||||
})
|
||||
.then(function (results) {
|
||||
c.checkDuration(100)
|
||||
c.checkResultsOrder([[1], [4]])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Weight', function () {
|
||||
it('Should not add jobs with a weight above the maxConcurrent', function () {
|
||||
c = makeTest({maxConcurrent: 2})
|
||||
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 1 }, c.promise, null, 1), 1)
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 2 }, c.promise, null, 2), 2)
|
||||
|
||||
return c.limiter.schedule({ weight: 3 }, c.promise, null, 3)
|
||||
.catch(function (err) {
|
||||
c.mustEqual(err.message, 'Impossible to add a job having a weight of 3 to a limiter having a maxConcurrent setting of 2')
|
||||
return c.last()
|
||||
})
|
||||
.then(function (results) {
|
||||
c.checkDuration(0)
|
||||
c.checkResultsOrder([[1], [2]])
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
it('Should support custom job weights', function () {
|
||||
c = makeTest({maxConcurrent: 2})
|
||||
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 1 }, c.slowPromise, 100, null, 1), 1)
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 2 }, c.slowPromise, 200, null, 2), 2)
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 1 }, c.slowPromise, 100, null, 3), 3)
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 1 }, c.slowPromise, 100, null, 4), 4)
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 0 }, c.slowPromise, 100, null, 5), 5)
|
||||
|
||||
return c.last()
|
||||
.then(function (results) {
|
||||
c.checkDuration(400)
|
||||
c.checkResultsOrder([[1], [2], [3], [4], [5]])
|
||||
})
|
||||
})
|
||||
|
||||
it('Should overflow at the correct rate', function () {
|
||||
c = makeTest({
|
||||
maxConcurrent: 2,
|
||||
reservoir: 3
|
||||
})
|
||||
|
||||
var calledDepleted = 0
|
||||
var emptyArguments = []
|
||||
c.limiter.on('depleted', function (empty) {
|
||||
emptyArguments.push(empty)
|
||||
calledDepleted++
|
||||
})
|
||||
|
||||
var p1 = c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 1 }, c.slowPromise, 100, null, 1), 1)
|
||||
var p2 = c.pNoErrVal(c.limiter.schedule({ weight: 2, id: 2 }, c.slowPromise, 150, null, 2), 2)
|
||||
var p3 = c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 3 }, c.slowPromise, 100, null, 3), 3)
|
||||
var p4 = c.pNoErrVal(c.limiter.schedule({ weight: 1, id: 4 }, c.slowPromise, 100, null, 4), 4)
|
||||
|
||||
return Promise.all([p1, p2])
|
||||
.then(function () {
|
||||
c.mustEqual(c.limiter.queued(), 2)
|
||||
return c.limiter.currentReservoir()
|
||||
})
|
||||
.then(function (reservoir) {
|
||||
c.mustEqual(reservoir, 0)
|
||||
c.mustEqual(calledDepleted, 1)
|
||||
return c.limiter.incrementReservoir(1)
|
||||
})
|
||||
.then(function (reservoir) {
|
||||
c.mustEqual(reservoir, 1)
|
||||
return c.last({ priority: 1, weight: 0 })
|
||||
})
|
||||
.then(function (results) {
|
||||
c.mustEqual(calledDepleted, 3)
|
||||
c.mustEqual(c.limiter.queued(), 1)
|
||||
c.checkDuration(250)
|
||||
c.checkResultsOrder([[1], [2]])
|
||||
return c.limiter.currentReservoir()
|
||||
})
|
||||
.then(function (reservoir) {
|
||||
c.mustEqual(reservoir, 0)
|
||||
return c.limiter.updateSettings({ reservoir: 1 })
|
||||
})
|
||||
.then(function () {
|
||||
return Promise.all([p3, p4])
|
||||
})
|
||||
.then(function () {
|
||||
return c.limiter.currentReservoir()
|
||||
})
|
||||
.then(function (reservoir) {
|
||||
c.mustEqual(reservoir, 0)
|
||||
c.mustEqual(calledDepleted, 4)
|
||||
c.mustEqual(emptyArguments, [false, false, false, true])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Expiration', function () {
|
||||
it('Should cancel jobs', function () {
|
||||
c = makeTest({ maxConcurrent: 2 })
|
||||
var t0 = Date.now()
|
||||
|
||||
return Promise.all([
|
||||
c.pNoErrVal(c.limiter.schedule({ id: 'very-slow-no-expiration' }, c.slowPromise, 150, null, 1), 1),
|
||||
|
||||
c.limiter.schedule({ expiration: 50, id: 'slow-with-expiration' }, c.slowPromise, 75, null, 2)
|
||||
.then(function () {
|
||||
return Promise.reject(new Error("Should have timed out."))
|
||||
})
|
||||
.catch(function (err) {
|
||||
c.mustEqual(err.message, 'This job timed out after 50 ms.')
|
||||
var duration = Date.now() - t0
|
||||
assert(duration > 45 && duration < 80)
|
||||
|
||||
return Promise.all([c.limiter.running(), c.limiter.done()])
|
||||
})
|
||||
.then(function ([running, done]) {
|
||||
c.mustEqual(running, 1)
|
||||
c.mustEqual(done, 1)
|
||||
})
|
||||
|
||||
])
|
||||
.then(function () {
|
||||
var duration = Date.now() - t0
|
||||
assert(duration > 145 && duration < 180)
|
||||
return Promise.all([c.limiter.running(), c.limiter.done()])
|
||||
})
|
||||
.then(function ([running, done]) {
|
||||
c.mustEqual(running, 0)
|
||||
c.mustEqual(done, 2)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Pubsub', function () {
|
||||
it('Should pass strings', function (done) {
|
||||
c = makeTest({ maxConcurrent: 2 })
|
||||
|
||||
c.limiter.on('message', function (msg) {
|
||||
c.mustEqual(msg, 'hello')
|
||||
done()
|
||||
})
|
||||
|
||||
c.limiter.publish('hello')
|
||||
})
|
||||
|
||||
it('Should pass objects', function (done) {
|
||||
c = makeTest({ maxConcurrent: 2 })
|
||||
var obj = {
|
||||
array: ['abc', true],
|
||||
num: 235.59
|
||||
}
|
||||
|
||||
c.limiter.on('message', function (msg) {
|
||||
c.mustEqual(JSON.parse(msg), obj)
|
||||
done()
|
||||
})
|
||||
|
||||
c.limiter.publish(JSON.stringify(obj))
|
||||
})
|
||||
})
|
||||
|
||||
describe('Reservoir Refresh', function () {
|
||||
it('Should auto-refresh the reservoir', function () {
|
||||
c = makeTest({
|
||||
reservoir: 8,
|
||||
reservoirRefreshInterval: 150,
|
||||
reservoirRefreshAmount: 5,
|
||||
heartbeatInterval: 75 // not for production use
|
||||
})
|
||||
var calledDepleted = 0
|
||||
|
||||
c.limiter.on('depleted', function () {
|
||||
calledDepleted++
|
||||
})
|
||||
|
||||
return Promise.all([
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 1 }, c.promise, null, 1), 1),
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 2 }, c.promise, null, 2), 2),
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 3 }, c.promise, null, 3), 3),
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 4 }, c.promise, null, 4), 4),
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 5 }, c.promise, null, 5), 5)
|
||||
])
|
||||
.then(function () {
|
||||
return c.limiter.currentReservoir()
|
||||
})
|
||||
.then(function (reservoir) {
|
||||
c.mustEqual(reservoir, 0)
|
||||
return c.last({ weight: 0, priority: 9 })
|
||||
})
|
||||
.then(function (results) {
|
||||
c.checkResultsOrder([[1], [2], [3], [4], [5]])
|
||||
c.mustEqual(calledDepleted, 2)
|
||||
c.checkDuration(300)
|
||||
})
|
||||
})
|
||||
|
||||
it('Should allow staggered X by Y type usage', function () {
|
||||
c = makeTest({
|
||||
reservoir: 2,
|
||||
reservoirRefreshInterval: 150,
|
||||
reservoirRefreshAmount: 2,
|
||||
heartbeatInterval: 75 // not for production use
|
||||
})
|
||||
|
||||
return Promise.all([
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 1), 1),
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 2), 2),
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 3), 3),
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 4), 4)
|
||||
])
|
||||
.then(function () {
|
||||
return c.limiter.currentReservoir()
|
||||
})
|
||||
.then(function (reservoir) {
|
||||
c.mustEqual(reservoir, 0)
|
||||
return c.last({ weight: 0, priority: 9 })
|
||||
})
|
||||
.then(function (results) {
|
||||
c.checkResultsOrder([[1], [2], [3], [4]])
|
||||
c.checkDuration(150)
|
||||
})
|
||||
})
|
||||
|
||||
it('Should keep process alive until queue is empty', function (done) {
|
||||
c = makeTest()
|
||||
var options = {
|
||||
cwd: process.cwd() + '/test/spawn',
|
||||
timeout: 1000
|
||||
}
|
||||
child_process.exec('node refreshKeepAlive.js', options, function (err, stdout, stderr) {
|
||||
c.mustEqual(stdout, '[0][0][2][2]')
|
||||
c.mustEqual(stderr, '')
|
||||
done(err)
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
describe('Reservoir Increase', function () {
|
||||
it('Should auto-increase the reservoir', async function () {
|
||||
c = makeTest({
|
||||
reservoir: 3,
|
||||
reservoirIncreaseInterval: 150,
|
||||
reservoirIncreaseAmount: 5,
|
||||
heartbeatInterval: 75 // not for production use
|
||||
})
|
||||
var calledDepleted = 0
|
||||
|
||||
c.limiter.on('depleted', function () {
|
||||
calledDepleted++
|
||||
})
|
||||
|
||||
await Promise.all([
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 1 }, c.promise, null, 1), 1),
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 2 }, c.promise, null, 2), 2),
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 3 }, c.promise, null, 3), 3),
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 4 }, c.promise, null, 4), 4),
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 5 }, c.promise, null, 5), 5)
|
||||
])
|
||||
const reservoir = await c.limiter.currentReservoir()
|
||||
c.mustEqual(reservoir, 3)
|
||||
|
||||
const results = await c.last({ weight: 0, priority: 9 })
|
||||
c.checkResultsOrder([[1], [2], [3], [4], [5]])
|
||||
c.mustEqual(calledDepleted, 1)
|
||||
c.checkDuration(450)
|
||||
})
|
||||
|
||||
it('Should auto-increase the reservoir up to a maximum', async function () {
|
||||
c = makeTest({
|
||||
reservoir: 3,
|
||||
reservoirIncreaseInterval: 150,
|
||||
reservoirIncreaseAmount: 5,
|
||||
reservoirIncreaseMaximum: 6,
|
||||
heartbeatInterval: 75 // not for production use
|
||||
})
|
||||
var calledDepleted = 0
|
||||
|
||||
c.limiter.on('depleted', function () {
|
||||
calledDepleted++
|
||||
})
|
||||
|
||||
await Promise.all([
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 1 }, c.promise, null, 1), 1),
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 2 }, c.promise, null, 2), 2),
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 3 }, c.promise, null, 3), 3),
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 4 }, c.promise, null, 4), 4),
|
||||
c.pNoErrVal(c.limiter.schedule({ weight: 5 }, c.promise, null, 5), 5)
|
||||
])
|
||||
const reservoir = await c.limiter.currentReservoir()
|
||||
c.mustEqual(reservoir, 1)
|
||||
|
||||
const results = await c.last({ weight: 0, priority: 9 })
|
||||
c.checkResultsOrder([[1], [2], [3], [4], [5]])
|
||||
c.mustEqual(calledDepleted, 1)
|
||||
c.checkDuration(450)
|
||||
})
|
||||
|
||||
it('Should allow staggered X by Y type usage', function () {
|
||||
c = makeTest({
|
||||
reservoir: 2,
|
||||
reservoirIncreaseInterval: 150,
|
||||
reservoirIncreaseAmount: 2,
|
||||
heartbeatInterval: 75 // not for production use
|
||||
})
|
||||
|
||||
return Promise.all([
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 1), 1),
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 2), 2),
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 3), 3),
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 4), 4)
|
||||
])
|
||||
.then(function () {
|
||||
return c.limiter.currentReservoir()
|
||||
})
|
||||
.then(function (reservoir) {
|
||||
c.mustEqual(reservoir, 0)
|
||||
return c.last({ weight: 0, priority: 9 })
|
||||
})
|
||||
.then(function (results) {
|
||||
c.checkResultsOrder([[1], [2], [3], [4]])
|
||||
c.checkDuration(150)
|
||||
})
|
||||
})
|
||||
|
||||
it('Should keep process alive until queue is empty', function (done) {
|
||||
c = makeTest()
|
||||
var options = {
|
||||
cwd: process.cwd() + '/test/spawn',
|
||||
timeout: 1000
|
||||
}
|
||||
child_process.exec('node increaseKeepAlive.js', options, function (err, stdout, stderr) {
|
||||
c.mustEqual(stdout, '[0][0][2][2]')
|
||||
c.mustEqual(stderr, '')
|
||||
done(err)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
})
|
255
node_modules/bottleneck/test/group.js
generated
vendored
Normal file
255
node_modules/bottleneck/test/group.js
generated
vendored
Normal file
|
@ -0,0 +1,255 @@
|
|||
var makeTest = require('./context')
|
||||
var Bottleneck = require('./bottleneck')
|
||||
var assert = require('assert')
|
||||
|
||||
describe('Group', function () {
|
||||
var c
|
||||
|
||||
afterEach(function () {
|
||||
return c.limiter.disconnect(false)
|
||||
})
|
||||
|
||||
it('Should create limiters', function (done) {
|
||||
c = makeTest()
|
||||
var group = new Bottleneck.Group({
|
||||
maxConcurrent: 1, minTime: 100
|
||||
})
|
||||
|
||||
var results = []
|
||||
|
||||
var job = function (...result) {
|
||||
results.push(result)
|
||||
return new Promise(function (resolve, reject) {
|
||||
setTimeout(function () {
|
||||
return resolve()
|
||||
}, 50)
|
||||
})
|
||||
}
|
||||
|
||||
group.key('A').schedule(job, 1, 2)
|
||||
group.key('A').schedule(job, 3)
|
||||
group.key('A').schedule(job, 4)
|
||||
setTimeout(function () {
|
||||
group.key('B').schedule(job, 5)
|
||||
}, 20)
|
||||
setTimeout(function () {
|
||||
group.key('C').schedule(job, 6)
|
||||
group.key('C').schedule(job, 7)
|
||||
}, 40)
|
||||
|
||||
group.key('A').submit(function (cb) {
|
||||
c.mustEqual(results, [[1,2], [5], [6], [3], [7], [4]])
|
||||
cb()
|
||||
done()
|
||||
}, null)
|
||||
})
|
||||
|
||||
it('Should set up the limiter IDs (default)', function () {
|
||||
c = makeTest()
|
||||
var group = new Bottleneck.Group({
|
||||
maxConcurrent: 1, minTime: 100
|
||||
})
|
||||
|
||||
c.mustEqual(group.key('A').id, 'group-key-A')
|
||||
c.mustEqual(group.key('B').id, 'group-key-B')
|
||||
c.mustEqual(group.key('XYZ').id, 'group-key-XYZ')
|
||||
|
||||
var ids = group.keys().map(function (key) {
|
||||
var limiter = group.key(key)
|
||||
c.mustEqual(limiter._store.timeout, group.timeout)
|
||||
return limiter.id
|
||||
})
|
||||
c.mustEqual(ids.sort(), ['group-key-A', 'group-key-B', 'group-key-XYZ'])
|
||||
})
|
||||
|
||||
it('Should set up the limiter IDs (custom)', function () {
|
||||
c = makeTest()
|
||||
var group = new Bottleneck.Group({
|
||||
maxConcurrent: 1, minTime: 100,
|
||||
id: 'custom-id'
|
||||
})
|
||||
|
||||
c.mustEqual(group.key('A').id, 'custom-id-A')
|
||||
c.mustEqual(group.key('B').id, 'custom-id-B')
|
||||
c.mustEqual(group.key('XYZ').id, 'custom-id-XYZ')
|
||||
|
||||
var ids = group.keys().map(function (key) {
|
||||
var limiter = group.key(key)
|
||||
c.mustEqual(limiter._store.timeout, group.timeout)
|
||||
return limiter.id
|
||||
})
|
||||
c.mustEqual(ids.sort(), ['custom-id-A', 'custom-id-B', 'custom-id-XYZ'])
|
||||
})
|
||||
|
||||
it('Should pass new limiter to \'created\' event', function () {
|
||||
c = makeTest()
|
||||
var group = new Bottleneck.Group({
|
||||
maxConcurrent: 1, minTime: 100
|
||||
})
|
||||
|
||||
var keys = []
|
||||
var ids = []
|
||||
var promises = []
|
||||
group.on('created', function (created, key) {
|
||||
keys.push(key)
|
||||
promises.push(
|
||||
created.updateSettings({ id: key })
|
||||
.then(function (limiter) {
|
||||
ids.push(limiter.id)
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
group.key('A')
|
||||
group.key('B')
|
||||
group.key('A')
|
||||
group.key('B')
|
||||
group.key('B')
|
||||
group.key('BB')
|
||||
group.key('C')
|
||||
group.key('A')
|
||||
|
||||
return Promise.all(promises)
|
||||
.then(function () {
|
||||
c.mustEqual(keys, ids)
|
||||
return c.limiter.ready()
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
it('Should pass error on failure', function (done) {
|
||||
var failureMessage = 'SOMETHING BLEW UP!!'
|
||||
c = makeTest()
|
||||
var group = new Bottleneck.Group({
|
||||
maxConcurrent: 1, minTime: 100
|
||||
})
|
||||
c.mustEqual(Object.keys(group.limiters), [])
|
||||
|
||||
var results = []
|
||||
|
||||
var job = function (...result) {
|
||||
results.push(result)
|
||||
return new Promise(function (resolve, reject) {
|
||||
setTimeout(function () {
|
||||
return resolve()
|
||||
}, 50)
|
||||
})
|
||||
}
|
||||
|
||||
group.key('A').schedule(job, 1, 2)
|
||||
group.key('A').schedule(job, 3)
|
||||
group.key('A').schedule(job, 4)
|
||||
group.key('B').schedule(() => Promise.reject(new Error(failureMessage)))
|
||||
.catch(function (err) {
|
||||
results.push(['CAUGHT', err.message])
|
||||
})
|
||||
setTimeout(function () {
|
||||
group.key('C').schedule(job, 6)
|
||||
group.key('C').schedule(job, 7)
|
||||
}, 40)
|
||||
|
||||
|
||||
group.key('A').submit(function (cb) {
|
||||
c.mustEqual(results, [[1,2], ['CAUGHT', failureMessage], [6], [3], [7], [4]])
|
||||
cb()
|
||||
done()
|
||||
}, null)
|
||||
})
|
||||
|
||||
it('Should update its timeout', function () {
|
||||
c = makeTest()
|
||||
var group1 = new Bottleneck.Group({
|
||||
maxConcurrent: 1, minTime: 100
|
||||
})
|
||||
var group2 = new Bottleneck.Group({
|
||||
maxConcurrent: 1, minTime: 100, timeout: 5000
|
||||
})
|
||||
|
||||
c.mustEqual(group1.timeout, 300000)
|
||||
c.mustEqual(group2.timeout, 5000)
|
||||
|
||||
var p1 = group1.updateSettings({ timeout: 123 })
|
||||
var p2 = group2.updateSettings({ timeout: 456 })
|
||||
return Promise.all([p1, p2])
|
||||
.then(function () {
|
||||
c.mustEqual(group1.timeout, 123)
|
||||
c.mustEqual(group2.timeout, 456)
|
||||
})
|
||||
})
|
||||
|
||||
it('Should update its limiter options', function () {
|
||||
c = makeTest()
|
||||
var group = new Bottleneck.Group({
|
||||
maxConcurrent: 1, minTime: 100
|
||||
})
|
||||
|
||||
var limiter1 = group.key('AAA')
|
||||
c.mustEqual(limiter1._store.storeOptions.minTime, 100)
|
||||
|
||||
group.updateSettings({ minTime: 200 })
|
||||
c.mustEqual(limiter1._store.storeOptions.minTime, 100)
|
||||
|
||||
var limiter2 = group.key('BBB')
|
||||
c.mustEqual(limiter2._store.storeOptions.minTime, 200)
|
||||
})
|
||||
|
||||
it('Should support keys(), limiters(), deleteKey()', function () {
|
||||
c = makeTest()
|
||||
var group1 = new Bottleneck.Group({
|
||||
maxConcurrent: 1
|
||||
})
|
||||
var KEY_A = "AAA"
|
||||
var KEY_B = "BBB"
|
||||
|
||||
return Promise.all([
|
||||
c.pNoErrVal(group1.key(KEY_A).schedule(c.promise, null, 1), 1),
|
||||
c.pNoErrVal(group1.key(KEY_B).schedule(c.promise, null, 2), 2)
|
||||
])
|
||||
.then(function () {
|
||||
var keys = group1.keys()
|
||||
var limiters = group1.limiters()
|
||||
c.mustEqual(keys, [KEY_A, KEY_B])
|
||||
c.mustEqual(limiters.length, 2)
|
||||
|
||||
limiters.forEach(function (limiter, i) {
|
||||
c.mustEqual(limiter.key, keys[i])
|
||||
assert(limiter.limiter instanceof Bottleneck)
|
||||
})
|
||||
|
||||
return group1.deleteKey(KEY_A)
|
||||
})
|
||||
.then(function (deleted) {
|
||||
c.mustEqual(deleted, true)
|
||||
c.mustEqual(group1.keys().length, 1)
|
||||
return group1.deleteKey(KEY_A)
|
||||
})
|
||||
.then(function (deleted) {
|
||||
c.mustEqual(deleted, false)
|
||||
c.mustEqual(group1.keys().length, 1)
|
||||
})
|
||||
})
|
||||
|
||||
it('Should call autocleanup', function () {
|
||||
var KEY = 'test-key'
|
||||
var group = new Bottleneck.Group({
|
||||
maxConcurrent: 1
|
||||
})
|
||||
group.updateSettings({ timeout: 50 })
|
||||
c = makeTest({ id: 'something', timeout: group.timeout })
|
||||
|
||||
group.instances[KEY] = c.limiter
|
||||
return group.key(KEY).schedule(function () {
|
||||
return Promise.resolve()
|
||||
})
|
||||
.then(function () {
|
||||
assert(group.instances[KEY] != null)
|
||||
return new Promise(function (resolve, reject) {
|
||||
setTimeout(resolve, 100)
|
||||
})
|
||||
})
|
||||
.then(function () {
|
||||
assert(group.instances[KEY] == null)
|
||||
})
|
||||
})
|
||||
|
||||
})
|
135
node_modules/bottleneck/test/ioredis.js
generated
vendored
Normal file
135
node_modules/bottleneck/test/ioredis.js
generated
vendored
Normal file
|
@ -0,0 +1,135 @@
|
|||
var makeTest = require('./context')
|
||||
var Bottleneck = require('./bottleneck')
|
||||
var assert = require('assert')
|
||||
var Redis = require('ioredis')
|
||||
|
||||
if (process.env.DATASTORE === 'ioredis') {
|
||||
describe('ioredis-only', function () {
|
||||
var c
|
||||
|
||||
afterEach(function () {
|
||||
return c.limiter.disconnect(false)
|
||||
})
|
||||
|
||||
it('Should accept ioredis lib override', function () {
|
||||
c = makeTest({
|
||||
maxConcurrent: 2,
|
||||
Redis,
|
||||
clientOptions: {},
|
||||
clusterNodes: [{
|
||||
host: process.env.REDIS_HOST,
|
||||
port: process.env.REDIS_PORT
|
||||
}]
|
||||
})
|
||||
|
||||
c.mustEqual(c.limiter.datastore, 'ioredis')
|
||||
})
|
||||
|
||||
it('Should connect in Redis Cluster mode', function () {
|
||||
c = makeTest({
|
||||
maxConcurrent: 2,
|
||||
clientOptions: {},
|
||||
clusterNodes: [{
|
||||
host: process.env.REDIS_HOST,
|
||||
port: process.env.REDIS_PORT
|
||||
}]
|
||||
})
|
||||
|
||||
c.mustEqual(c.limiter.datastore, 'ioredis')
|
||||
assert(c.limiter._store.connection.client.nodes().length >= 0)
|
||||
})
|
||||
|
||||
it('Should connect in Redis Cluster mode with premade client', function () {
|
||||
var client = new Redis.Cluster('')
|
||||
var connection = new Bottleneck.IORedisConnection({ client })
|
||||
c = makeTest({
|
||||
maxConcurrent: 2,
|
||||
clientOptions: {},
|
||||
clusterNodes: [{
|
||||
host: process.env.REDIS_HOST,
|
||||
port: process.env.REDIS_PORT
|
||||
}]
|
||||
})
|
||||
|
||||
c.mustEqual(c.limiter.datastore, 'ioredis')
|
||||
assert(c.limiter._store.connection.client.nodes().length >= 0)
|
||||
connection.disconnect(false)
|
||||
})
|
||||
|
||||
it('Should accept existing connections', function () {
|
||||
var connection = new Bottleneck.IORedisConnection()
|
||||
connection.id = 'super-connection'
|
||||
c = makeTest({
|
||||
minTime: 50,
|
||||
connection
|
||||
})
|
||||
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 1), 1)
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 2), 2)
|
||||
|
||||
return c.last()
|
||||
.then(function (results) {
|
||||
c.checkResultsOrder([[1], [2]])
|
||||
c.checkDuration(50)
|
||||
c.mustEqual(c.limiter.connection.id, 'super-connection')
|
||||
c.mustEqual(c.limiter.datastore, 'ioredis')
|
||||
|
||||
return c.limiter.disconnect()
|
||||
})
|
||||
.then(function () {
|
||||
// Shared connections should not be disconnected by the limiter
|
||||
c.mustEqual(c.limiter.clients().client.status, 'ready')
|
||||
return connection.disconnect()
|
||||
})
|
||||
})
|
||||
|
||||
it('Should accept existing redis clients', function () {
|
||||
var client = new Redis()
|
||||
client.id = 'super-client'
|
||||
|
||||
var connection = new Bottleneck.IORedisConnection({ client })
|
||||
connection.id = 'super-connection'
|
||||
c = makeTest({
|
||||
minTime: 50,
|
||||
connection
|
||||
})
|
||||
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 1), 1)
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 2), 2)
|
||||
|
||||
return c.last()
|
||||
.then(function (results) {
|
||||
c.checkResultsOrder([[1], [2]])
|
||||
c.checkDuration(50)
|
||||
c.mustEqual(c.limiter.clients().client.id, 'super-client')
|
||||
c.mustEqual(c.limiter.connection.id, 'super-connection')
|
||||
c.mustEqual(c.limiter.datastore, 'ioredis')
|
||||
|
||||
return c.limiter.disconnect()
|
||||
})
|
||||
.then(function () {
|
||||
// Shared connections should not be disconnected by the limiter
|
||||
c.mustEqual(c.limiter.clients().client.status, 'ready')
|
||||
return connection.disconnect()
|
||||
})
|
||||
})
|
||||
|
||||
it('Should trigger error events on the shared connection', function (done) {
|
||||
var connection = new Bottleneck.IORedisConnection({
|
||||
clientOptions: {
|
||||
port: 1
|
||||
}
|
||||
})
|
||||
connection.on('error', function (err) {
|
||||
c.mustEqual(c.limiter.datastore, 'ioredis')
|
||||
connection.disconnect()
|
||||
done()
|
||||
})
|
||||
|
||||
c = makeTest({ connection })
|
||||
c.limiter.on('error', function (err) {
|
||||
done(err)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
100
node_modules/bottleneck/test/node_redis.js
generated
vendored
Normal file
100
node_modules/bottleneck/test/node_redis.js
generated
vendored
Normal file
|
@ -0,0 +1,100 @@
|
|||
var makeTest = require('./context')
|
||||
var Bottleneck = require('./bottleneck')
|
||||
var assert = require('assert')
|
||||
var Redis = require('redis')
|
||||
|
||||
if (process.env.DATASTORE === 'redis') {
|
||||
describe('node_redis-only', function () {
|
||||
var c
|
||||
|
||||
afterEach(function () {
|
||||
return c.limiter.disconnect(false)
|
||||
})
|
||||
|
||||
it('Should accept node_redis lib override', function () {
|
||||
c = makeTest({
|
||||
maxConcurrent: 2,
|
||||
Redis,
|
||||
clientOptions: {}
|
||||
})
|
||||
|
||||
c.mustEqual(c.limiter.datastore, 'redis')
|
||||
})
|
||||
|
||||
it('Should accept existing connections', function () {
|
||||
var connection = new Bottleneck.RedisConnection()
|
||||
connection.id = 'super-connection'
|
||||
c = makeTest({
|
||||
minTime: 50,
|
||||
connection
|
||||
})
|
||||
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 1), 1)
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 2), 2)
|
||||
|
||||
return c.last()
|
||||
.then(function (results) {
|
||||
c.checkResultsOrder([[1], [2]])
|
||||
c.checkDuration(50)
|
||||
c.mustEqual(c.limiter.connection.id, 'super-connection')
|
||||
c.mustEqual(c.limiter.datastore, 'redis')
|
||||
|
||||
return c.limiter.disconnect()
|
||||
})
|
||||
.then(function () {
|
||||
// Shared connections should not be disconnected by the limiter
|
||||
c.mustEqual(c.limiter.clients().client.ready, true)
|
||||
return connection.disconnect()
|
||||
})
|
||||
})
|
||||
|
||||
it('Should accept existing redis clients', function () {
|
||||
var client = Redis.createClient()
|
||||
client.id = 'super-client'
|
||||
|
||||
var connection = new Bottleneck.RedisConnection({ client })
|
||||
connection.id = 'super-connection'
|
||||
c = makeTest({
|
||||
minTime: 50,
|
||||
connection
|
||||
})
|
||||
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 1), 1)
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 2), 2)
|
||||
|
||||
return c.last()
|
||||
.then(function (results) {
|
||||
c.checkResultsOrder([[1], [2]])
|
||||
c.checkDuration(50)
|
||||
c.mustEqual(c.limiter.clients().client.id, 'super-client')
|
||||
c.mustEqual(c.limiter.connection.id, 'super-connection')
|
||||
c.mustEqual(c.limiter.datastore, 'redis')
|
||||
|
||||
return c.limiter.disconnect()
|
||||
})
|
||||
.then(function () {
|
||||
// Shared connections should not be disconnected by the limiter
|
||||
c.mustEqual(c.limiter.clients().client.ready, true)
|
||||
return connection.disconnect()
|
||||
})
|
||||
})
|
||||
|
||||
it('Should trigger error events on the shared connection', function (done) {
|
||||
var connection = new Bottleneck.RedisConnection({
|
||||
clientOptions: {
|
||||
port: 1
|
||||
}
|
||||
})
|
||||
connection.on('error', function (err) {
|
||||
c.mustEqual(c.limiter.datastore, 'redis')
|
||||
connection.disconnect()
|
||||
done()
|
||||
})
|
||||
|
||||
c = makeTest({ connection })
|
||||
c.limiter.on('error', function (err) {
|
||||
done(err)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
184
node_modules/bottleneck/test/priority.js
generated
vendored
Normal file
184
node_modules/bottleneck/test/priority.js
generated
vendored
Normal file
|
@ -0,0 +1,184 @@
|
|||
var makeTest = require('./context')
|
||||
var Bottleneck = require('./bottleneck')
|
||||
var assert = require('assert')
|
||||
|
||||
describe('Priority', function () {
|
||||
var c
|
||||
|
||||
afterEach(function () {
|
||||
return c.limiter.disconnect(false)
|
||||
})
|
||||
|
||||
it('Should do basic ordering', function () {
|
||||
c = makeTest({maxConcurrent: 1, minTime: 100, rejectOnDrop: false})
|
||||
|
||||
return Promise.all([
|
||||
c.pNoErrVal(c.limiter.schedule(c.slowPromise, 50, null, 1), 1),
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 2), 2),
|
||||
c.pNoErrVal(c.limiter.schedule({priority: 1}, c.promise, null, 5, 6), 5, 6),
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 3), 3),
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 4), 4)
|
||||
])
|
||||
.then(function () {
|
||||
return c.last()
|
||||
})
|
||||
.then(function (results) {
|
||||
c.checkResultsOrder([[1], [5,6], [2] ,[3], [4]])
|
||||
c.checkDuration(400)
|
||||
})
|
||||
})
|
||||
|
||||
it('Should support LEAK', function () {
|
||||
c = makeTest({
|
||||
maxConcurrent: 1,
|
||||
minTime: 100,
|
||||
highWater: 3,
|
||||
strategy: Bottleneck.strategy.LEAK,
|
||||
rejectOnDrop: false
|
||||
})
|
||||
|
||||
var called = false
|
||||
c.limiter.on('dropped', function (dropped) {
|
||||
c.mustExist(dropped.task)
|
||||
c.mustExist(dropped.args)
|
||||
c.mustExist(dropped.promise)
|
||||
called = true
|
||||
})
|
||||
|
||||
c.limiter.submit(c.slowJob, 50, null, 1, c.noErrVal(1))
|
||||
c.limiter.submit(c.job, null, 2, c.noErrVal(2))
|
||||
c.limiter.submit(c.job, null, 3, c.noErrVal(3))
|
||||
c.limiter.submit(c.job, null, 4, c.noErrVal(4))
|
||||
c.limiter.submit({priority: 2}, c.job, null, 5, c.noErrVal(5))
|
||||
c.limiter.submit({priority: 1}, c.job, null, 6, c.noErrVal(6))
|
||||
c.limiter.submit({priority: 9}, c.job, null, 7, c.noErrVal(7))
|
||||
|
||||
return c.last({ weight: 0 })
|
||||
.then(function (results) {
|
||||
c.checkDuration(200)
|
||||
c.checkResultsOrder([[1], [6], [5]])
|
||||
c.mustEqual(called, true)
|
||||
})
|
||||
})
|
||||
|
||||
it('Should support OVERFLOW', function () {
|
||||
c = makeTest({
|
||||
maxConcurrent: 1,
|
||||
minTime: 100,
|
||||
highWater: 2,
|
||||
strategy: Bottleneck.strategy.OVERFLOW,
|
||||
rejectOnDrop: false
|
||||
})
|
||||
var called = false
|
||||
c.limiter.on('dropped', function (dropped) {
|
||||
c.mustExist(dropped.task)
|
||||
c.mustExist(dropped.args)
|
||||
c.mustExist(dropped.promise)
|
||||
called = true
|
||||
})
|
||||
|
||||
c.limiter.submit(c.slowJob, 50, null, 1, c.noErrVal(1))
|
||||
c.limiter.submit(c.job, null, 2, c.noErrVal(2))
|
||||
c.limiter.submit(c.job, null, 3, c.noErrVal(3))
|
||||
c.limiter.submit(c.job, null, 4, c.noErrVal(4))
|
||||
c.limiter.submit({priority: 2}, c.job, null, 5, c.noErrVal(5))
|
||||
c.limiter.submit({priority: 1}, c.job, null, 6, c.noErrVal(6))
|
||||
|
||||
return c.limiter.submit({priority: 9}, c.job, null, 7, c.noErrVal(7))
|
||||
.then(function () {
|
||||
return c.limiter.updateSettings({ highWater: null })
|
||||
})
|
||||
.then(c.last)
|
||||
.then(function (results) {
|
||||
c.checkDuration(200)
|
||||
c.checkResultsOrder([[1], [2], [3]])
|
||||
c.mustEqual(called, true)
|
||||
})
|
||||
})
|
||||
|
||||
it('Should support OVERFLOW_PRIORITY', function () {
|
||||
c = makeTest({
|
||||
maxConcurrent: 1,
|
||||
minTime: 100,
|
||||
highWater: 2,
|
||||
strategy: Bottleneck.strategy.OVERFLOW_PRIORITY,
|
||||
rejectOnDrop: false
|
||||
})
|
||||
var called = false
|
||||
c.limiter.on('dropped', function (dropped) {
|
||||
c.mustExist(dropped.task)
|
||||
c.mustExist(dropped.args)
|
||||
c.mustExist(dropped.promise)
|
||||
called = true
|
||||
})
|
||||
|
||||
c.limiter.submit(c.slowJob, 50, null, 1, c.noErrVal(1))
|
||||
c.limiter.submit(c.job, null, 2, c.noErrVal(2))
|
||||
c.limiter.submit(c.job, null, 3, c.noErrVal(3))
|
||||
c.limiter.submit(c.job, null, 4, c.noErrVal(4))
|
||||
c.limiter.submit({priority: 2}, c.job, null, 5, c.noErrVal(5))
|
||||
c.limiter.submit({priority: 2}, c.job, null, 6, c.noErrVal(6))
|
||||
|
||||
return c.limiter.submit({priority: 2}, c.job, null, 7, c.noErrVal(7))
|
||||
.then(function () {
|
||||
return c.limiter.updateSettings({highWater: null})
|
||||
})
|
||||
.then(c.last)
|
||||
.then(function (results) {
|
||||
c.checkDuration(200)
|
||||
c.checkResultsOrder([[1], [5], [6]])
|
||||
c.mustEqual(called, true)
|
||||
})
|
||||
})
|
||||
|
||||
it('Should support BLOCK', function (done) {
|
||||
c = makeTest({
|
||||
maxConcurrent: 1,
|
||||
minTime: 100,
|
||||
highWater: 2,
|
||||
trackDoneStatus: true,
|
||||
strategy: Bottleneck.strategy.BLOCK
|
||||
})
|
||||
var called = 0
|
||||
|
||||
c.limiter.on('dropped', function (dropped) {
|
||||
c.mustExist(dropped.task)
|
||||
c.mustExist(dropped.args)
|
||||
c.mustExist(dropped.promise)
|
||||
called++
|
||||
if (called === 3) {
|
||||
c.limiter.updateSettings({ highWater: null })
|
||||
.then(function () {
|
||||
return c.limiter.schedule(c.job, null, 8)
|
||||
})
|
||||
.catch(function (err) {
|
||||
assert(err instanceof Bottleneck.BottleneckError)
|
||||
c.mustEqual(err.message, 'This job has been dropped by Bottleneck')
|
||||
c.limiter.removeAllListeners('error')
|
||||
done()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
c.limiter.submit(c.slowJob, 20, null, 1, c.noErrVal(1))
|
||||
c.limiter.submit(c.slowJob, 20, null, 2, (err) => c.mustExist(err))
|
||||
c.limiter.submit(c.slowJob, 20, null, 3, (err) => c.mustExist(err))
|
||||
c.limiter.submit(c.slowJob, 20, null, 4, (err) => c.mustExist(err))
|
||||
})
|
||||
|
||||
it('Should have the right priority', function () {
|
||||
c = makeTest({maxConcurrent: 1, minTime: 100})
|
||||
|
||||
c.pNoErrVal(c.limiter.schedule({priority: 6}, c.slowPromise, 50, null, 1), 1)
|
||||
c.pNoErrVal(c.limiter.schedule({priority: 5}, c.promise, null, 2), 2)
|
||||
c.pNoErrVal(c.limiter.schedule({priority: 4}, c.promise, null, 3), 3)
|
||||
c.pNoErrVal(c.limiter.schedule({priority: 3}, c.promise, null, 4), 4)
|
||||
|
||||
return c.last()
|
||||
.then(function (results) {
|
||||
c.checkDuration(300)
|
||||
c.checkResultsOrder([[1], [4], [3], [2]])
|
||||
})
|
||||
})
|
||||
|
||||
})
|
202
node_modules/bottleneck/test/promises.js
generated
vendored
Normal file
202
node_modules/bottleneck/test/promises.js
generated
vendored
Normal file
|
@ -0,0 +1,202 @@
|
|||
var makeTest = require('./context')
|
||||
var Bottleneck = require('./bottleneck')
|
||||
var assert = require('assert')
|
||||
|
||||
describe('Promises', function () {
|
||||
var c
|
||||
|
||||
afterEach(function () {
|
||||
return c.limiter.disconnect(false)
|
||||
})
|
||||
|
||||
it('Should support promises', function () {
|
||||
c = makeTest({maxConcurrent: 1, minTime: 100})
|
||||
|
||||
c.limiter.submit(c.job, null, 1, 9, c.noErrVal(1, 9))
|
||||
c.limiter.submit(c.job, null, 2, c.noErrVal(2))
|
||||
c.limiter.submit(c.job, null, 3, c.noErrVal(3))
|
||||
c.pNoErrVal(c.limiter.schedule(c.promise, null, 4, 5), 4, 5)
|
||||
|
||||
return c.last()
|
||||
.then(function (results) {
|
||||
c.checkResultsOrder([[1,9], [2], [3], [4,5]])
|
||||
c.checkDuration(300)
|
||||
})
|
||||
})
|
||||
|
||||
it('Should pass error on failure', function () {
|
||||
var failureMessage = 'failed'
|
||||
c = makeTest({maxConcurrent: 1, minTime: 100})
|
||||
|
||||
return c.limiter.schedule(c.promise, new Error(failureMessage))
|
||||
.catch(function (err) {
|
||||
c.mustEqual(err.message, failureMessage)
|
||||
})
|
||||
})
|
||||
|
||||
it('Should allow non-Promise returns', function () {
|
||||
c = makeTest()
|
||||
var str = 'This is a string'
|
||||
|
||||
return c.limiter.schedule(() => str)
|
||||
.then(function (x) {
|
||||
c.mustEqual(x, str)
|
||||
})
|
||||
})
|
||||
|
||||
it('Should get rejected when rejectOnDrop is true', function () {
|
||||
c = makeTest({
|
||||
maxConcurrent: 1,
|
||||
minTime: 0,
|
||||
highWater: 1,
|
||||
strategy: Bottleneck.strategy.OVERFLOW,
|
||||
rejectOnDrop: true
|
||||
})
|
||||
var dropped = 0
|
||||
var caught = 0
|
||||
var p1
|
||||
var p2
|
||||
|
||||
c.limiter.on('dropped', function () {
|
||||
dropped++
|
||||
})
|
||||
|
||||
p1 = c.pNoErrVal(c.limiter.schedule({id: 1}, c.slowPromise, 50, null, 1), 1)
|
||||
p2 = c.pNoErrVal(c.limiter.schedule({id: 2}, c.slowPromise, 50, null, 2), 2)
|
||||
|
||||
return c.limiter.schedule({id: 3}, c.slowPromise, 50, null, 3)
|
||||
.catch(function (err) {
|
||||
c.mustEqual(err.message, 'This job has been dropped by Bottleneck')
|
||||
assert(err instanceof Bottleneck.BottleneckError)
|
||||
caught++
|
||||
return Promise.all([p1, p2])
|
||||
})
|
||||
.then(c.last)
|
||||
.then(function (results) {
|
||||
c.checkResultsOrder([[1], [2]])
|
||||
c.checkDuration(100)
|
||||
c.mustEqual(dropped, 1)
|
||||
c.mustEqual(caught, 1)
|
||||
})
|
||||
})
|
||||
|
||||
it('Should automatically wrap an exception in a rejected promise - schedule()', function () {
|
||||
c = makeTest({maxConcurrent: 1, minTime: 100})
|
||||
|
||||
return c.limiter.schedule(() => {
|
||||
throw new Error('I will reject')
|
||||
})
|
||||
.then(() => assert(false))
|
||||
.catch(err => {
|
||||
assert(err.message === 'I will reject');
|
||||
})
|
||||
})
|
||||
|
||||
describe('Wrap', function () {
|
||||
it('Should wrap', function () {
|
||||
c = makeTest({maxConcurrent: 1, minTime: 100})
|
||||
|
||||
c.limiter.submit(c.job, null, 1, c.noErrVal(1))
|
||||
c.limiter.submit(c.job, null, 2, c.noErrVal(2))
|
||||
c.limiter.submit(c.job, null, 3, c.noErrVal(3))
|
||||
|
||||
var wrapped = c.limiter.wrap(c.promise)
|
||||
c.pNoErrVal(wrapped(null, 4), 4)
|
||||
|
||||
return c.last()
|
||||
.then(function (results) {
|
||||
c.checkResultsOrder([[1], [2], [3], [4]])
|
||||
c.checkDuration(300)
|
||||
})
|
||||
})
|
||||
|
||||
it('Should automatically wrap a returned value in a resolved promise', function () {
|
||||
c = makeTest({maxConcurrent: 1, minTime: 100})
|
||||
|
||||
fn = c.limiter.wrap(() => { return 7 });
|
||||
|
||||
return fn().then(result => {
|
||||
assert(result === 7);
|
||||
})
|
||||
})
|
||||
|
||||
it('Should automatically wrap an exception in a rejected promise', function () {
|
||||
c = makeTest({maxConcurrent: 1, minTime: 100})
|
||||
|
||||
fn = c.limiter.wrap(() => { throw new Error('I will reject') });
|
||||
|
||||
return fn().then(() => assert(false)).catch(error => {
|
||||
assert(error.message === 'I will reject');
|
||||
})
|
||||
})
|
||||
|
||||
it('Should inherit the original target for wrapped methods', function () {
|
||||
c = makeTest({maxConcurrent: 1, minTime: 100})
|
||||
|
||||
var object = {
|
||||
fn: c.limiter.wrap(function () { return this })
|
||||
}
|
||||
|
||||
return object.fn().then(result => {
|
||||
assert(result === object)
|
||||
})
|
||||
})
|
||||
|
||||
it('Should inherit the original target on prototype methods', function () {
|
||||
c = makeTest({maxConcurrent: 1, minTime: 100})
|
||||
|
||||
class Animal {
|
||||
constructor(name) { this.name = name }
|
||||
getName() { return this.name }
|
||||
}
|
||||
|
||||
Animal.prototype.getName = c.limiter.wrap(Animal.prototype.getName)
|
||||
let elephant = new Animal('Dumbo')
|
||||
|
||||
return elephant.getName().then(result => {
|
||||
assert(result === 'Dumbo')
|
||||
})
|
||||
})
|
||||
|
||||
it('Should pass errors back', function () {
|
||||
var failureMessage = 'BLEW UP!!!'
|
||||
c = makeTest({maxConcurrent: 1, minTime: 100})
|
||||
|
||||
var wrapped = c.limiter.wrap(c.promise)
|
||||
c.pNoErrVal(wrapped(null, 1), 1)
|
||||
c.pNoErrVal(wrapped(null, 2), 2)
|
||||
|
||||
return wrapped(new Error(failureMessage), 3)
|
||||
.catch(function (err) {
|
||||
c.mustEqual(err.message, failureMessage)
|
||||
return c.last()
|
||||
})
|
||||
.then(function (results) {
|
||||
c.checkResultsOrder([[1], [2], [3]])
|
||||
c.checkDuration(200)
|
||||
})
|
||||
})
|
||||
|
||||
it('Should allow passing options', function () {
|
||||
var failureMessage = 'BLEW UP!!!'
|
||||
c = makeTest({maxConcurrent: 1, minTime: 50})
|
||||
|
||||
var wrapped = c.limiter.wrap(c.promise)
|
||||
c.pNoErrVal(wrapped(null, 1), 1)
|
||||
c.pNoErrVal(wrapped(null, 2), 2)
|
||||
c.pNoErrVal(wrapped(null, 3), 3)
|
||||
c.pNoErrVal(wrapped(null, 4), 4)
|
||||
c.pNoErrVal(wrapped.withOptions({ priority: 1 }, null, 5), 5)
|
||||
|
||||
return wrapped.withOptions({ priority: 1 }, new Error(failureMessage), 6)
|
||||
.catch(function (err) {
|
||||
c.mustEqual(err.message, failureMessage)
|
||||
return c.last()
|
||||
})
|
||||
.then(function (results) {
|
||||
c.checkResultsOrder([[1], [2], [5], [6], [3], [4]])
|
||||
c.checkDuration(250)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
237
node_modules/bottleneck/test/retries.js
generated
vendored
Normal file
237
node_modules/bottleneck/test/retries.js
generated
vendored
Normal file
|
@ -0,0 +1,237 @@
|
|||
var makeTest = require('./context')
|
||||
var Bottleneck = require('./bottleneck')
|
||||
var assert = require('assert')
|
||||
var child_process = require('child_process')
|
||||
|
||||
describe('Retries', function () {
|
||||
var c
|
||||
|
||||
afterEach(function () {
|
||||
return c.limiter.disconnect(false)
|
||||
})
|
||||
|
||||
it('Should retry when requested by the user (sync)', async function () {
|
||||
c = makeTest({ trackDoneStatus: true })
|
||||
var failedEvents = 0
|
||||
var retryEvents = 0
|
||||
|
||||
c.limiter.on('failed', function (error, info) {
|
||||
c.mustEqual(c.limiter.counts().EXECUTING, 1)
|
||||
c.mustEqual(info.retryCount, failedEvents)
|
||||
failedEvents++
|
||||
return 50
|
||||
})
|
||||
|
||||
c.limiter.on('retry', function (error, info) {
|
||||
c.mustEqual(c.limiter.counts().EXECUTING, 1)
|
||||
retryEvents++
|
||||
})
|
||||
|
||||
var times = 0
|
||||
const job = function () {
|
||||
times++
|
||||
if (times <= 2) {
|
||||
return Promise.reject(new Error('boom'))
|
||||
}
|
||||
return Promise.resolve('Success!')
|
||||
}
|
||||
|
||||
c.mustEqual(await c.limiter.schedule(job), 'Success!')
|
||||
const results = await c.results()
|
||||
assert(results.elapsed > 90 && results.elapsed < 130)
|
||||
c.mustEqual(failedEvents, 2)
|
||||
c.mustEqual(retryEvents, 2)
|
||||
c.mustEqual(c.limiter.counts().EXECUTING, 0)
|
||||
c.mustEqual(c.limiter.counts().DONE, 1)
|
||||
})
|
||||
|
||||
it('Should retry when requested by the user (async)', async function () {
|
||||
c = makeTest({ trackDoneStatus: true })
|
||||
var failedEvents = 0
|
||||
var retryEvents = 0
|
||||
|
||||
c.limiter.on('failed', function (error, info) {
|
||||
c.mustEqual(c.limiter.counts().EXECUTING, 1)
|
||||
c.mustEqual(info.retryCount, failedEvents)
|
||||
failedEvents++
|
||||
return Promise.resolve(50)
|
||||
})
|
||||
|
||||
c.limiter.on('retry', function (error, info) {
|
||||
c.mustEqual(c.limiter.counts().EXECUTING, 1)
|
||||
retryEvents++
|
||||
})
|
||||
|
||||
var times = 0
|
||||
const job = function () {
|
||||
times++
|
||||
if (times <= 2) {
|
||||
return Promise.reject(new Error('boom'))
|
||||
}
|
||||
return Promise.resolve('Success!')
|
||||
}
|
||||
|
||||
c.mustEqual(await c.limiter.schedule(job), 'Success!')
|
||||
const results = await c.results()
|
||||
assert(results.elapsed > 90 && results.elapsed < 130)
|
||||
c.mustEqual(failedEvents, 2)
|
||||
c.mustEqual(retryEvents, 2)
|
||||
c.mustEqual(c.limiter.counts().EXECUTING, 0)
|
||||
c.mustEqual(c.limiter.counts().DONE, 1)
|
||||
})
|
||||
|
||||
it('Should not retry when user returns an error (sync)', async function () {
|
||||
c = makeTest({ errorEventsExpected: true, trackDoneStatus: true })
|
||||
var failedEvents = 0
|
||||
var retryEvents = 0
|
||||
var errorEvents = 0
|
||||
var caught = false
|
||||
|
||||
c.limiter.on('failed', function (error, info) {
|
||||
c.mustEqual(c.limiter.counts().EXECUTING, 1)
|
||||
c.mustEqual(info.retryCount, failedEvents)
|
||||
failedEvents++
|
||||
throw new Error('Nope')
|
||||
})
|
||||
|
||||
c.limiter.on('retry', function (error, info) {
|
||||
retryEvents++
|
||||
})
|
||||
|
||||
c.limiter.on('error', function (error, info) {
|
||||
c.mustEqual(error.message, 'Nope')
|
||||
errorEvents++
|
||||
})
|
||||
|
||||
const job = function () {
|
||||
return Promise.reject(new Error('boom'))
|
||||
}
|
||||
|
||||
try {
|
||||
await c.limiter.schedule(job)
|
||||
throw new Error('Should not reach')
|
||||
} catch (error) {
|
||||
c.mustEqual(error.message, 'boom')
|
||||
caught = true
|
||||
}
|
||||
c.mustEqual(failedEvents, 1)
|
||||
c.mustEqual(retryEvents, 0)
|
||||
c.mustEqual(errorEvents, 1)
|
||||
c.mustEqual(caught, true)
|
||||
c.mustEqual(c.limiter.counts().EXECUTING, 0)
|
||||
c.mustEqual(c.limiter.counts().DONE, 1)
|
||||
})
|
||||
|
||||
it('Should not retry when user returns an error (async)', async function () {
|
||||
c = makeTest({ errorEventsExpected: true, trackDoneStatus: true })
|
||||
var failedEvents = 0
|
||||
var retryEvents = 0
|
||||
var errorEvents = 0
|
||||
var caught = false
|
||||
|
||||
c.limiter.on('failed', function (error, info) {
|
||||
c.mustEqual(c.limiter.counts().EXECUTING, 1)
|
||||
c.mustEqual(info.retryCount, failedEvents)
|
||||
failedEvents++
|
||||
return Promise.reject(new Error('Nope'))
|
||||
})
|
||||
|
||||
c.limiter.on('retry', function (error, info) {
|
||||
retryEvents++
|
||||
})
|
||||
|
||||
c.limiter.on('error', function (error, info) {
|
||||
c.mustEqual(error.message, 'Nope')
|
||||
errorEvents++
|
||||
})
|
||||
|
||||
const job = function () {
|
||||
return Promise.reject(new Error('boom'))
|
||||
}
|
||||
|
||||
try {
|
||||
await c.limiter.schedule(job)
|
||||
throw new Error('Should not reach')
|
||||
} catch (error) {
|
||||
c.mustEqual(error.message, 'boom')
|
||||
caught = true
|
||||
}
|
||||
c.mustEqual(failedEvents, 1)
|
||||
c.mustEqual(retryEvents, 0)
|
||||
c.mustEqual(errorEvents, 1)
|
||||
c.mustEqual(caught, true)
|
||||
c.mustEqual(c.limiter.counts().EXECUTING, 0)
|
||||
c.mustEqual(c.limiter.counts().DONE, 1)
|
||||
})
|
||||
|
||||
it('Should not retry when user returns null (sync)', async function () {
|
||||
c = makeTest({ trackDoneStatus: true })
|
||||
var failedEvents = 0
|
||||
var retryEvents = 0
|
||||
var caught = false
|
||||
|
||||
c.limiter.on('failed', function (error, info) {
|
||||
c.mustEqual(c.limiter.counts().EXECUTING, 1)
|
||||
c.mustEqual(info.retryCount, failedEvents)
|
||||
failedEvents++
|
||||
return null
|
||||
})
|
||||
|
||||
c.limiter.on('retry', function (error, info) {
|
||||
retryEvents++
|
||||
})
|
||||
|
||||
const job = function () {
|
||||
return Promise.reject(new Error('boom'))
|
||||
}
|
||||
|
||||
try {
|
||||
await c.limiter.schedule(job)
|
||||
throw new Error('Should not reach')
|
||||
} catch (error) {
|
||||
c.mustEqual(error.message, 'boom')
|
||||
caught = true
|
||||
}
|
||||
c.mustEqual(failedEvents, 1)
|
||||
c.mustEqual(retryEvents, 0)
|
||||
c.mustEqual(caught, true)
|
||||
c.mustEqual(c.limiter.counts().EXECUTING, 0)
|
||||
c.mustEqual(c.limiter.counts().DONE, 1)
|
||||
})
|
||||
|
||||
it('Should not retry when user returns null (async)', async function () {
|
||||
c = makeTest({ trackDoneStatus: true })
|
||||
var failedEvents = 0
|
||||
var retryEvents = 0
|
||||
var caught = false
|
||||
|
||||
c.limiter.on('failed', function (error, info) {
|
||||
c.mustEqual(c.limiter.counts().EXECUTING, 1)
|
||||
c.mustEqual(info.retryCount, failedEvents)
|
||||
failedEvents++
|
||||
return Promise.resolve(null)
|
||||
})
|
||||
|
||||
c.limiter.on('retry', function (error, info) {
|
||||
retryEvents++
|
||||
})
|
||||
|
||||
const job = function () {
|
||||
return Promise.reject(new Error('boom'))
|
||||
}
|
||||
|
||||
try {
|
||||
await c.limiter.schedule(job)
|
||||
throw new Error('Should not reach')
|
||||
} catch (error) {
|
||||
c.mustEqual(error.message, 'boom')
|
||||
caught = true
|
||||
}
|
||||
c.mustEqual(failedEvents, 1)
|
||||
c.mustEqual(retryEvents, 0)
|
||||
c.mustEqual(caught, true)
|
||||
c.mustEqual(c.limiter.counts().EXECUTING, 0)
|
||||
c.mustEqual(c.limiter.counts().DONE, 1)
|
||||
})
|
||||
|
||||
})
|
17
node_modules/bottleneck/test/spawn/increaseKeepAlive.js
generated
vendored
Normal file
17
node_modules/bottleneck/test/spawn/increaseKeepAlive.js
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
var Bottleneck = require('../bottleneck.js')
|
||||
var now = Date.now()
|
||||
|
||||
var limiter = new Bottleneck({
|
||||
reservoir: 2,
|
||||
reservoirIncreaseAmount: 2,
|
||||
reservoirIncreaseInterval: 200
|
||||
})
|
||||
var f1 = () => {
|
||||
var secDiff = Math.floor((Date.now() - now) / 100)
|
||||
return Promise.resolve(`[${secDiff}]`)
|
||||
}
|
||||
|
||||
limiter.schedule(f1).then((x) => process.stdout.write(x))
|
||||
limiter.schedule(f1).then((x) => process.stdout.write(x))
|
||||
limiter.schedule(f1).then((x) => process.stdout.write(x))
|
||||
limiter.schedule(f1).then((x) => process.stdout.write(x))
|
17
node_modules/bottleneck/test/spawn/refreshKeepAlive.js
generated
vendored
Normal file
17
node_modules/bottleneck/test/spawn/refreshKeepAlive.js
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
var Bottleneck = require('../bottleneck.js')
|
||||
var now = Date.now()
|
||||
|
||||
var limiter = new Bottleneck({
|
||||
reservoir: 2,
|
||||
reservoirRefreshAmount: 2,
|
||||
reservoirRefreshInterval: 200
|
||||
})
|
||||
var f1 = () => {
|
||||
var secDiff = Math.floor((Date.now() - now) / 100)
|
||||
return Promise.resolve(`[${secDiff}]`)
|
||||
}
|
||||
|
||||
limiter.schedule(f1).then((x) => process.stdout.write(x))
|
||||
limiter.schedule(f1).then((x) => process.stdout.write(x))
|
||||
limiter.schedule(f1).then((x) => process.stdout.write(x))
|
||||
limiter.schedule(f1).then((x) => process.stdout.write(x))
|
103
node_modules/bottleneck/test/states.js
generated
vendored
Normal file
103
node_modules/bottleneck/test/states.js
generated
vendored
Normal file
|
@ -0,0 +1,103 @@
|
|||
var States = require('../lib/States')
|
||||
var assert = require('assert')
|
||||
var c = require('./context')({datastore: 'local'})
|
||||
var Bottleneck = require('./bottleneck')
|
||||
|
||||
describe('States', function () {
|
||||
|
||||
it('Should be created and be empty', function () {
|
||||
var states = new States(["A", "B", "C"])
|
||||
c.mustEqual(states.statusCounts(), { A: 0, B: 0, C: 0 })
|
||||
})
|
||||
|
||||
it('Should start new series', function () {
|
||||
var states = new States(["A", "B", "C"])
|
||||
|
||||
states.start('x')
|
||||
states.start('y')
|
||||
|
||||
c.mustEqual(states.statusCounts(), { A: 2, B: 0, C: 0 })
|
||||
})
|
||||
|
||||
it('Should increment', function () {
|
||||
var states = new States(["A", "B", "C"])
|
||||
|
||||
states.start('x')
|
||||
states.start('y')
|
||||
states.next('x')
|
||||
states.next('y')
|
||||
states.next('x')
|
||||
c.mustEqual(states.statusCounts(), { A: 0, B: 1, C: 1 })
|
||||
|
||||
states.next('z')
|
||||
c.mustEqual(states.statusCounts(), { A: 0, B: 1, C: 1 })
|
||||
|
||||
states.next('x')
|
||||
c.mustEqual(states.statusCounts(), { A: 0, B: 1, C: 0 })
|
||||
|
||||
states.next('x')
|
||||
c.mustEqual(states.statusCounts(), { A: 0, B: 1, C: 0 })
|
||||
|
||||
states.next('y')
|
||||
states.next('y')
|
||||
c.mustEqual(states.statusCounts(), { A: 0, B: 0, C: 0 })
|
||||
})
|
||||
|
||||
it('Should remove', function () {
|
||||
var states = new States(["A", "B", "C"])
|
||||
|
||||
states.start('x')
|
||||
states.start('y')
|
||||
states.next('x')
|
||||
states.next('y')
|
||||
states.next('x')
|
||||
c.mustEqual(states.statusCounts(), { A: 0, B: 1, C: 1 })
|
||||
|
||||
states.remove('x')
|
||||
c.mustEqual(states.statusCounts(), { A: 0, B: 1, C: 0 })
|
||||
|
||||
states.remove('y')
|
||||
c.mustEqual(states.statusCounts(), { A: 0, B: 0, C: 0 })
|
||||
})
|
||||
|
||||
it('Should return current status', function () {
|
||||
var states = new States(["A", "B", "C"])
|
||||
|
||||
states.start('x')
|
||||
states.start('y')
|
||||
states.next('x')
|
||||
states.next('y')
|
||||
states.next('x')
|
||||
c.mustEqual(states.statusCounts(), { A: 0, B: 1, C: 1 })
|
||||
|
||||
c.mustEqual(states.jobStatus('x'), 'C')
|
||||
c.mustEqual(states.jobStatus('y'), 'B')
|
||||
c.mustEqual(states.jobStatus('z'), null)
|
||||
})
|
||||
|
||||
it('Should return job ids for a status', function (done) {
|
||||
var states = new States(["A", "B", "C"])
|
||||
|
||||
states.start('x')
|
||||
states.start('y')
|
||||
states.start('z')
|
||||
states.next('x')
|
||||
states.next('y')
|
||||
states.next('x')
|
||||
states.next('z')
|
||||
c.mustEqual(states.statusCounts(), { A: 0, B: 2, C: 1 })
|
||||
|
||||
c.mustEqual(states.statusJobs().sort(), ['x', 'y', 'z'])
|
||||
c.mustEqual(states.statusJobs('A'), [])
|
||||
c.mustEqual(states.statusJobs('B').sort(), ['y', 'z'])
|
||||
c.mustEqual(states.statusJobs('C'), ['x'])
|
||||
try {
|
||||
states.statusJobs('Z')
|
||||
} catch (err) {
|
||||
if (process.env.BUILD !== 'es5' && process.env.BUILD !== 'light') {
|
||||
assert(err instanceof Bottleneck.BottleneckError)
|
||||
}
|
||||
done()
|
||||
}
|
||||
})
|
||||
})
|
208
node_modules/bottleneck/test/stop.js
generated
vendored
Normal file
208
node_modules/bottleneck/test/stop.js
generated
vendored
Normal file
|
@ -0,0 +1,208 @@
|
|||
var makeTest = require('./context')
|
||||
var Bottleneck = require('./bottleneck')
|
||||
var assert = require('assert')
|
||||
|
||||
describe('Stop', function () {
|
||||
var c
|
||||
|
||||
afterEach(function () {
|
||||
return c.limiter.disconnect(false)
|
||||
})
|
||||
|
||||
it('Should stop and drop the queue', function (done) {
|
||||
c = makeTest({
|
||||
maxConcurrent: 2,
|
||||
minTime: 100,
|
||||
trackDoneStatus: true
|
||||
})
|
||||
var submitFailed = false
|
||||
var queuedDropped = false
|
||||
var scheduledDropped = false
|
||||
var dropped = 0
|
||||
|
||||
c.limiter.on('dropped', function () {
|
||||
dropped++
|
||||
})
|
||||
|
||||
c.pNoErrVal(c.limiter.schedule({id: '0'}, c.promise, null, 0), 0)
|
||||
|
||||
c.pNoErrVal(c.limiter.schedule({id: '1'}, c.slowPromise, 100, null, 1), 1)
|
||||
|
||||
c.limiter.schedule({id: '2'}, c.promise, null, 2)
|
||||
.catch(function (err) {
|
||||
c.mustEqual(err.message, 'Dropped!')
|
||||
scheduledDropped = true
|
||||
})
|
||||
|
||||
c.limiter.schedule({id: '3'}, c.promise, null, 3)
|
||||
.catch(function (err) {
|
||||
c.mustEqual(err.message, 'Dropped!')
|
||||
queuedDropped = true
|
||||
})
|
||||
|
||||
setTimeout(function () {
|
||||
var counts = c.limiter.counts()
|
||||
c.mustEqual(counts.RECEIVED, 0)
|
||||
c.mustEqual(counts.QUEUED, 1)
|
||||
c.mustEqual(counts.RUNNING, 1)
|
||||
c.mustEqual(counts.EXECUTING, 1)
|
||||
c.mustEqual(counts.DONE, 1)
|
||||
|
||||
c.limiter.stop({
|
||||
enqueueErrorMessage: 'Stopped!',
|
||||
dropErrorMessage: 'Dropped!'
|
||||
})
|
||||
.then(function () {
|
||||
counts = c.limiter.counts()
|
||||
c.mustEqual(submitFailed, true)
|
||||
c.mustEqual(scheduledDropped, true)
|
||||
c.mustEqual(queuedDropped, true)
|
||||
c.mustEqual(dropped, 2)
|
||||
c.mustEqual(counts.RECEIVED, 0)
|
||||
c.mustEqual(counts.QUEUED, 0)
|
||||
c.mustEqual(counts.RUNNING, 0)
|
||||
c.mustEqual(counts.EXECUTING, 0)
|
||||
c.mustEqual(counts.DONE, 2)
|
||||
|
||||
c.checkResultsOrder([[0], [1]])
|
||||
done()
|
||||
})
|
||||
|
||||
c.limiter.schedule(() => Promise.resolve(true))
|
||||
.catch(function (err) {
|
||||
c.mustEqual(err.message, 'Stopped!')
|
||||
submitFailed = true
|
||||
})
|
||||
|
||||
}, 125)
|
||||
})
|
||||
|
||||
it('Should stop and let the queue finish', function (done) {
|
||||
c = makeTest({
|
||||
maxConcurrent: 1,
|
||||
minTime: 100,
|
||||
trackDoneStatus: true
|
||||
})
|
||||
var submitFailed = false
|
||||
var dropped = 0
|
||||
|
||||
c.limiter.on('dropped', function () {
|
||||
dropped++
|
||||
})
|
||||
|
||||
c.pNoErrVal(c.limiter.schedule({id: '1'}, c.promise, null, 1), 1)
|
||||
c.pNoErrVal(c.limiter.schedule({id: '2'}, c.promise, null, 2), 2)
|
||||
c.pNoErrVal(c.limiter.schedule({id: '3'}, c.slowPromise, 100, null, 3), 3)
|
||||
|
||||
setTimeout(function () {
|
||||
var counts = c.limiter.counts()
|
||||
c.mustEqual(counts.RECEIVED, 0)
|
||||
c.mustEqual(counts.QUEUED, 1)
|
||||
c.mustEqual(counts.RUNNING, 1)
|
||||
c.mustEqual(counts.EXECUTING, 0)
|
||||
c.mustEqual(counts.DONE, 1)
|
||||
|
||||
c.limiter.stop({
|
||||
enqueueErrorMessage: 'Stopped!',
|
||||
dropWaitingJobs: false
|
||||
})
|
||||
.then(function () {
|
||||
counts = c.limiter.counts()
|
||||
c.mustEqual(submitFailed, true)
|
||||
c.mustEqual(dropped, 0)
|
||||
c.mustEqual(counts.RECEIVED, 0)
|
||||
c.mustEqual(counts.QUEUED, 0)
|
||||
c.mustEqual(counts.RUNNING, 0)
|
||||
c.mustEqual(counts.EXECUTING, 0)
|
||||
c.mustEqual(counts.DONE, 4)
|
||||
|
||||
c.checkResultsOrder([[1], [2], [3]])
|
||||
done()
|
||||
})
|
||||
|
||||
c.limiter.schedule(() => Promise.resolve(true))
|
||||
.catch(function (err) {
|
||||
c.mustEqual(err.message, 'Stopped!')
|
||||
submitFailed = true
|
||||
})
|
||||
|
||||
}, 75)
|
||||
})
|
||||
|
||||
it('Should still resolve when rejectOnDrop is false', function (done) {
|
||||
c = makeTest({
|
||||
maxConcurrent: 1,
|
||||
minTime: 100,
|
||||
rejectOnDrop: false
|
||||
})
|
||||
|
||||
c.pNoErrVal(c.limiter.schedule({id: '1'}, c.promise, null, 1), 1)
|
||||
c.pNoErrVal(c.limiter.schedule({id: '2'}, c.promise, null, 2), 2)
|
||||
c.pNoErrVal(c.limiter.schedule({id: '3'}, c.slowPromise, 100, null, 3), 3)
|
||||
|
||||
c.limiter.stop()
|
||||
.then(function () {
|
||||
return c.limiter.stop()
|
||||
})
|
||||
.then(function () {
|
||||
done(new Error("Should not be here"))
|
||||
})
|
||||
.catch(function (err) {
|
||||
c.mustEqual(err.message, "stop() has already been called")
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('Should not allow calling stop() twice when dropWaitingJobs=true', function (done) {
|
||||
c = makeTest({
|
||||
maxConcurrent: 1,
|
||||
minTime: 100
|
||||
})
|
||||
var failed = 0
|
||||
var handler = function (err) {
|
||||
c.mustEqual(err.message, "This limiter has been stopped.")
|
||||
failed++
|
||||
}
|
||||
|
||||
c.pNoErrVal(c.limiter.schedule({id: '1'}, c.promise, null, 1), 1).catch(handler)
|
||||
c.pNoErrVal(c.limiter.schedule({id: '2'}, c.promise, null, 2), 2).catch(handler)
|
||||
c.pNoErrVal(c.limiter.schedule({id: '3'}, c.slowPromise, 100, null, 3), 3).catch(handler)
|
||||
|
||||
c.limiter.stop({ dropWaitingJobs: true })
|
||||
.then(function () {
|
||||
return c.limiter.stop({ dropWaitingJobs: true })
|
||||
})
|
||||
.then(function () {
|
||||
done(new Error("Should not be here"))
|
||||
})
|
||||
.catch(function (err) {
|
||||
c.mustEqual(err.message, "stop() has already been called")
|
||||
c.mustEqual(failed, 3)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('Should not allow calling stop() twice when dropWaitingJobs=false', function (done) {
|
||||
c = makeTest({
|
||||
maxConcurrent: 1,
|
||||
minTime: 100
|
||||
})
|
||||
|
||||
c.pNoErrVal(c.limiter.schedule({id: '1'}, c.promise, null, 1), 1)
|
||||
c.pNoErrVal(c.limiter.schedule({id: '2'}, c.promise, null, 2), 2)
|
||||
c.pNoErrVal(c.limiter.schedule({id: '3'}, c.slowPromise, 100, null, 3), 3)
|
||||
|
||||
c.limiter.stop({ dropWaitingJobs: false })
|
||||
.then(function () {
|
||||
return c.limiter.stop({ dropWaitingJobs: false })
|
||||
})
|
||||
.then(function () {
|
||||
done(new Error("Should not be here"))
|
||||
})
|
||||
.catch(function (err) {
|
||||
c.mustEqual(err.message, "stop() has already been called")
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
})
|
Loading…
Add table
Add a link
Reference in a new issue