lru-cache-for-clusters-as-promised
Advanced tools
Comparing version 1.3.1 to 1.4.0
@@ -13,2 +13,3 @@ /** | ||
const cluster = require('cluster'); | ||
const CronJob = require('cron').CronJob; | ||
const Debug = require('debug'); | ||
@@ -19,2 +20,3 @@ const uuid = require('uuid'); | ||
const debug = new Debug('lru-cache-for-clusters-as-promised'); | ||
const messages = new Debug('lru-cache-for-clusters-as-promised-messages'); | ||
@@ -30,2 +32,17 @@ // lru caches by namespace on the master | ||
function startPruneCronJob(cache, cronTime) { | ||
debug('Creating cache prune job.', cache); | ||
const job = new CronJob({ | ||
cronTime, | ||
onTick: () => { | ||
debug('Pruning cache', cache); | ||
cache.prune(); | ||
}, | ||
start: true, | ||
runOnInit: true, | ||
}); | ||
job.start(); | ||
return job; | ||
} | ||
// only run on the master thread | ||
@@ -38,2 +55,3 @@ if (cluster.isMaster) { | ||
if (request.source !== source) return; | ||
messages(`Master recieved message from worker ${worker.id}`, request); | ||
@@ -46,2 +64,3 @@ // send a response back to the worker thread | ||
response.func = request.func; | ||
messages(`Master sending response to worker ${worker.id}`, response); | ||
worker.send(response); | ||
@@ -61,2 +80,6 @@ } | ||
lru = caches[request.namespace] = new LRUCache(...request.arguments); | ||
// start a job to clean the cache | ||
if (request.arguments[0].prune) { | ||
lru.job = startPruneCronJob(lru, request.arguments[0].prune); | ||
} | ||
} | ||
@@ -123,2 +146,3 @@ sendResponse({ | ||
process.on('message', (response) => { | ||
messages(`Worker ${cluster.worker.id} recieved message`, response); | ||
// look up the callback based on the response ID, delete it, then call it | ||
@@ -161,2 +185,5 @@ if (response.source !== source || !callbacks[response.id]) return; | ||
lru = new LRUCache(options); | ||
if (options.prune) { | ||
lru.job = startPruneCronJob(lru, options.prune); | ||
} | ||
} | ||
@@ -248,3 +275,3 @@ } | ||
return { | ||
set: (key, value) => promiseTo('set', key, value), | ||
set: (key, value, maxAge) => promiseTo('set', key, value, maxAge), | ||
get: key => promiseTo('get', key), | ||
@@ -251,0 +278,0 @@ peek: key => promiseTo('peek', key), |
{ | ||
"name": "lru-cache-for-clusters-as-promised", | ||
"version": "1.3.1", | ||
"version": "1.4.0", | ||
"description": "LRU Cache that is safe for clusters", | ||
@@ -31,2 +31,3 @@ "main": "./lru-cache-for-clusters-as-promised.js", | ||
"dependencies": { | ||
"cron": "^1.1.1", | ||
"debug": "^2.2.0", | ||
@@ -41,7 +42,7 @@ "lru-cache": "^4.0.1", | ||
"eslint-plugin-jsx-a11y": "^2.2.3", | ||
"eslint-plugin-mocha": "^4.6.0", | ||
"eslint-plugin-react": "^6.4.0", | ||
"eslint-plugin-mocha": "^4.7.0", | ||
"eslint-plugin-react": "^6.4.1", | ||
"express": "^4.14.0", | ||
"should": "^11.1.1", | ||
"supertest": "^2.0.0" | ||
"supertest": "^2.0.1" | ||
}, | ||
@@ -48,0 +49,0 @@ "pre-commit": [ |
@@ -38,2 +38,4 @@ # lru-cache-for-clusters-as-promised | ||
* When `true` expired items are return before they are removed rather than `undefined` | ||
* `prune: false|crontime string`, defaults to `false` | ||
* Use a cron job on the master thread to call `prune()` on your cache at regular intervals specified in "crontime", for example "*/30 * * * * *" would prune the cache every 30 seconds. Also works in single threaded environments not using the `cluster` module. | ||
@@ -44,4 +46,4 @@ > ! note that `length` and `dispose` are missing as it is not possible to pass `functions` via IPC messages. | ||
* `set(key, value)` | ||
* Sets a value for a key. | ||
* `set(key, value, maxAge)` | ||
* Sets a value for a key. Specifying the `maxAge` will cause the value to expire per the `stale` value or when `prune`d. | ||
* `get(key)` | ||
@@ -137,28 +139,8 @@ * Returns a value for a key. | ||
**Clustered cache on master thread for clustered environments** | ||
``` | ||
+-----+ | ||
+--------+ +---------------+ +---------+ +---------------+ # M T # | ||
| +--> LRU Cache for +--> +--> Worker Sends +--># A H # | ||
| Worker | | Clusters as | | Promise | | IPC Message | # S R # | ||
| <--+ Promised <--+ <--+ to Master <---# T E # | ||
+--------+ +---------------+ +---------+ +---------------+ # E A # | ||
# R D # | ||
v---------------------------------------------------------------+-----+ | ||
+-----+ | ||
* W T * +--------------+ +--------+ +-----------+ | ||
* O H *---> Master +--> +--> LRU Cache | | ||
* R R * | IPC Message | | Master | | by | | ||
* K E *<--+ Listener <--+ <--+ namespace | | ||
* E A * +--------------+ +--------+ +-----------+ | ||
* R D * | ||
+-----+ | ||
``` | ||
![Clustered/Worker Thread](https://www.websequencediagrams.com/files/render?link=RqoArRgR8ZFZCL9ELm9C) | ||
**Promisified for non-clustered environments** | ||
``` | ||
+---------------+ +---------------+ +---------+ +-----------+ | ||
| +--> LRU Cache for +--> +--> | | ||
| Non-clustered | | Clusters as | | Promise | | LRU Cache | | ||
| <--+ Promised <--+ <--+ | | ||
+---------------+ +---------------+ +---------+ +-----------+ | ||
``` | ||
![Single/Master Thread](https://www.websequencediagrams.com/files/render?link=OfdL9HvP0ntvqPSAavdV) |
@@ -37,4 +37,3 @@ const request = require('supertest'); | ||
} | ||
response.body.should.equal(true); | ||
return done(); | ||
return response.body === true ? done() : done(new Error(response.body)); | ||
}); | ||
@@ -41,0 +40,0 @@ }); |
const config = require('./config'); | ||
const cluster = require('cluster'); | ||
const should = require('should'); | ||
const LRUCache = require('../../'); | ||
const member = cluster.isWorker ? 'worker' : 'master'; | ||
function TestUtils(cache) { | ||
@@ -13,2 +16,3 @@ return { | ||
tests: { | ||
pruneJob: 'prune cache using cron job', | ||
set: 'set(key, value)', | ||
@@ -56,3 +60,3 @@ get: 'get(key)', | ||
timeout: 1, | ||
namespace: 'bad-cache-resolve', | ||
namespace: `bad-cache-resolve-${member}`, | ||
}); | ||
@@ -73,3 +77,3 @@ let large = '1234567890'; | ||
failsafe: 'reject', | ||
namespace: 'bad-cache-reject', | ||
namespace: `bad-cache-reject-${member}`, | ||
}); | ||
@@ -84,2 +88,32 @@ let large = '1234567890'; | ||
}, | ||
pruneJob: (cb) => { | ||
const prunedCache = new LRUCache({ | ||
max: 10, | ||
stale: true, | ||
maxAge: 100, | ||
namespace: `pruned-cache-${member}`, | ||
prune: '*/1 * * * * *', | ||
}); | ||
prunedCache.set(config.args.one, config.args.one) | ||
.then(() => prunedCache.set(config.args.two, config.args.two, 2000)) | ||
.then(() => prunedCache.itemCount()) | ||
.then((itemCount) => { | ||
// we should see 2 items in the cache | ||
should(itemCount).equal(2); | ||
// check again in 1100 ms | ||
setTimeout(() => { | ||
// one of the items should have been removed based on the expiration | ||
prunedCache.itemCount() | ||
.then((itemCount2) => { | ||
try { | ||
should(itemCount2).equal(1); | ||
return cb(null, true); | ||
} catch (err) { | ||
return cb(err); | ||
} | ||
}); | ||
}, 1100); | ||
}) | ||
.catch(err => cb(err)); | ||
}, | ||
set: (cb) => { | ||
@@ -86,0 +120,0 @@ cache.set(config.args.one, config.args.one) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
36085
842
1
4
144
+ Addedcron@^1.1.1
+ Addedcron@1.8.3(transitive)
+ Addedluxon@1.28.1(transitive)