@level-two/core
Advanced tools
Comparing version 1.1.0 to 1.2.0
@@ -124,2 +124,9 @@ /// <reference types="node" /> | ||
/** | ||
* Similar to getMulti, fetches list of values for the identifiers provided, but | ||
* raises exceptions when they are found instead of returning errors | ||
* | ||
* @param ids List of unique identifiers to get | ||
*/ | ||
getUnsafeMulti(ids: IdentifierType[]): Promise<Array<ResultType | undefined>>; | ||
/** | ||
* Exposes data as it becomes available for the unique identifiers requested | ||
@@ -324,2 +331,12 @@ * | ||
/** | ||
* Normalized runner for fetching a batch of values from a list of unique | ||
* identifiers, merging in the pre-cached results | ||
* | ||
* @param ids List of unique identifiers to get | ||
* @param cachedValues List of cached results mapping to the id | ||
* @param staleIds List of cached identifiers that need to be re-fetched | ||
* @param raiseExceptions Indicates if exceptions should be thrown instead of returned | ||
*/ | ||
private runBatchFetch; | ||
/** | ||
* Valve fetcher process. Looks for data first in the remote cache, then | ||
@@ -326,0 +343,0 @@ * falls back to the worker fetch process |
@@ -144,3 +144,3 @@ "use strict"; | ||
// Test local cache to see if all results can be returned immediately | ||
const [needsFetch, quickResults, staleIds] = this.getCachedEntries(ids); | ||
const [needsFetch, cachedValues, staleIds] = this.getCachedEntries(ids); | ||
if (!needsFetch) { | ||
@@ -150,31 +150,24 @@ if (staleIds.length) { | ||
} | ||
return quickResults; | ||
return cachedValues; | ||
} | ||
// Only get uncached entries | ||
const fetchSet = new Set(); | ||
const results = new Map(); | ||
quickResults.forEach((value, index) => { | ||
const id = ids[index]; | ||
if (value === undefined) { | ||
fetchSet.add(id); | ||
} | ||
else { | ||
results.set(id, value); | ||
} | ||
}); | ||
return new Promise((resolve, reject) => { | ||
const fetchIds = Array.from(fetchSet); | ||
this.burstValve | ||
.batch(fetchIds) | ||
.then((batchResults) => { | ||
if (batchResults) { | ||
fetchIds.forEach((id, index) => results.set(id, batchResults[index])); | ||
} | ||
resolve(ids.map((id) => results.get(id))); | ||
}) | ||
.catch(reject); | ||
// Run the actual batch fetching, returning any errors as result entries | ||
return this.runBatchFetch(ids, cachedValues, staleIds); | ||
} | ||
/** | ||
* Similar to getMulti, fetches list of values for the identifiers provided, but | ||
* raises exceptions when they are found instead of returning errors | ||
* | ||
* @param ids List of unique identifiers to get | ||
*/ | ||
async getUnsafeMulti(ids) { | ||
// Test local cache to see if all results can be returned immediately | ||
const [needsFetch, cachedValues, staleIds] = this.getCachedEntries(ids); | ||
if (!needsFetch) { | ||
if (staleIds.length) { | ||
this.upsertStaleIds(staleIds); | ||
} | ||
}); | ||
return cachedValues; | ||
} | ||
// Run the actual batch fetching, raising any exceptions | ||
return this.runBatchFetch(ids, cachedValues, staleIds, true); | ||
} | ||
@@ -720,2 +713,42 @@ /** | ||
/** | ||
* Normalized runner for fetching a batch of values from a list of unique | ||
* identifiers, merging in the pre-cached results | ||
* | ||
* @param ids List of unique identifiers to get | ||
* @param cachedValues List of cached results mapping to the id | ||
* @param staleIds List of cached identifiers that need to be re-fetched | ||
* @param raiseExceptions Indicates if exceptions should be thrown instead of returned | ||
*/ | ||
async runBatchFetch(ids, cachedValues, staleIds, raiseExceptions) { | ||
// Only get uncached entries | ||
const fetchSet = new Set(); | ||
const results = new Map(); | ||
cachedValues.forEach((value, index) => { | ||
const id = ids[index]; | ||
if (value === undefined) { | ||
fetchSet.add(id); | ||
} | ||
else { | ||
results.set(id, value); | ||
} | ||
}); | ||
return new Promise((resolve, reject) => { | ||
const fetchIds = Array.from(fetchSet); | ||
const batchPromise = raiseExceptions | ||
? this.burstValve.unsafeBatch(fetchIds) | ||
: this.burstValve.batch(fetchIds); | ||
batchPromise | ||
.then((batchResults) => { | ||
if (batchResults) { | ||
fetchIds.forEach((id, index) => results.set(id, batchResults[index])); | ||
} | ||
resolve(ids.map((id) => results.get(id))); | ||
}) | ||
.catch(reject); | ||
if (staleIds.length) { | ||
this.upsertStaleIds(staleIds); | ||
} | ||
}); | ||
} | ||
/** | ||
* Valve fetcher process. Looks for data first in the remote cache, then | ||
@@ -738,3 +771,3 @@ * falls back to the worker fetch process | ||
const remote = this.remoteCache; | ||
await new Promise((resolve) => { | ||
await new Promise((resolve, reject) => { | ||
let finished = false; | ||
@@ -773,30 +806,40 @@ const remoteResults = new Map(); | ||
finished = true; | ||
// Mapped results from cache fetching | ||
if (response instanceof Map) { | ||
response.forEach((value, id) => { | ||
writeRemoteResult(id, value); | ||
}); | ||
} | ||
// Array of results matching the cache ids passed in | ||
else if (Array.isArray(response)) { | ||
// Enforcing array matching | ||
if (response.length !== ids.length) { | ||
const error = new Error(`Remote cache fetch returned inconsistent result length with fetch ids requested`); | ||
ids.forEach((id) => writeRemoteResult(id, error)); | ||
try { | ||
// Mapped results from cache fetching | ||
if (response instanceof Map) { | ||
response.forEach((value, id) => { | ||
writeRemoteResult(id, value); | ||
}); | ||
} | ||
else { | ||
response.forEach((value, index) => writeRemoteResult(ids[index], value)); | ||
// Array of results matching the cache ids passed in | ||
else if (Array.isArray(response)) { | ||
// Enforcing array matching | ||
if (response.length !== ids.length) { | ||
const error = new Error(`Remote cache fetch returned inconsistent result length with fetch ids requested`); | ||
ids.forEach((id) => writeRemoteResult(id, error)); | ||
} | ||
else { | ||
response.forEach((value, index) => writeRemoteResult(ids[index], value)); | ||
} | ||
return resolve(); | ||
} | ||
return resolve(); | ||
// Ensure all ids are at least written | ||
ids.forEach((id) => writeRemoteResult(id, undefined)); | ||
resolve(); | ||
} | ||
// Ensure all ids are at least written | ||
ids.forEach((id) => writeRemoteResult(id, undefined)); | ||
resolve(); | ||
catch (e) { | ||
reject(e); | ||
} | ||
}) | ||
.catch((e) => { | ||
finished = true; | ||
// Ignore exceptions when configured | ||
const error = new Error(`Remote cache.get error`, { cause: e }); | ||
ids.forEach((id) => writeRemoteResult(id, this.ignoreCacheFetchErrors ? undefined : error)); | ||
resolve(); | ||
try { | ||
// Ignore exceptions when configured | ||
const error = new Error(`Remote cache.get error`, { cause: e }); | ||
ids.forEach((id) => writeRemoteResult(id, this.ignoreCacheFetchErrors ? undefined : error)); | ||
resolve(); | ||
} | ||
catch (e) { | ||
reject(e); | ||
} | ||
}); | ||
@@ -807,3 +850,3 @@ }); | ||
if (batchIds.length > 0) { | ||
await new Promise((resolve) => { | ||
await new Promise((resolve, reject) => { | ||
let finished = false; | ||
@@ -843,32 +886,42 @@ const results = new Map(); | ||
finished = true; | ||
// Map of results | ||
if (response instanceof Map) { | ||
response.forEach((value, id) => { | ||
writeResult(id, value); | ||
}); | ||
} | ||
// Array of results matching the batch ids passed in | ||
else if (Array.isArray(response)) { | ||
// Enforcing array matching | ||
if (response.length !== batchIds.length) { | ||
const error = new Error(`Worker fetch results length does not match batch id length`); | ||
batchIds.forEach((id) => writeResult(id, error)); | ||
try { | ||
// Map of results | ||
if (response instanceof Map) { | ||
response.forEach((value, id) => { | ||
writeResult(id, value); | ||
}); | ||
} | ||
else { | ||
response.forEach((value, index) => writeResult(batchIds[index], value)); | ||
// Array of results matching the batch ids passed in | ||
else if (Array.isArray(response)) { | ||
// Enforcing array matching | ||
if (response.length !== batchIds.length) { | ||
const error = new Error(`Worker fetch results length does not match batch id length`); | ||
batchIds.forEach((id) => writeResult(id, error)); | ||
} | ||
else { | ||
response.forEach((value, index) => writeResult(batchIds[index], value)); | ||
} | ||
return resolve(); | ||
} | ||
return resolve(); | ||
// Ensure all ids are accounted for | ||
batchIds.forEach((id) => writeResult(id, undefined)); | ||
resolve(); | ||
} | ||
// Ensure all ids are accounted for | ||
batchIds.forEach((id) => writeResult(id, undefined)); | ||
resolve(); | ||
catch (e) { | ||
reject(e); | ||
} | ||
}) | ||
.catch((e) => { | ||
finished = true; | ||
// Write error to every batch id | ||
const error = new Error(`Worker fetch fetch process error`, { | ||
cause: e, | ||
}); | ||
batchIds.forEach((id) => writeResult(id, error)); | ||
resolve(); | ||
try { | ||
// Write error to every batch id | ||
const error = new Error(`Worker fetch process error`, { | ||
cause: e, | ||
}); | ||
batchIds.forEach((id) => writeResult(id, error)); | ||
resolve(); | ||
} | ||
catch (e) { | ||
reject(e); | ||
} | ||
}); | ||
@@ -875,0 +928,0 @@ }); |
{ | ||
"name": "@level-two/core", | ||
"version": "1.1.0", | ||
"version": "1.2.0", | ||
"description": "A distributed in-process cache", | ||
@@ -50,3 +50,3 @@ "author": "Corey Hart <corey@codenothing.com>", | ||
"dependencies": { | ||
"burst-valve": "^1.2.0" | ||
"burst-valve": "^1.3.0" | ||
}, | ||
@@ -56,3 +56,3 @@ "publishConfig": { | ||
}, | ||
"gitHead": "190435e80544664b8d6e9277f43a23f56c8af1bb" | ||
"gitHead": "60334dd75d9baf8fb1b303cdad64ee9ebab13105" | ||
} |
@@ -167,2 +167,6 @@ # LevelTwo | ||
### `getUnsafeMulti(ids: IdentifierType[])` | ||
Similar to getMulti, fetches list of values for the identifiers provided, but raises exceptions when they are found instead of returning errors | ||
### `stream(ids: IdentifierType[], streamResultCallback: (id: IdentifierType, result: ResultType) => Promise<void>)` | ||
@@ -169,0 +173,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
120317
1714
324
Updatedburst-valve@^1.3.0