petty-cache 3.3.1 → 3.5.0
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/CHANGELOG.md +8 -0
- package/README.md +1 -1
- package/eslint.config.js +44 -0
- package/index.js +70 -29
- package/package.json +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [3.5.0] - 2025-05-01
|
|
10
|
+
### Changed
|
|
11
|
+
- Added the ability for `pettyCache.del` functions to support callbacks and promises.
|
|
12
|
+
|
|
13
|
+
## [3.4.0] - 2025-02-21
|
|
14
|
+
### Changed
|
|
15
|
+
- Added the ability for `pettyCache.mutex` functions to support callbacks and promises.
|
|
16
|
+
|
|
9
17
|
## [3.3.0] - 2024-07-03
|
|
10
18
|
### Changed
|
|
11
19
|
- Added the ability for `pettyCache.fetch` to support async functions.
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# petty-cache
|
|
2
2
|
|
|
3
|
-
[](https://github.com/mediocre/petty-cache/actions?query=workflow%3Abuild+branch%3Amain)
|
|
4
4
|
[](https://coveralls.io/github/mediocre/petty-cache?branch=main)
|
|
5
5
|
|
|
6
6
|
A cache module for Node.js that uses a two-level cache (in-memory cache for recently accessed data plus Redis for distributed caching) with automatic serialization plus some extra features to avoid cache stampedes and thundering herds.
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const globals = require('globals');
|
|
2
|
+
const js = require('@eslint/js');
|
|
3
|
+
|
|
4
|
+
module.exports = [
|
|
5
|
+
js.configs.recommended,
|
|
6
|
+
{
|
|
7
|
+
ignores: ['node_modules/*'],
|
|
8
|
+
languageOptions: {
|
|
9
|
+
ecmaVersion: 2020,
|
|
10
|
+
sourceType: 'module',
|
|
11
|
+
parserOptions: {
|
|
12
|
+
ecmaFeatures: {
|
|
13
|
+
jsx: true
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
globals: {
|
|
17
|
+
...globals.es2020,
|
|
18
|
+
...globals.mocha,
|
|
19
|
+
...globals.node,
|
|
20
|
+
//added for 'fetch()' access
|
|
21
|
+
...globals.serviceworker
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
rules: {
|
|
25
|
+
'brace-style': ['error', '1tbs', { allowSingleLine: true }],
|
|
26
|
+
'comma-dangle': ['error', 'never'],
|
|
27
|
+
'dot-notation': 'error',
|
|
28
|
+
'no-array-constructor': 'error',
|
|
29
|
+
'no-console': 'error',
|
|
30
|
+
'no-fallthrough': 'off',
|
|
31
|
+
'no-inline-comments': 'warn',
|
|
32
|
+
'no-trailing-spaces': 'error',
|
|
33
|
+
'no-unused-vars': ['error', { caughtErrors: 'none' }],
|
|
34
|
+
'object-curly-spacing': ['error', 'always'],
|
|
35
|
+
quotes: ['error', 'single'],
|
|
36
|
+
semi: ['error', 'always'],
|
|
37
|
+
'space-before-function-paren': ['error', {
|
|
38
|
+
anonymous: 'never',
|
|
39
|
+
named: 'never',
|
|
40
|
+
asyncArrow: 'always'
|
|
41
|
+
}]
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
];
|
package/index.js
CHANGED
|
@@ -13,6 +13,7 @@ function PettyCache() {
|
|
|
13
13
|
redisClient = redis.createClient(...arguments);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
//eslint-disable-next-line no-console
|
|
16
17
|
redisClient.on('error', err => console.warn(`Warning: Redis reported a client error: ${err}`));
|
|
17
18
|
|
|
18
19
|
function bulkGetFromRedis(keys, callback) {
|
|
@@ -254,14 +255,24 @@ function PettyCache() {
|
|
|
254
255
|
};
|
|
255
256
|
|
|
256
257
|
this.del = function(key, callback) {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
258
|
+
const executor = () => {
|
|
259
|
+
return new Promise((resolve, reject) => {
|
|
260
|
+
redisClient.del(key, function(err) {
|
|
261
|
+
if (err) {
|
|
262
|
+
return reject(err);
|
|
263
|
+
}
|
|
261
264
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
+
memoryCache.del(key);
|
|
266
|
+
resolve();
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
if (callback) {
|
|
272
|
+
executor().then(result => callback(null, result)).catch(callback);
|
|
273
|
+
} else {
|
|
274
|
+
return executor();
|
|
275
|
+
}
|
|
265
276
|
};
|
|
266
277
|
|
|
267
278
|
// Returns data from cache if available;
|
|
@@ -461,42 +472,72 @@ function PettyCache() {
|
|
|
461
472
|
};
|
|
462
473
|
|
|
463
474
|
this.mutex = {
|
|
464
|
-
lock:
|
|
475
|
+
lock: (key, options, callback) => {
|
|
465
476
|
// Options are optional
|
|
466
477
|
if (!callback && typeof options === 'function') {
|
|
467
478
|
callback = options;
|
|
468
479
|
options = {};
|
|
469
480
|
}
|
|
470
481
|
|
|
471
|
-
callback = callback || function() {};
|
|
472
482
|
options = options || {};
|
|
473
483
|
|
|
474
|
-
options.retry = Object.
|
|
475
|
-
options.retry.interval = Object.
|
|
476
|
-
options.retry.times = Object.
|
|
477
|
-
options.ttl = Object.
|
|
484
|
+
options.retry = Object.hasOwn(options, 'retry') ? options.retry : {};
|
|
485
|
+
options.retry.interval = Object.hasOwn(options.retry, 'interval') ? options.retry.interval : 100;
|
|
486
|
+
options.retry.times = Object.hasOwn(options.retry, 'times') ? options.retry.times : 1;
|
|
487
|
+
options.ttl = Object.hasOwn(options, 'ttl') ? options.ttl : 1000;
|
|
478
488
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
489
|
+
const executor = () => {
|
|
490
|
+
return new Promise((resolve, reject) => {
|
|
491
|
+
async.retry({ interval: options.retry.interval, times: options.retry.times }, callback => {
|
|
492
|
+
redisClient.set(key, '1', 'NX', 'PX', options.ttl, function(err, res) {
|
|
493
|
+
if (err) {
|
|
494
|
+
return callback(err);
|
|
495
|
+
}
|
|
484
496
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
497
|
+
if (!res) {
|
|
498
|
+
return callback(new Error());
|
|
499
|
+
}
|
|
488
500
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
501
|
+
if (res !== 'OK') {
|
|
502
|
+
return callback(new Error(res));
|
|
503
|
+
}
|
|
492
504
|
|
|
493
|
-
|
|
505
|
+
callback();
|
|
506
|
+
});
|
|
507
|
+
}, function(err) {
|
|
508
|
+
if (err) {
|
|
509
|
+
return reject(err);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
resolve();
|
|
513
|
+
});
|
|
494
514
|
});
|
|
495
|
-
}
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
if (callback) {
|
|
518
|
+
executor().then(result => callback(null, result)).catch(callback);
|
|
519
|
+
} else {
|
|
520
|
+
return executor();
|
|
521
|
+
}
|
|
496
522
|
},
|
|
497
|
-
unlock:
|
|
498
|
-
|
|
499
|
-
|
|
523
|
+
unlock: (key, callback) => {
|
|
524
|
+
const executor = () => {
|
|
525
|
+
return new Promise((resolve, reject) => {
|
|
526
|
+
redisClient.del(key, function(err) {
|
|
527
|
+
if (err) {
|
|
528
|
+
return reject(err);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
resolve();
|
|
532
|
+
});
|
|
533
|
+
});
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
if (callback) {
|
|
537
|
+
executor().then(result => callback(null, result)).catch(callback);
|
|
538
|
+
} else {
|
|
539
|
+
return executor();
|
|
540
|
+
}
|
|
500
541
|
}
|
|
501
542
|
};
|
|
502
543
|
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"description": "A cache module for node.js that uses a two-level cache (in-memory cache for recently accessed data plus Redis for distributed caching) with some extra features to avoid cache stampedes and thundering herds.",
|
|
3
3
|
"dependencies": {
|
|
4
|
-
"async": "~3.2.
|
|
4
|
+
"async": "~3.2.6",
|
|
5
5
|
"lock": "~1.1.0",
|
|
6
6
|
"memory-cache": "~0.2.0",
|
|
7
7
|
"redis": "~3.1.0"
|
|
8
8
|
},
|
|
9
9
|
"devDependencies": {
|
|
10
|
+
"@eslint/js": "*",
|
|
11
|
+
"globals": "*",
|
|
10
12
|
"coveralls": "*",
|
|
11
13
|
"mocha": "*",
|
|
12
14
|
"nyc": "*"
|
|
@@ -30,5 +32,5 @@
|
|
|
30
32
|
"type": "git",
|
|
31
33
|
"url": "https://github.com/mediocre/petty-cache.git"
|
|
32
34
|
},
|
|
33
|
-
"version": "3.
|
|
35
|
+
"version": "3.5.0"
|
|
34
36
|
}
|