better-lock 1.0.0 → 2.0.1-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +24 -0
- package/.idea/better-lock.iml +1 -7
- package/.idea/codeStyles/Project.xml +336 -5
- package/.idea/compiler.xml +7 -0
- package/.idea/inspectionProfiles/Project_Default.xml +6 -2
- package/.idea/jsLibraryMappings.xml +0 -1
- package/.idea/modules.xml +1 -1
- package/.idea/prettier.xml +8 -0
- package/.prettierrc.yaml +1 -3
- package/.travis.yml +2 -2
- package/README.md +102 -53
- package/dist/better_lock.d.ts +50 -0
- package/dist/better_lock.js +317 -0
- package/dist/better_lock.js.map +1 -0
- package/dist/errors.d.ts +44 -0
- package/dist/errors.js +131 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/internals.d.ts +75 -0
- package/dist/internals.js +75 -0
- package/dist/internals.js.map +1 -0
- package/dist/options.d.ts +54 -0
- package/dist/options.js +3 -0
- package/dist/options.js.map +1 -0
- package/dist/tools.d.ts +19 -0
- package/dist/tools.js +109 -0
- package/dist/tools.js.map +1 -0
- package/dist/types.d.ts +23 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/jest.config.js +4 -0
- package/package.json +30 -8
- package/spec/better_lock.spec.ts +614 -0
- package/src/better_lock.ts +430 -0
- package/src/errors.ts +124 -0
- package/src/index.ts +54 -0
- package/src/internals.ts +118 -0
- package/src/options.ts +63 -0
- package/src/tools.ts +111 -0
- package/src/types.ts +29 -0
- package/tsconfig.json +13 -0
- package/.idea/markdown-navigator/profiles_settings.xml +0 -3
- package/.idea/markdown-navigator.xml +0 -78
- package/.idea/misc.xml +0 -6
- package/.idea/watcherTasks.xml +0 -8
- package/index.js +0 -19
- package/spec/better_lock.spec.js +0 -583
- package/src/better_lock.js +0 -400
- package/src/errors.js +0 -81
- package/src/options.js +0 -104
- package/src/tools.js +0 -125
- package/src/types.js +0 -110
package/spec/better_lock.spec.js
DELETED
|
@@ -1,583 +0,0 @@
|
|
|
1
|
-
const expect = require('chai').expect;
|
|
2
|
-
|
|
3
|
-
const { BetterLock } = require('../index');
|
|
4
|
-
|
|
5
|
-
describe('BetterLock', () => {
|
|
6
|
-
it('can run a simple happy path', testDone => {
|
|
7
|
-
const lock = new BetterLock();
|
|
8
|
-
const startedAt = new Date();
|
|
9
|
-
|
|
10
|
-
lock.acquire(waitWorker(250, 'a', 1, [new Error()]), (a1, a2, a3) => {
|
|
11
|
-
expect(new Date() - startedAt).to.be.within(245, 300);
|
|
12
|
-
expect(a1).to.equal('a');
|
|
13
|
-
expect(a2).to.equal(1);
|
|
14
|
-
expect(a3[0]).to.be.instanceOf(Error);
|
|
15
|
-
testDone();
|
|
16
|
-
});
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('will accept number as a name', testDone => {
|
|
20
|
-
const lock = new BetterLock();
|
|
21
|
-
|
|
22
|
-
let doneFirst = false;
|
|
23
|
-
lock.acquire(15, waitWorker(20), () => {
|
|
24
|
-
doneFirst = true;
|
|
25
|
-
|
|
26
|
-
testDone();
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
lock.acquire('15', () => {
|
|
30
|
-
expect(doneFirst).to.be.true;
|
|
31
|
-
});
|
|
32
|
-
lock.acquire(15, () => {
|
|
33
|
-
expect(doneFirst).to.be.true;
|
|
34
|
-
});
|
|
35
|
-
lock.acquire(16, () => {
|
|
36
|
-
expect(doneFirst).to.be.false;
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('can run locks with different keys concurrently', testDone => {
|
|
41
|
-
const lock = new BetterLock();
|
|
42
|
-
const startedAt = new Date();
|
|
43
|
-
let cbCount = 0;
|
|
44
|
-
|
|
45
|
-
lock.acquire(undefined, waitWorker(250, 'a'), res => {
|
|
46
|
-
expect(res).to.equal('a');
|
|
47
|
-
cb();
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
lock.acquire('', waitWorker(250, 'b'), res => {
|
|
51
|
-
expect(res).to.equal('b');
|
|
52
|
-
cb();
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
lock.acquire('Proper key', waitWorker(250, 'c'), res => {
|
|
56
|
-
expect(res).to.equal('c');
|
|
57
|
-
cb();
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
lock.acquire('proper key', waitWorker(250, 'd'), res => {
|
|
61
|
-
expect(res).to.equal('d');
|
|
62
|
-
cb();
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
function cb() {
|
|
66
|
-
cbCount++;
|
|
67
|
-
if (cbCount < 4) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
expect(new Date() - startedAt).to.be.within(245, 300);
|
|
72
|
-
testDone();
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('can execute multiple jobs one after another', testDone => {
|
|
77
|
-
const lock = new BetterLock({
|
|
78
|
-
wait_timeout: 100,
|
|
79
|
-
execution_timeout: 200, // should never trigger
|
|
80
|
-
queue_size: 5,
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
let called1 = false;
|
|
84
|
-
|
|
85
|
-
lock.acquire(waitWorker(50, null, 'ok1'), (err, res) => {
|
|
86
|
-
expect(err).to.be.null;
|
|
87
|
-
expect(res).to.equal('ok1');
|
|
88
|
-
called1 = true;
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
lock.acquire(waitWorker(150, null, 'ok2'), (err, res) => {
|
|
92
|
-
expect(err).to.be.null;
|
|
93
|
-
expect(res).to.equal('ok2');
|
|
94
|
-
expect(called1).to.be.true;
|
|
95
|
-
testDone();
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
it('will correctly tell caller if they can acquire lock', testDone => {
|
|
100
|
-
const lock = new BetterLock({});
|
|
101
|
-
|
|
102
|
-
expect(lock.canAcquire()).to.be.true;
|
|
103
|
-
expect(lock.canAcquire('test')).to.be.true;
|
|
104
|
-
|
|
105
|
-
lock.acquire(waitWorker(10), () => {});
|
|
106
|
-
lock.acquire('test', waitWorker(30), () => {
|
|
107
|
-
expect(lock.canAcquire()).to.be.true;
|
|
108
|
-
expect(lock.canAcquire('test')).to.be.true;
|
|
109
|
-
|
|
110
|
-
testDone();
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
expect(lock.canAcquire()).to.be.false;
|
|
114
|
-
expect(lock.canAcquire('test')).to.be.false;
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it('will log', testDone => {
|
|
118
|
-
let seq = 0;
|
|
119
|
-
const expected = [
|
|
120
|
-
'[MyLock] Enqueued Job #10 [My test]',
|
|
121
|
-
'[MyLock] Executing Job #10 [My test]',
|
|
122
|
-
'[MyLock] Done called for Job #10 [My test]',
|
|
123
|
-
];
|
|
124
|
-
|
|
125
|
-
const lock = new BetterLock({
|
|
126
|
-
name: 'MyLock',
|
|
127
|
-
log,
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
BetterLock.LockJob._lastId = 9;
|
|
131
|
-
lock.acquire('My test', waitWorker(100), () => {
|
|
132
|
-
testDone();
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
function log(msg) {
|
|
136
|
-
expect(msg).to.equal(expected[seq]);
|
|
137
|
-
seq++;
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
it('can change default options', () => {
|
|
142
|
-
const defaultOptions = BetterLock.DEFAULT_OPTIONS;
|
|
143
|
-
BetterLock.DEFAULT_OPTIONS = new BetterLock.Options({
|
|
144
|
-
name: 'MyLock',
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
let seq = 0;
|
|
148
|
-
const expected = [
|
|
149
|
-
'[MyLock] Enqueued Job #10 [My test]',
|
|
150
|
-
'[MyLock] Executing Job #10 [My test]',
|
|
151
|
-
'[MyLock] Done called for Job #10 [My test]',
|
|
152
|
-
];
|
|
153
|
-
|
|
154
|
-
const lock = new BetterLock({
|
|
155
|
-
log,
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
BetterLock.LockJob._lastId = 9;
|
|
159
|
-
|
|
160
|
-
return lock.acquire('My test', waitWorker(100)).then(
|
|
161
|
-
() => {
|
|
162
|
-
BetterLock.DEFAULT_OPTIONS = defaultOptions;
|
|
163
|
-
},
|
|
164
|
-
() => {
|
|
165
|
-
BetterLock.DEFAULT_OPTIONS = defaultOptions;
|
|
166
|
-
}
|
|
167
|
-
);
|
|
168
|
-
|
|
169
|
-
function log(msg) {
|
|
170
|
-
expect(msg).to.equal(expected[seq]);
|
|
171
|
-
seq++;
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
it('will accept custom promise tester', () => {
|
|
176
|
-
const lock = new BetterLock({
|
|
177
|
-
promise_tester: p => p.isPromise === true,
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
let called = false;
|
|
181
|
-
|
|
182
|
-
return Promise.all([
|
|
183
|
-
lock.acquire(() => {
|
|
184
|
-
return {
|
|
185
|
-
then: resolve => {
|
|
186
|
-
called = true;
|
|
187
|
-
resolve();
|
|
188
|
-
},
|
|
189
|
-
isPromise: true,
|
|
190
|
-
};
|
|
191
|
-
}),
|
|
192
|
-
]).then(() => {
|
|
193
|
-
expect(called).to.be.true;
|
|
194
|
-
});
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
it('jobs will timeout after waiting in queue for too long', testDone => {
|
|
198
|
-
const lock = new BetterLock({
|
|
199
|
-
wait_timeout: 50,
|
|
200
|
-
execution_timeout: 100, // should never trigger
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
let cbCount = 0;
|
|
204
|
-
|
|
205
|
-
lock.acquire(waitWorker(75, null, 'ok1'), (err, res) => {
|
|
206
|
-
expect(err).to.be.null;
|
|
207
|
-
expect(res).to.equal('ok1');
|
|
208
|
-
cbCount++;
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
lock.acquire(waitWorker(200000, null, 'ok2'), (err, res) => {
|
|
212
|
-
expect(err).to.be.instanceOf(BetterLock.WaitTimeoutError);
|
|
213
|
-
cbCount++;
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
setTimeout(() => {
|
|
217
|
-
// Enqueue after some time, this one should run
|
|
218
|
-
lock.acquire(waitWorker(50, null, 'ok3'), (err, res) => {
|
|
219
|
-
expect(err).to.be.null;
|
|
220
|
-
expect(res).to.equal('ok3');
|
|
221
|
-
expect(cbCount).to.equal(2);
|
|
222
|
-
testDone();
|
|
223
|
-
});
|
|
224
|
-
}, 50);
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
it('will timeout long running jobs', testDone => {
|
|
228
|
-
const lock = new BetterLock({
|
|
229
|
-
wait_timeout: 100, // should never trigger
|
|
230
|
-
execution_timeout: 75,
|
|
231
|
-
queue_size: 5,
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
let cbCount = 0;
|
|
235
|
-
lock.acquire(waitWorker(100, 'wont', 'be', 'used'), err => {
|
|
236
|
-
expect(err).to.be.instanceOf(BetterLock.ExecutionTimeoutError);
|
|
237
|
-
cbCount++;
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
setTimeout(() => {
|
|
241
|
-
lock.acquire(waitWorker(50, null, 'ok'), (err, res) => {
|
|
242
|
-
expect(cbCount).to.equal(1);
|
|
243
|
-
expect(err).to.be.null;
|
|
244
|
-
expect(res).to.equal('ok');
|
|
245
|
-
testDone();
|
|
246
|
-
});
|
|
247
|
-
}, 75);
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
describe('when overflowing', () => {
|
|
251
|
-
it('it will kick out the most recently submitted job', testDone => {
|
|
252
|
-
const lock = new BetterLock({
|
|
253
|
-
wait_timeout: 200, // should never trigger
|
|
254
|
-
execution_timeout: 300, // should never trigger
|
|
255
|
-
queue_size: 2,
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
let cbCount = 0;
|
|
259
|
-
lock.acquire(waitWorker(25, 1), arg => {
|
|
260
|
-
// The executing one
|
|
261
|
-
cbCount++;
|
|
262
|
-
expect(cbCount).to.equal(2);
|
|
263
|
-
expect(arg).to.equal(1);
|
|
264
|
-
});
|
|
265
|
-
lock.acquire(waitWorker(5, 2), arg => {
|
|
266
|
-
cbCount++;
|
|
267
|
-
expect(cbCount).to.equal(3);
|
|
268
|
-
expect(arg).to.equal(2);
|
|
269
|
-
});
|
|
270
|
-
lock.acquire(waitWorker(5, 3), arg => {
|
|
271
|
-
cbCount++;
|
|
272
|
-
expect(cbCount).to.equal(4);
|
|
273
|
-
expect(arg).to.equal(3);
|
|
274
|
-
testDone();
|
|
275
|
-
});
|
|
276
|
-
lock.acquire(waitWorker(5, 4), err => {
|
|
277
|
-
// This one will trigger the kicking out. And it will be the one kicked out
|
|
278
|
-
cbCount++;
|
|
279
|
-
expect(cbCount).to.equal(1);
|
|
280
|
-
expect(err).to.be.instanceOf(BetterLock.QueueOverflowError);
|
|
281
|
-
});
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
it('will handle queue size of 0', () => {
|
|
285
|
-
const lock = new BetterLock({
|
|
286
|
-
wait_timeout: 200, // should never trigger
|
|
287
|
-
execution_timeout: 300, // should never trigger
|
|
288
|
-
queue_size: 0,
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
return Promise.all([
|
|
292
|
-
lock.acquire(waitWorker(25, null, 'result')),
|
|
293
|
-
lock.acquire(waitWorker(5, null, 'never get here')).catch(err => err),
|
|
294
|
-
]).then(([res1, res2]) => {
|
|
295
|
-
expect(res1).to.equal('result');
|
|
296
|
-
expect(res2).to.be.instanceOf(BetterLock.QueueOverflowError);
|
|
297
|
-
});
|
|
298
|
-
});
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
it('will extend stack traces', () => {
|
|
302
|
-
return (function colorfulFunctionName() {
|
|
303
|
-
const lock = new BetterLock({
|
|
304
|
-
wait_timeout: 0,
|
|
305
|
-
execution_timeout: 5,
|
|
306
|
-
queue_size: 1,
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
return Promise.all([
|
|
310
|
-
lock.acquire(waitWorker(25)).catch(err => err),
|
|
311
|
-
lock.acquire(waitWorker(120)).catch(err => err),
|
|
312
|
-
lock.acquire(waitWorker(120)).catch(err => err),
|
|
313
|
-
]).then(([err1, err2, err3]) => {
|
|
314
|
-
expect(err1).to.be.instanceOf(BetterLock.ExecutionTimeoutError);
|
|
315
|
-
expect(err1.stack.indexOf('colorfulFunctionName')).to.be.gte(0);
|
|
316
|
-
|
|
317
|
-
expect(err2).to.be.instanceOf(BetterLock.WaitTimeoutError);
|
|
318
|
-
expect(err2.stack.indexOf('colorfulFunctionName')).to.be.gte(0);
|
|
319
|
-
|
|
320
|
-
expect(err3).to.be.instanceOf(BetterLock.QueueOverflowError);
|
|
321
|
-
expect(err3.stack.indexOf('colorfulFunctionName')).to.be.gte(0);
|
|
322
|
-
});
|
|
323
|
-
})();
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
it('can abort specific key', done => {
|
|
327
|
-
const lock = new BetterLock();
|
|
328
|
-
|
|
329
|
-
let noCallCount = 0;
|
|
330
|
-
const noCall = () => {
|
|
331
|
-
noCallCount++;
|
|
332
|
-
};
|
|
333
|
-
|
|
334
|
-
let result1 = undefined;
|
|
335
|
-
lock.acquire(waitWorker(25, null, 'a')).then(res => {
|
|
336
|
-
result1 = res;
|
|
337
|
-
}, noCall);
|
|
338
|
-
|
|
339
|
-
setTimeout(() => {
|
|
340
|
-
lock.acquire(noCall).then(noCall, err => {
|
|
341
|
-
expect(err).to.be.instanceOf(BetterLock.JobAbortedError);
|
|
342
|
-
});
|
|
343
|
-
}, 5);
|
|
344
|
-
|
|
345
|
-
setTimeout(() => {
|
|
346
|
-
lock.abort();
|
|
347
|
-
}, 10);
|
|
348
|
-
|
|
349
|
-
setTimeout(() => {
|
|
350
|
-
expect(noCallCount).to.equal(0);
|
|
351
|
-
expect(result1).to.equal('a');
|
|
352
|
-
|
|
353
|
-
done();
|
|
354
|
-
}, 40);
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
it('can abort all', () => {
|
|
358
|
-
const lock = new BetterLock();
|
|
359
|
-
|
|
360
|
-
let noCallCount = 0;
|
|
361
|
-
const noCall = () => {
|
|
362
|
-
noCallCount++;
|
|
363
|
-
};
|
|
364
|
-
|
|
365
|
-
let cbCount = 0;
|
|
366
|
-
const callback = err => {
|
|
367
|
-
cbCount++;
|
|
368
|
-
expect(err).to.be.instanceOf(BetterLock.JobAbortedError);
|
|
369
|
-
};
|
|
370
|
-
|
|
371
|
-
lock.acquire(noCall, callback);
|
|
372
|
-
lock.acquire('a', noCall, callback);
|
|
373
|
-
lock.acquire('b', noCall, callback);
|
|
374
|
-
|
|
375
|
-
lock.abortAll();
|
|
376
|
-
|
|
377
|
-
expect(lock.canAcquire()).to.be.true;
|
|
378
|
-
expect(lock.canAcquire('a')).to.be.true;
|
|
379
|
-
expect(lock.canAcquire('b')).to.be.true;
|
|
380
|
-
expect(cbCount).to.equal(3);
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
describe('if used with promises', () => {
|
|
384
|
-
it('will return a viable promise if called without callback', testDone => {
|
|
385
|
-
const lock = new BetterLock();
|
|
386
|
-
|
|
387
|
-
const variants = [];
|
|
388
|
-
|
|
389
|
-
variants.push(
|
|
390
|
-
lock.acquire(waitWorker(0, null, 'success')).then(res => {
|
|
391
|
-
expect(res).to.equal('success');
|
|
392
|
-
|
|
393
|
-
return lock.acquire(waitWorker(0, 'fail')).catch(err => {
|
|
394
|
-
expect(err).to.equal('fail');
|
|
395
|
-
return 1;
|
|
396
|
-
});
|
|
397
|
-
})
|
|
398
|
-
);
|
|
399
|
-
|
|
400
|
-
variants.push(
|
|
401
|
-
lock.acquire('with key', waitWorker(0, null, 'success')).then(res => {
|
|
402
|
-
expect(res).to.equal('success');
|
|
403
|
-
|
|
404
|
-
return lock.acquire('with key', waitWorker(0, 'fail')).catch(err => {
|
|
405
|
-
expect(err).to.equal('fail');
|
|
406
|
-
return 2;
|
|
407
|
-
});
|
|
408
|
-
})
|
|
409
|
-
);
|
|
410
|
-
|
|
411
|
-
variants.push(
|
|
412
|
-
lock.acquire('with key and options', waitWorker(0, null, 'success'), {}).then(res => {
|
|
413
|
-
expect(res).to.equal('success');
|
|
414
|
-
|
|
415
|
-
return lock.acquire('with key and options', waitWorker(0, 'fail')).catch(err => {
|
|
416
|
-
expect(err).to.equal('fail');
|
|
417
|
-
return 3;
|
|
418
|
-
});
|
|
419
|
-
})
|
|
420
|
-
);
|
|
421
|
-
|
|
422
|
-
variants.push(
|
|
423
|
-
lock.acquire(/* just options */ waitWorker(0, null, 'success'), {}).then(res => {
|
|
424
|
-
expect(res).to.equal('success');
|
|
425
|
-
|
|
426
|
-
return lock.acquire(waitWorker(0, 'fail'), {}).catch(err => {
|
|
427
|
-
expect(err).to.equal('fail');
|
|
428
|
-
return 4;
|
|
429
|
-
});
|
|
430
|
-
})
|
|
431
|
-
);
|
|
432
|
-
|
|
433
|
-
Promise.all(variants)
|
|
434
|
-
.then(results => {
|
|
435
|
-
expect(results).to.eql([1, 2, 3, 4]);
|
|
436
|
-
testDone();
|
|
437
|
-
})
|
|
438
|
-
.catch(testDone);
|
|
439
|
-
});
|
|
440
|
-
|
|
441
|
-
it('will allow executor to return a promise instead of calling done', testDone => {
|
|
442
|
-
const lock = new BetterLock();
|
|
443
|
-
|
|
444
|
-
lock.acquire(
|
|
445
|
-
() => {
|
|
446
|
-
return new Promise((resolve, reject) => {
|
|
447
|
-
setTimeout(() => {
|
|
448
|
-
resolve('result');
|
|
449
|
-
}, 20);
|
|
450
|
-
});
|
|
451
|
-
},
|
|
452
|
-
(err, res) => {
|
|
453
|
-
expect(err).to.be.null;
|
|
454
|
-
expect(res).to.equal('result');
|
|
455
|
-
}
|
|
456
|
-
);
|
|
457
|
-
|
|
458
|
-
lock.acquire(
|
|
459
|
-
() => {
|
|
460
|
-
return new Promise((resolve, reject) => {
|
|
461
|
-
setTimeout(() => {
|
|
462
|
-
reject('error');
|
|
463
|
-
}, 20);
|
|
464
|
-
});
|
|
465
|
-
},
|
|
466
|
-
err => {
|
|
467
|
-
expect(err).to.equal('error');
|
|
468
|
-
|
|
469
|
-
testDone();
|
|
470
|
-
}
|
|
471
|
-
);
|
|
472
|
-
});
|
|
473
|
-
|
|
474
|
-
it('will allow executor to directly return a value or throw an error', testDone => {
|
|
475
|
-
const lock = new BetterLock();
|
|
476
|
-
|
|
477
|
-
lock.acquire(
|
|
478
|
-
() => 'result',
|
|
479
|
-
(err, res) => {
|
|
480
|
-
expect(err).to.be.null;
|
|
481
|
-
expect(res).to.equal('result');
|
|
482
|
-
}
|
|
483
|
-
);
|
|
484
|
-
|
|
485
|
-
lock.acquire(
|
|
486
|
-
() => {
|
|
487
|
-
throw 'error';
|
|
488
|
-
},
|
|
489
|
-
err => {
|
|
490
|
-
expect(err).to.equal('error');
|
|
491
|
-
|
|
492
|
-
testDone();
|
|
493
|
-
}
|
|
494
|
-
);
|
|
495
|
-
});
|
|
496
|
-
});
|
|
497
|
-
|
|
498
|
-
describe('when using in multi-lock mode', () => {
|
|
499
|
-
it('can lock on multiple keys in a basic case', () => {
|
|
500
|
-
const lock = new BetterLock();
|
|
501
|
-
const startedAt = new Date();
|
|
502
|
-
|
|
503
|
-
const sequence = [];
|
|
504
|
-
return Promise.all([
|
|
505
|
-
lock.acquire('a', waitWorker(50, null, 1)).then(res => sequence.push(res)),
|
|
506
|
-
waitPromise(35).then(() =>
|
|
507
|
-
lock.acquire('b', () => {
|
|
508
|
-
sequence.push(2);
|
|
509
|
-
return waitPromise(50, 2);
|
|
510
|
-
})
|
|
511
|
-
),
|
|
512
|
-
waitPromise(15).then(() =>
|
|
513
|
-
lock.acquire(['a', 'b'], () => {
|
|
514
|
-
sequence.push(3);
|
|
515
|
-
return waitPromise(50, 3);
|
|
516
|
-
})
|
|
517
|
-
),
|
|
518
|
-
]).then(res => {
|
|
519
|
-
expect(res).to.eql([1, 2, 3]);
|
|
520
|
-
expect(sequence).to.eql([1, 3, 2]);
|
|
521
|
-
expect(new Date() - startedAt).to.be.within(145, 180);
|
|
522
|
-
});
|
|
523
|
-
});
|
|
524
|
-
|
|
525
|
-
it('can handle duplicate keys in the key list', () => {
|
|
526
|
-
const lock = new BetterLock({});
|
|
527
|
-
|
|
528
|
-
const startedAt = new Date();
|
|
529
|
-
|
|
530
|
-
return Promise.all([
|
|
531
|
-
lock.acquire(['a', undefined], waitWorker(50, null, '1')),
|
|
532
|
-
waitPromise(5).then(() =>
|
|
533
|
-
lock.acquire(['a', 'b', undefined, 'c', undefined, 'a'], waitWorker(50, null, '2'))
|
|
534
|
-
),
|
|
535
|
-
waitPromise(15).then(() => lock.acquire('c', waitWorker(50, null, '3'))),
|
|
536
|
-
]).then(res => {
|
|
537
|
-
expect(res).to.eql(['1', '2', '3']);
|
|
538
|
-
expect(new Date() - startedAt).to.be.within(145, 180);
|
|
539
|
-
});
|
|
540
|
-
});
|
|
541
|
-
|
|
542
|
-
it('can wait timeout on partially held locks', () => {
|
|
543
|
-
const lock = new BetterLock({
|
|
544
|
-
wait_timeout: 20,
|
|
545
|
-
execution_timeout: 50,
|
|
546
|
-
});
|
|
547
|
-
|
|
548
|
-
const startedAt = new Date();
|
|
549
|
-
|
|
550
|
-
return Promise.all([
|
|
551
|
-
// Hold a, time out execution after 50ms
|
|
552
|
-
lock.acquire('a', waitWorker(10000, null, 1)).catch(err => err),
|
|
553
|
-
// Wait on a, grab b, then time out on a after 20ms
|
|
554
|
-
lock
|
|
555
|
-
.acquire(['a', 'b'], waitWorker(50, new Error('Should never be seen')))
|
|
556
|
-
.catch(err => err),
|
|
557
|
-
// Wait for b, grab it when #2 times out (20ms in).
|
|
558
|
-
lock.acquire('b', waitWorker(30, null, 3), { wait_timeout: 30 }).catch(err => err),
|
|
559
|
-
]).then(([res1, res2, res3]) => {
|
|
560
|
-
expect(res1).to.be.instanceOf(BetterLock.ExecutionTimeoutError);
|
|
561
|
-
expect(res2).to.be.instanceOf(BetterLock.WaitTimeoutError);
|
|
562
|
-
expect(res3).to.equal(3);
|
|
563
|
-
expect(new Date() - startedAt).to.be.within(45, 60);
|
|
564
|
-
});
|
|
565
|
-
});
|
|
566
|
-
});
|
|
567
|
-
});
|
|
568
|
-
|
|
569
|
-
function waitWorker(ms, ...args) {
|
|
570
|
-
return function(done) {
|
|
571
|
-
setTimeout(() => {
|
|
572
|
-
done.apply(null, args);
|
|
573
|
-
}, ms);
|
|
574
|
-
};
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
function waitPromise(ms, result) {
|
|
578
|
-
return new Promise(resolve => {
|
|
579
|
-
setTimeout(() => {
|
|
580
|
-
resolve(result);
|
|
581
|
-
}, ms);
|
|
582
|
-
});
|
|
583
|
-
}
|