-
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* v4 main * fixed cacheHit reporting * updated interfaces * fixed readme and tests to match new config spec * fixed tests, remote store integrations * removed test .only Co-authored-by: Frederic Charette <[email protected]>
- Loading branch information
Showing
23 changed files
with
693 additions
and
288 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,8 @@ jobs: | |
uses: actions/setup-node@v1 | ||
with: | ||
node-version: ${{ matrix.node-version }} | ||
- name: Start Redis | ||
uses: supercharge/[email protected] | ||
- name: npm install, build, and test | ||
run: | | ||
npm install | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
{ | ||
"name": "ha-store", | ||
"version": "3.2.0", | ||
"version": "4.0.0", | ||
"description": "Efficient data fetching", | ||
"main": "src/index.js", | ||
"scripts": { | ||
|
@@ -20,11 +20,7 @@ | |
}, | ||
"keywords": [ | ||
"store", | ||
"availability", | ||
"optimize", | ||
"throughput", | ||
"cache", | ||
"service", | ||
"batch", | ||
"congestion", | ||
"tlru" | ||
|
@@ -35,9 +31,9 @@ | |
"author": "frederic charette <[email protected]>", | ||
"license": "Apache-2.0", | ||
"devDependencies": { | ||
"@ha-store/redis": "^4.0.1", | ||
"chai": "^4.3.0", | ||
"eslint": "^8.18.0", | ||
"ha-store-redis": "^2.0.1", | ||
"eslint": "^8.20.0", | ||
"mocha": "^10.0.0", | ||
"sinon": "^14.0.0", | ||
"split2": "^4.1.0" | ||
|
@@ -49,6 +45,6 @@ | |
], | ||
"typings": "./src/index.d.ts", | ||
"dependencies": { | ||
"lru-cache": "^7.10.0" | ||
"lru-cache": "^7.13.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
const {settleAndLog} = require('./utils'); | ||
|
||
function cachesConstructor(config, emitter) { | ||
const caches = config.cache.enabled && config.cache.tiers.map(tier => tier.store(tier)) || []; | ||
const local = caches.find(cache => cache.local); | ||
const remotes = caches.filter(cache => !cache.local); | ||
|
||
function getLocal(key) { | ||
return local && local.get(key); | ||
} | ||
|
||
function getMultiLocal(recordKey, keys) { | ||
return local && local.getMulti(recordKey, keys); | ||
} | ||
|
||
function get(key) { | ||
if (!config.cache.enabled) return undefined; | ||
|
||
const localValue = getLocal(key); | ||
if (localValue !== undefined) { | ||
emitter.track('localCacheHit', 1); | ||
emitter.track('cacheHit', 1); | ||
return localValue; | ||
} | ||
|
||
return settleAndLog(remotes.map((remote) => remote.get(key))) | ||
.then((remoteValues) => { | ||
const responseValue = remoteValues.find(value => value !== undefined); | ||
if (responseValue !== undefined) { | ||
emitter.track('cacheHit', 1); | ||
} | ||
else { | ||
emitter.track('cacheMiss', 1); | ||
} | ||
return remoteValues.find((response) => response !== undefined); | ||
}); | ||
} | ||
|
||
function getMulti(recordKey, keys) { | ||
if (!config.cache.enabled) return Promise.resolve(Array.from(new Array(keys.length), () => undefined)); | ||
|
||
const localValues = getMultiLocal(recordKey, keys); | ||
const foundLocally = localValues && localValues.filter(value => value !== undefined).length; | ||
if (foundLocally) { | ||
emitter.track('localCacheHit', foundLocally); | ||
emitter.track('cacheHit', foundLocally); | ||
} | ||
if (foundLocally && foundLocally === keys.length) { | ||
return Promise.resolve(localValues); | ||
} | ||
|
||
return settleAndLog(remotes.map((remote) => remote.getMulti(recordKey, keys))) | ||
.then((remoteValues) => { | ||
const responseValues = Object.assign(...remoteValues, localValues).map((value) => (value === null || value === undefined) ? undefined : JSON.parse(value)); | ||
const foundRemotely = remoteValues.filter((value) => value !== undefined); | ||
const missingValues = responseValues.filter((value) => value === undefined); | ||
emitter.track('cacheHit', foundRemotely.length); | ||
emitter.track('cacheMiss', missingValues.length); | ||
return responseValues; | ||
}); | ||
} | ||
|
||
function set(recordKey, keys, values) { | ||
local && local.set(recordKey, keys, values); | ||
return Promise.all(remotes.map((remote) => remote.set(recordKey, keys, values))).catch((err) => console.log('error writing', err)); | ||
} | ||
|
||
function clear(key) { | ||
local && local.clear(key); | ||
remotes.forEach((remote) => remote.clear(key)); | ||
return true; | ||
} | ||
|
||
function size() { | ||
if (!config.cache.enabled) { | ||
return Promise.resolve({ | ||
local: 0, | ||
remote: 0, | ||
status: 'disabled', | ||
}); | ||
} | ||
|
||
return Promise.resolve(remotes[0] && remotes[0].size()) | ||
.then((remoteItems) => { | ||
return { | ||
local: local && local.size(), | ||
remote: remoteItems || 0, | ||
} | ||
}); | ||
} | ||
|
||
return { | ||
get, | ||
getLocal, | ||
getMulti, | ||
getMultiLocal, | ||
set, | ||
clear, | ||
size, | ||
}; | ||
} | ||
|
||
module.exports = cachesConstructor; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
const EventEmitter = require('events').EventEmitter; | ||
|
||
class DeferredEmitter extends EventEmitter { | ||
constructor() { | ||
super(); | ||
this._counters = { | ||
localCacheHit: 0, | ||
cacheHit: 0, | ||
cacheMiss: 0, | ||
coalescedHit: 0, | ||
}; | ||
|
||
this._timer = setInterval(() => { | ||
for (const type in this._counters) { | ||
if (this._counters[type] !== 0) this.emit(type, this._counters[type]); | ||
this._counters[type] = 0; | ||
} | ||
}, 1000); | ||
} | ||
|
||
track(type, number) { | ||
this._counters[type] += number; | ||
} | ||
} | ||
|
||
module.exports = DeferredEmitter; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.