dobi-cache-2
Advanced tools
Comparing version 3.0.6 to 3.0.7
@@ -7,9 +7,23 @@ /* eslint-disable no-process-env */ | ||
const isNil = require('lodash/isNil'); | ||
const LRU = require('lru-cache'); | ||
module.exports = class CacheHelper { | ||
constructor({ disabled = false, keyPrefix = 'dobiCache', redisUri }) { | ||
this.disabled = !(!disabled && redisUri); | ||
/** | ||
* @param {Object} config | ||
* @param {boolean} config.enabled=true | ||
* @param {string} config.keyPrefix=dobiCache prefix for redis keys | ||
* @param {number} config.lruMaxItems max number of lru items | ||
* @param {string} config.redisUri uri for redis server | ||
*/ | ||
constructor({ | ||
enabled, | ||
keyPrefix = 'dobiCache', | ||
lruMaxItems: max = 100, | ||
redisUri, | ||
}) { | ||
this.enabled = enabled; | ||
this.redisUri = redisUri; | ||
this.keyPrefix = keyPrefix; | ||
this.state = 'initializing'; | ||
this.redisState = 'initializing'; | ||
this.lru = LRU({ max }); | ||
this.redis = new Redis(this.redisUri, { | ||
@@ -22,20 +36,38 @@ lazyConnect: true, | ||
isDisabled() { | ||
return this.disabled || this.state !== 'connected'; | ||
return !(this.enabled && this.method); | ||
} | ||
async connect() { | ||
if (this.disabled || this.state !== 'initializing') { | ||
if (!this.enabled || this.redisState !== 'initializing') { | ||
return; | ||
} | ||
try { | ||
this.state = 'pending'; | ||
this.redisState = 'pending'; | ||
await this.redis.connect(); | ||
this.state = 'connected'; | ||
this.redisState = 'connected'; | ||
this.method = 'redis'; | ||
} catch (err) { | ||
this.state = 'disconnected'; | ||
this.redisState = 'disconnected'; | ||
this.method = 'lru'; | ||
// eslint-disable-next-line no-console | ||
console.warn(`redis server not found, cache disabled: ${this.redisUri}`); | ||
console.warn(`redis server not found: ${this.redisUri}. using LRU cache`); | ||
} | ||
} | ||
async getKeys() { | ||
if (this.isDisabled()) { | ||
return []; | ||
} | ||
let keys = []; | ||
if (this.method === 'redis') { | ||
keys = await this.redis.keys(`${this.keyPrefix}:*`); | ||
} else { | ||
keys = this.lru.keys(); | ||
} | ||
return keys.map(key => ( | ||
key.replace(new RegExp(`^${this.keyPrefix}:`), '') | ||
)); | ||
} | ||
async flushCache() { | ||
@@ -45,6 +77,6 @@ if (this.isDisabled()) { | ||
} | ||
const keys = await this.redis.keys(`${this.keyPrefix}:*`); | ||
const keys = await this.getKeys(); | ||
const flushed = []; | ||
const promises = keys.map(async (key) => { | ||
flushed.push(await this.redis.del(key)); | ||
flushed.push(await this.delete(key)); | ||
}); | ||
@@ -56,3 +88,3 @@ | ||
getKey(key) { | ||
buildKey(key) { | ||
return `${this.keyPrefix}:${key}`; | ||
@@ -65,3 +97,9 @@ } | ||
} | ||
return this.redis.del(this.getKey(key)); | ||
const itemKey = this.buildKey(key); | ||
if (this.method === 'redis') { | ||
return this.redis.del(itemKey); | ||
} | ||
const result = this.lru.peek(itemKey) ? 1 : 0; | ||
this.lru.del(itemKey); | ||
return result; | ||
} | ||
@@ -74,3 +112,8 @@ | ||
try { | ||
const document = await this.redis.get(this.getKey(key)); | ||
let document; | ||
if (this.method === 'redis') { | ||
document = await this.redis.get(this.buildKey(key)); | ||
} else { | ||
document = this.lru.get(this.buildKey(key)); | ||
} | ||
if (!document) { | ||
@@ -104,5 +147,12 @@ return null; | ||
} | ||
await this.redis.set(this.getKey(key), JSON.stringify({ type, value })); | ||
await this.redis.expire(this.getKey(key), ttl); | ||
const itemKey = this.buildKey(key); | ||
const itemValue = JSON.stringify({ type, value }); | ||
if (this.method === 'redis') { | ||
await this.redis.set(itemKey, itemValue); | ||
await this.redis.expire(itemKey, ttl); | ||
} else { | ||
this.lru.set(itemKey, itemValue, ttl * 1000); | ||
} | ||
} | ||
}; |
@@ -9,8 +9,20 @@ 'use strict'; | ||
module.exports = class Cache { | ||
constructor(config) { | ||
this.config = config; | ||
/** | ||
* @param {Object} config | ||
* @param {boolean} config.enabled=true | ||
* @param {string} config.keyPrefix=dobiCache prefix for redis keys | ||
* @param {number} config.lruMaxItems max number of lru items | ||
* @param {string} config.redisUri uri for redis server | ||
*/ | ||
constructor({ | ||
enabled = true, | ||
keyPrefix = 'dobiCache', | ||
lruMaxItems = 100, | ||
redisUri, | ||
}) { | ||
// connect to redis | ||
const { disabled, keyPrefix, redisUri } = config; | ||
this.cacheHelper = new CacheHelper({ disabled, keyPrefix, redisUri }); | ||
this.enabled = enabled; | ||
this.cacheHelper = new CacheHelper({ | ||
enabled, keyPrefix, lruMaxItems, redisUri, | ||
}); | ||
this.flushCache = this.cacheHelper.flushCache.bind(this.cacheHelper); | ||
@@ -91,4 +103,2 @@ this.cache = this.cache.bind(this); | ||
const { disabled = false } = this.config; | ||
const { | ||
@@ -103,3 +113,3 @@ headers = {}, | ||
if (disabled || method === 'POST' || skipCache) { | ||
if (!this.enabled || method === 'POST' || skipCache) { | ||
const data = await asyncFetch(); | ||
@@ -106,0 +116,0 @@ return res.send(data); |
@@ -9,2 +9,3 @@ { | ||
"lodash": "^4.17.11", | ||
"lru-cache": "^4.1.3", | ||
"parseurl": "^1.3.2" | ||
@@ -28,3 +29,3 @@ }, | ||
}, | ||
"version": "3.0.6", | ||
"version": "3.0.7", | ||
"devDependencies": { | ||
@@ -31,0 +32,0 @@ "eslint": "^5.5.0", |
@@ -10,3 +10,3 @@ 'use strict'; | ||
const cacheFlushTester = new Cache({ | ||
disabled: false, | ||
enabled: true, | ||
keyPrefix: 'flushTest', | ||
@@ -16,4 +16,10 @@ redisUri: 'localhost', | ||
const cacheDisabled = new Cache({ | ||
enabled: false, | ||
keyPrefix: 'flushTest', | ||
redisUri: 'localhost', | ||
}); | ||
const cacheServer = new Cache({ | ||
disabled: false, | ||
enabled: true, | ||
redisUri: 'localhost', | ||
@@ -23,3 +29,3 @@ }); | ||
const cacheDisconnected = new Cache({ | ||
disabled: false, | ||
enabled: true, | ||
redisUri: 'failfailfail', | ||
@@ -30,2 +36,3 @@ }); | ||
let disconnectedApp; | ||
let disabledApp; | ||
beforeAll(async () => { | ||
@@ -43,2 +50,3 @@ await cacheFlushTester.cacheHelper.connect(); | ||
disconnectedApp = appGenerator(cacheDisconnected.cache); | ||
disabledApp = appGenerator(cacheDisabled.cache); | ||
}); | ||
@@ -50,11 +58,13 @@ | ||
expect(resp.headers['dobi-cache']).toBe('MISS'); | ||
const resp2 = await request(connectedApp).get('/'); | ||
if (resp2.headers['dobi-cache'] === 'MISS') { | ||
// eslint-disable-next-line no-console | ||
console.error('run redis locally to test'); | ||
} | ||
expect(resp2.headers['dobi-cache']).toBe('HIT'); | ||
}); | ||
it('works if disabled', async () => { | ||
const resp = await request(disabledApp).get('/'); | ||
expect(resp.headers['dobi-cache']).toBe(undefined); | ||
const resp2 = await request(disabledApp).get('/'); | ||
expect(resp2.headers['dobi-cache']).toBe(undefined); | ||
}); | ||
it('allows bypass', async () => { | ||
@@ -61,0 +71,0 @@ const resp = await request(connectedApp).get('/?_=234234234'); |
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
26350
454
1
4
+ Addedlru-cache@^4.1.3
+ Addedlru-cache@4.1.5(transitive)
+ Addedpseudomap@1.0.2(transitive)
+ Addedyallist@2.1.2(transitive)