create-dacosta-proj 1.0.25 → 1.0.26
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/package.json
CHANGED
|
@@ -1,23 +1,39 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const crypto = require('crypto');
|
|
4
|
+
|
|
5
|
+
const DEFAULT_TIMEOUT = 5_000;
|
|
4
6
|
const DEFAULT_RETRY_DELAY = 50;
|
|
7
|
+
const DEFAULT_WAIT_TIMEOUT = 30_000;
|
|
8
|
+
|
|
9
|
+
// Atomic compare-and-delete so we only release a lock we still hold.
|
|
10
|
+
// Without this, an expired lock that another caller already re-acquired
|
|
11
|
+
// would be deleted by our release(), letting a third caller acquire it
|
|
12
|
+
// while the second is still inside its critical section.
|
|
13
|
+
const RELEASE_SCRIPT = 'if redis.call("GET", KEYS[1]) == ARGV[1] then return redis.call("DEL", KEYS[1]) else return 0 end';
|
|
5
14
|
|
|
6
15
|
function redisLock(client, retryDelay = DEFAULT_RETRY_DELAY) {
|
|
7
|
-
async function lock(lockName, timeout = DEFAULT_TIMEOUT) {
|
|
16
|
+
async function lock(lockName, timeout = DEFAULT_TIMEOUT, waitTimeout = DEFAULT_WAIT_TIMEOUT) {
|
|
8
17
|
const lockKey = `lock.${lockName}`;
|
|
9
|
-
const
|
|
18
|
+
const token = crypto.randomBytes(16).toString('hex');
|
|
19
|
+
const deadline = Date.now() + waitTimeout;
|
|
20
|
+
let released = false;
|
|
21
|
+
|
|
10
22
|
while (true) {
|
|
11
|
-
const result = await client.set(lockKey,
|
|
23
|
+
const result = await client.set(lockKey, token, { PX: timeout, NX: true });
|
|
12
24
|
if (result !== null) {
|
|
13
25
|
return async () => {
|
|
14
|
-
if (
|
|
26
|
+
if (released) return;
|
|
27
|
+
released = true;
|
|
28
|
+
try { await client.sendCommand(['EVAL', RELEASE_SCRIPT, '1', lockKey, token]); }
|
|
29
|
+
catch {}
|
|
15
30
|
};
|
|
16
31
|
}
|
|
32
|
+
if (Date.now() >= deadline) throw new Error(`redisLock: timed out waiting for "${lockName}" after ${waitTimeout}ms`);
|
|
17
33
|
await new Promise(r => setTimeout(r, retryDelay));
|
|
18
34
|
}
|
|
19
35
|
}
|
|
20
36
|
return lock;
|
|
21
37
|
}
|
|
22
38
|
|
|
23
|
-
module.exports = redisLock;
|
|
39
|
+
module.exports = redisLock;
|
package/template/list.todo
DELETED
|
File without changes
|