cachette 4.0.25 → 4.0.26-remove-redlock.1
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.
|
@@ -19,15 +19,12 @@ export declare class RedisCache extends CacheInstance {
|
|
|
19
19
|
static ERROR_PREFIX: string;
|
|
20
20
|
static NUMBER_PREFIX: string;
|
|
21
21
|
static REDIS_CONNECTION_TIMEOUT_MS: number;
|
|
22
|
-
static
|
|
23
|
-
static
|
|
24
|
-
static
|
|
25
|
-
static REDLOCK_JITTER_MS: number;
|
|
22
|
+
static LOCK_MAX_ATTEMPTS: number;
|
|
23
|
+
static LOCK_RETRY_DELAY: number;
|
|
24
|
+
static LOCK_JITTER_MS: number;
|
|
26
25
|
private redisClient;
|
|
27
26
|
private ready;
|
|
28
27
|
private url;
|
|
29
|
-
private redlock;
|
|
30
|
-
private redlockWithoutRetry;
|
|
31
28
|
constructor(redisUrl: string, readOnly?: boolean);
|
|
32
29
|
/**
|
|
33
30
|
* @inheritdoc
|
|
@@ -43,7 +40,6 @@ export declare class RedisCache extends CacheInstance {
|
|
|
43
40
|
* with an UncaughtException.
|
|
44
41
|
*/
|
|
45
42
|
errorStrategy(): void;
|
|
46
|
-
redlockErrorStrategy(err: any): void;
|
|
47
43
|
/**
|
|
48
44
|
* The end event is emitted by the redis client when an
|
|
49
45
|
* established connection has ended.
|
|
@@ -111,8 +107,6 @@ export declare class RedisCache extends CacheInstance {
|
|
|
111
107
|
clearMemory(): Promise<void>;
|
|
112
108
|
/**
|
|
113
109
|
* @inheritdoc
|
|
114
|
-
* Locking through the redlock algorithm
|
|
115
|
-
* https://redis.io/topics/distlock
|
|
116
110
|
*/
|
|
117
111
|
isLockingSupported(): boolean;
|
|
118
112
|
/**
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RedisCache = exports.SIZE_THRESHOLD_WARNING_BYTES = void 0;
|
|
4
4
|
const ioredis_1 = require("ioredis");
|
|
5
|
-
const
|
|
5
|
+
const node_crypto_1 = require("node:crypto");
|
|
6
6
|
const CacheInstance_1 = require("./CacheInstance");
|
|
7
7
|
exports.SIZE_THRESHOLD_WARNING_BYTES = 20_000_000;
|
|
8
8
|
/**
|
|
@@ -25,20 +25,12 @@ class RedisCache extends CacheInstance_1.CacheInstance {
|
|
|
25
25
|
static NUMBER_PREFIX = 'f405eed4-507c-4aa5-a6d2-c1813d584b8f-NUMBER';
|
|
26
26
|
static REDIS_CONNECTION_TIMEOUT_MS = parseInt(process.env.REDIS_CONNECTION_TIMEOUT_MS, 10) || 5000;
|
|
27
27
|
// Backward compatible: REDLOCK_* takes precedence, then CACHETTE_LOCK_*
|
|
28
|
-
static
|
|
29
|
-
static
|
|
30
|
-
static
|
|
31
|
-
static REDLOCK_JITTER_MS = parseInt(process.env.REDLOCK_JITTER_MS, 10) || 200; // lib. default: 200
|
|
28
|
+
static LOCK_MAX_ATTEMPTS = parseInt(process.env.REDLOCK_RETRY_COUNT, 10) || RedisCache.LOCK_RETRY_COUNT;
|
|
29
|
+
static LOCK_RETRY_DELAY = parseInt(process.env.REDLOCK_RETRY_DELAY_MS, 10) || RedisCache.LOCK_RETRY_DELAY_MS;
|
|
30
|
+
static LOCK_JITTER_MS = parseInt(process.env.REDLOCK_JITTER_MS, 10) || 200;
|
|
32
31
|
redisClient;
|
|
33
32
|
ready = false;
|
|
34
33
|
url;
|
|
35
|
-
// We manage several redlock instances because some options (like retryCount)
|
|
36
|
-
// are set at redlock init. By having these options in our constructor too
|
|
37
|
-
// (and only having one redlock with fixed behavior), we would be unable to
|
|
38
|
-
// support mixing calls requiring one behavior, then another.
|
|
39
|
-
// And so, we have as many redlocks as we need to honor these runtime needs.
|
|
40
|
-
redlock;
|
|
41
|
-
redlockWithoutRetry;
|
|
42
34
|
constructor(redisUrl, readOnly = false) {
|
|
43
35
|
super();
|
|
44
36
|
if (!redisUrl || (!redisUrl.startsWith('redis://') && !redisUrl.startsWith('rediss://'))) {
|
|
@@ -56,26 +48,9 @@ class RedisCache extends CacheInstance_1.CacheInstance {
|
|
|
56
48
|
// This prevents get/setValue calls from hanging if there is no active connection
|
|
57
49
|
enableOfflineQueue: false,
|
|
58
50
|
});
|
|
59
|
-
this.redlock = new Redlock([this.redisClient], {
|
|
60
|
-
// Hack until Redlock 5.x is out of beta
|
|
61
|
-
driftFactor: RedisCache.REDLOCK_CLOCK_DRIFT_FACTOR,
|
|
62
|
-
retryCount: RedisCache.REDLOCK_RETRY_COUNT,
|
|
63
|
-
retryDelay: RedisCache.REDLOCK_RETRY_DELAY_MS,
|
|
64
|
-
retryJitter: RedisCache.REDLOCK_JITTER_MS,
|
|
65
|
-
});
|
|
66
|
-
this.redlockWithoutRetry = new Redlock([this.redisClient], {
|
|
67
|
-
// Hack until Redlock 5.x is out of beta
|
|
68
|
-
driftFactor: RedisCache.REDLOCK_CLOCK_DRIFT_FACTOR,
|
|
69
|
-
retryCount: 0,
|
|
70
|
-
retryDelay: 0,
|
|
71
|
-
retryJitter: 0,
|
|
72
|
-
});
|
|
73
51
|
this.redisClient.on('ready', this.startConnectionStrategy.bind(this));
|
|
74
52
|
this.redisClient.on('end', this.endConnectionStrategy.bind(this));
|
|
75
53
|
this.redisClient.on('error', this.errorStrategy.bind(this));
|
|
76
|
-
// TODO when migrating to Redlock v5: rename 'clientError' to 'error'
|
|
77
|
-
this.redlock.on('clientError', this.redlockErrorStrategy.bind(this));
|
|
78
|
-
this.redlockWithoutRetry.on('clientError', this.redlockErrorStrategy.bind(this));
|
|
79
54
|
}
|
|
80
55
|
/**
|
|
81
56
|
* @inheritdoc
|
|
@@ -100,9 +75,6 @@ class RedisCache extends CacheInstance_1.CacheInstance {
|
|
|
100
75
|
errorStrategy() {
|
|
101
76
|
this.emit('warn', 'Error while connected to the Redis cache!');
|
|
102
77
|
}
|
|
103
|
-
redlockErrorStrategy(err) {
|
|
104
|
-
this.emit('warn', 'Redlock error:', err);
|
|
105
|
-
}
|
|
106
78
|
/**
|
|
107
79
|
* The end event is emitted by the redis client when an
|
|
108
80
|
* established connection has ended.
|
|
@@ -325,8 +297,6 @@ class RedisCache extends CacheInstance_1.CacheInstance {
|
|
|
325
297
|
}
|
|
326
298
|
/**
|
|
327
299
|
* @inheritdoc
|
|
328
|
-
* Locking through the redlock algorithm
|
|
329
|
-
* https://redis.io/topics/distlock
|
|
330
300
|
*/
|
|
331
301
|
isLockingSupported() {
|
|
332
302
|
return true;
|
|
@@ -335,20 +305,23 @@ class RedisCache extends CacheInstance_1.CacheInstance {
|
|
|
335
305
|
* @inheritdoc
|
|
336
306
|
*/
|
|
337
307
|
async lock(resource, ttlMs, retry = true) {
|
|
338
|
-
const
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
308
|
+
const maxAttempts = retry === false ? 1 : RedisCache.LOCK_MAX_ATTEMPTS;
|
|
309
|
+
const value = (0, node_crypto_1.randomUUID)();
|
|
310
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
311
|
+
const result = await this.redisClient.set(resource, value, 'PX', ttlMs, 'NX');
|
|
312
|
+
if (result === 'OK') {
|
|
313
|
+
return {
|
|
314
|
+
value,
|
|
315
|
+
unlock: async () => {
|
|
316
|
+
await this.redisClient.eval('if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end', 1, resource, value);
|
|
317
|
+
},
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
if (attempt < maxAttempts - 1) {
|
|
321
|
+
await new Promise((resolve) => setTimeout(resolve, RedisCache.LOCK_RETRY_DELAY + Math.random() * RedisCache.LOCK_JITTER_MS));
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
throw new Error(`Failed to acquire lock on ${resource} after ${maxAttempts} attempts`);
|
|
352
325
|
}
|
|
353
326
|
/**
|
|
354
327
|
* @inheritdoc
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RedisCache.js","sourceRoot":"","sources":["../../../src/lib/RedisCache.ts"],"names":[],"mappings":";;;AAAA,qCAA4B;AAC5B,
|
|
1
|
+
{"version":3,"file":"RedisCache.js","sourceRoot":"","sources":["../../../src/lib/RedisCache.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cachette",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.26-remove-redlock.1",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=20",
|
|
6
6
|
"npm": ">=10"
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"test:ci": "npm run compile && mkdir -p ci_output/testresults && mocha --config test/mocharc-ci.js 'dist/test/**/*.js'",
|
|
33
33
|
"relock": "rm -rf node_modules package-lock.json; npm install --package-lock; npm out; true",
|
|
34
34
|
"postprepare": "npm run --silent githook-install",
|
|
35
|
-
"githook-install": "mkdir -p .git/hooks/ && echo '#!/usr/bin/env sh\necho \"⚠️ Reminder that cachette is a *source-public* package! ⚠️\"\necho \"No private info in comments!!!\"\necho \"Ctrl+C to abort git push, Enter to proceed.\"\nread REPLY < /dev/tty' > '.git/hooks/pre-push' && chmod +x '.git/hooks/pre-push'"
|
|
35
|
+
"githook-install": "[ -n \"$CI\" ] && exit 0; mkdir -p .git/hooks/ && echo '#!/usr/bin/env sh\necho \"⚠️ Reminder that cachette is a *source-public* package! ⚠️\"\necho \"No private info in comments!!!\"\necho \"Ctrl+C to abort git push, Enter to proceed.\"\nread REPLY < /dev/tty' > '.git/hooks/pre-push' && chmod +x '.git/hooks/pre-push'"
|
|
36
36
|
},
|
|
37
37
|
"nyc": {
|
|
38
38
|
"cache": false,
|
|
@@ -59,7 +59,6 @@
|
|
|
59
59
|
"@types/eslint__js": "8.x",
|
|
60
60
|
"@types/mocha": "10.x",
|
|
61
61
|
"@types/node": "20.x",
|
|
62
|
-
"@types/redlock": "4.x",
|
|
63
62
|
"@types/sinon": "21.x",
|
|
64
63
|
"chai": "6.x",
|
|
65
64
|
"eslint": "10.x",
|
|
@@ -74,7 +73,6 @@
|
|
|
74
73
|
},
|
|
75
74
|
"dependencies": {
|
|
76
75
|
"ioredis": "5.x",
|
|
77
|
-
"lru-cache": "11.x"
|
|
78
|
-
"redlock": "4.x"
|
|
76
|
+
"lru-cache": "11.x"
|
|
79
77
|
}
|
|
80
78
|
}
|
package/src/lib/RedisCache.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Redis from 'ioredis';
|
|
2
|
-
import
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
3
|
|
|
4
4
|
import { CachableValue, CacheInstance, Lock } from './CacheInstance';
|
|
5
5
|
|
|
@@ -26,23 +26,15 @@ export class RedisCache extends CacheInstance {
|
|
|
26
26
|
|
|
27
27
|
public static REDIS_CONNECTION_TIMEOUT_MS = parseInt(process.env.REDIS_CONNECTION_TIMEOUT_MS as string, 10) || 5000;
|
|
28
28
|
// Backward compatible: REDLOCK_* takes precedence, then CACHETTE_LOCK_*
|
|
29
|
-
public static
|
|
30
|
-
parseInt(process.env.REDLOCK_RETRY_COUNT as string, 10) || RedisCache.LOCK_RETRY_COUNT;
|
|
31
|
-
public static
|
|
32
|
-
parseInt(process.env.REDLOCK_RETRY_DELAY_MS as string, 10) || RedisCache.LOCK_RETRY_DELAY_MS;
|
|
33
|
-
public static
|
|
34
|
-
public static REDLOCK_JITTER_MS = parseInt(process.env.REDLOCK_JITTER_MS as string, 10) || 200; // lib. default: 200
|
|
29
|
+
public static LOCK_MAX_ATTEMPTS =
|
|
30
|
+
parseInt(process.env.REDLOCK_RETRY_COUNT as string, 10) || RedisCache.LOCK_RETRY_COUNT;
|
|
31
|
+
public static LOCK_RETRY_DELAY =
|
|
32
|
+
parseInt(process.env.REDLOCK_RETRY_DELAY_MS as string, 10) || RedisCache.LOCK_RETRY_DELAY_MS;
|
|
33
|
+
public static LOCK_JITTER_MS = parseInt(process.env.REDLOCK_JITTER_MS as string, 10) || 200;
|
|
35
34
|
|
|
36
35
|
private redisClient: Redis;
|
|
37
36
|
private ready = false;
|
|
38
37
|
private url: string;
|
|
39
|
-
// We manage several redlock instances because some options (like retryCount)
|
|
40
|
-
// are set at redlock init. By having these options in our constructor too
|
|
41
|
-
// (and only having one redlock with fixed behavior), we would be unable to
|
|
42
|
-
// support mixing calls requiring one behavior, then another.
|
|
43
|
-
// And so, we have as many redlocks as we need to honor these runtime needs.
|
|
44
|
-
private redlock: Redlock;
|
|
45
|
-
private redlockWithoutRetry: Redlock;
|
|
46
38
|
|
|
47
39
|
constructor(redisUrl: string, readOnly = false) {
|
|
48
40
|
super();
|
|
@@ -63,28 +55,10 @@ export class RedisCache extends CacheInstance {
|
|
|
63
55
|
// This prevents get/setValue calls from hanging if there is no active connection
|
|
64
56
|
enableOfflineQueue: false,
|
|
65
57
|
});
|
|
66
|
-
this.redlock = new Redlock([this.redisClient as unknown as Redlock.CompatibleRedisClient], {
|
|
67
|
-
// Hack until Redlock 5.x is out of beta
|
|
68
|
-
driftFactor: RedisCache.REDLOCK_CLOCK_DRIFT_FACTOR,
|
|
69
|
-
retryCount: RedisCache.REDLOCK_RETRY_COUNT,
|
|
70
|
-
retryDelay: RedisCache.REDLOCK_RETRY_DELAY_MS,
|
|
71
|
-
retryJitter: RedisCache.REDLOCK_JITTER_MS,
|
|
72
|
-
});
|
|
73
|
-
this.redlockWithoutRetry = new Redlock([this.redisClient as unknown as Redlock.CompatibleRedisClient], {
|
|
74
|
-
// Hack until Redlock 5.x is out of beta
|
|
75
|
-
driftFactor: RedisCache.REDLOCK_CLOCK_DRIFT_FACTOR,
|
|
76
|
-
retryCount: 0,
|
|
77
|
-
retryDelay: 0,
|
|
78
|
-
retryJitter: 0,
|
|
79
|
-
});
|
|
80
58
|
|
|
81
59
|
this.redisClient.on('ready', this.startConnectionStrategy.bind(this));
|
|
82
60
|
this.redisClient.on('end', this.endConnectionStrategy.bind(this));
|
|
83
61
|
this.redisClient.on('error', this.errorStrategy.bind(this));
|
|
84
|
-
|
|
85
|
-
// TODO when migrating to Redlock v5: rename 'clientError' to 'error'
|
|
86
|
-
this.redlock.on('clientError', this.redlockErrorStrategy.bind(this));
|
|
87
|
-
this.redlockWithoutRetry.on('clientError', this.redlockErrorStrategy.bind(this));
|
|
88
62
|
}
|
|
89
63
|
|
|
90
64
|
/**
|
|
@@ -113,10 +87,6 @@ export class RedisCache extends CacheInstance {
|
|
|
113
87
|
this.emit('warn', 'Error while connected to the Redis cache!');
|
|
114
88
|
}
|
|
115
89
|
|
|
116
|
-
public redlockErrorStrategy(err: any): void {
|
|
117
|
-
this.emit('warn', 'Redlock error:', err);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
90
|
/**
|
|
121
91
|
* The end event is emitted by the redis client when an
|
|
122
92
|
* established connection has ended.
|
|
@@ -368,8 +338,6 @@ export class RedisCache extends CacheInstance {
|
|
|
368
338
|
|
|
369
339
|
/**
|
|
370
340
|
* @inheritdoc
|
|
371
|
-
* Locking through the redlock algorithm
|
|
372
|
-
* https://redis.io/topics/distlock
|
|
373
341
|
*/
|
|
374
342
|
public isLockingSupported(): boolean {
|
|
375
343
|
return true;
|
|
@@ -379,19 +347,33 @@ export class RedisCache extends CacheInstance {
|
|
|
379
347
|
* @inheritdoc
|
|
380
348
|
*/
|
|
381
349
|
public async lock(resource: string, ttlMs: number, retry = true): Promise<Lock> {
|
|
382
|
-
const
|
|
383
|
-
const
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
350
|
+
const maxAttempts = retry === false ? 1 : RedisCache.LOCK_MAX_ATTEMPTS;
|
|
351
|
+
const value = randomUUID();
|
|
352
|
+
|
|
353
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
354
|
+
const result = await this.redisClient.set(resource, value, 'PX', ttlMs, 'NX');
|
|
355
|
+
if (result === 'OK') {
|
|
356
|
+
return {
|
|
357
|
+
value,
|
|
358
|
+
unlock: async () => {
|
|
359
|
+
await this.redisClient.eval(
|
|
360
|
+
'if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end',
|
|
361
|
+
1,
|
|
362
|
+
resource,
|
|
363
|
+
value,
|
|
364
|
+
);
|
|
365
|
+
},
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
if (attempt < maxAttempts - 1) {
|
|
370
|
+
await new Promise((resolve) =>
|
|
371
|
+
setTimeout(resolve, RedisCache.LOCK_RETRY_DELAY + Math.random() * RedisCache.LOCK_JITTER_MS),
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
throw new Error(`Failed to acquire lock on ${resource} after ${maxAttempts} attempts`);
|
|
395
377
|
}
|
|
396
378
|
|
|
397
379
|
/**
|
package/test/CacheClient_test.ts
CHANGED
|
@@ -328,16 +328,4 @@ describe('CacheClient', () => {
|
|
|
328
328
|
expect(() => cacheClient['buildCacheKey']('functionName', [obj2])).to.throw();
|
|
329
329
|
});
|
|
330
330
|
});
|
|
331
|
-
|
|
332
|
-
describe('Redlock maintenance reminder', () => {
|
|
333
|
-
it('is still on Redlock v4, or was carefully migrated to v5', () => {
|
|
334
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
335
|
-
const redlockVersion = require('../../package.json').dependencies.redlock;
|
|
336
|
-
if (redlockVersion !== '4.x') {
|
|
337
|
-
throw new Error(
|
|
338
|
-
'Migrating Redlock to v5? This breaking test is a reminder to:\n 1. Migrate v4 handling of `clientError` events into v5 `error` events\n 2. Review error handling: Redlock v5 throws at many places, while Redlock v4 only threw in its constructor\n 3. Review other breaking changes provided by the upgrade guide, if Redlock maintainers provide one when shipping v5',
|
|
339
|
-
);
|
|
340
|
-
}
|
|
341
|
-
});
|
|
342
|
-
});
|
|
343
331
|
});
|