-
Notifications
You must be signed in to change notification settings - Fork 48
/
Copy pathindex.js
52 lines (45 loc) · 1.55 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
"use strict";
const DEFAULT_TIMEOUT = 5000;
const DEFAULT_RETRY_DELAY = 50;
async function acquireLock (client, lockName, timeout, retryDelay, onLockAcquired) {
function retry () {
setTimeout(() => {
acquireLock(client, lockName, timeout, retryDelay, onLockAcquired);
}, retryDelay);
}
const lockTimeoutValue = Date.now() + timeout + 1;
try {
const result = await client.set(lockName, lockTimeoutValue, {
PX: timeout,
NX: true
});
if (result === null) {
throw new Error("Lock failed");
}
onLockAcquired(lockTimeoutValue);
} catch (err) {
retry();
}
}
function redisLock (client, retryDelay = DEFAULT_RETRY_DELAY) {
if(!(client && client.set && "v4" in client)) {
throw new Error("You must specify a v4 client instance of https://github.com/redis/node-redis");
}
async function lock (lockName, timeout = DEFAULT_TIMEOUT) {
return new Promise(resolve => {
if (!lockName) {
throw new Error("You must specify a lock string. It is on the redis key `lock.[string]` that the lock is acquired.");
}
lockName = `lock.${ lockName}`;
acquireLock(client, lockName, timeout, retryDelay, lockTimeoutValue => {
resolve(async () => {
if (lockTimeoutValue > Date.now()) {
return client.del(lockName);
}
});
});
});
}
return lock;
}
module.exports = redisLock;