Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add async cache.fetch() method, fetchMethod option
Fix: #102
- Loading branch information
Showing
3 changed files
with
208 additions
and
4 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
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,97 @@ | ||
const t = require('tap') | ||
const fn = async (k, v) => | ||
new Promise(res => setImmediate(() => res(v === undefined ? 0 : (v + 1)))) | ||
|
||
const Clock = require('clock-mock') | ||
const clock = new Clock() | ||
t.teardown(clock.enter()) | ||
clock.advance(1) | ||
|
||
const LRU = require('../') | ||
const c = new LRU({ | ||
fetchMethod: fn, | ||
max: 5, | ||
ttl: 5, | ||
}) | ||
|
||
t.test('asynchronous fetching', async t => { | ||
const v1 = await c.fetch('key') | ||
t.equal(v1, 0, 'first fetch, no stale data, wait for initial value') | ||
const v2 = await c.fetch('key') | ||
t.equal(v2, 0, 'got same cached value') | ||
|
||
clock.advance(10) | ||
|
||
const v3 = await c.fetch('key', { allowStale: true }) | ||
t.equal(v3, 0, 'fetch while stale, allowStale, get stale data') | ||
t.equal(await c.fetch('key', { allowStale: true }), 0, | ||
'get stale data again while re-fetching because stale previously') | ||
const v4 = await c.fetch('key') | ||
t.equal(v4, 1, 'no allow stale, wait until fresh data available') | ||
const v5 = await c.fetch('key') | ||
t.equal(v5, 1, 'fetch while not stale, just get from cache') | ||
|
||
clock.advance(10) | ||
|
||
const v6 = await c.fetch('key', { allowStale: true }) | ||
t.equal(v6, 1, 'fetch while stale, starts new fetch, return stale data') | ||
const v = c.valList[0] | ||
t.equal(c.isBackgroundFetch(v), true) | ||
t.equal(c.backgroundFetch('key', 0), v) | ||
await v | ||
const v7 = await c.fetch('key', { allowStale: true, updateAgeOnGet: true }) | ||
t.equal(v7, 2, 'fetch completed, so get new data') | ||
|
||
clock.advance(100) | ||
|
||
const v8 = await c.fetch('key', { allowStale: true }) | ||
const v9 = c.get('key', { allowStale: true }) | ||
t.equal(v8, 2, 'fetch returned stale while fetching') | ||
t.equal(v9, 2, 'get() returned stale while fetching') | ||
|
||
const v10 = c.fetch('key2') | ||
const v11 = c.get('key2') | ||
t.equal(v11, undefined, 'get while fetching but not yet returned') | ||
t.equal(await v10, 0, 'eventually 0 is returned') | ||
const v12 = c.get('key2') | ||
t.equal(v12, 0, 'get cached value after fetch') | ||
|
||
const v13 = c.fetch('key3') | ||
c.delete('key3') | ||
t.equal(await v13, 0, 'returned 0 eventually') | ||
t.equal(c.has('key3'), false, 'but not inserted into cache') | ||
|
||
const v14 = c.fetch('key4') | ||
clock.advance(100) | ||
const v15 = await c.fetch('key4', { allowStale: true }) | ||
t.equal(v15, 0, 'there was no stale data, even though we were ok with that') | ||
|
||
c.set('key5', 0) | ||
clock.advance(100) | ||
const v16 = await c.fetch('key5') | ||
t.equal(v16, 1, 'waited for new data, data in cache was stale') | ||
|
||
const v17 = c.fetch('key4') | ||
clock.advance(100) | ||
const v18 = c.get('key4') | ||
t.equal(v18, undefined, 'get while fetching, but did not want stale data') | ||
|
||
const v19 = c.fetch('key6') | ||
clock.advance(100) | ||
const v20 = c.get('key6', { allowStale: true }) | ||
t.equal(v20, undefined, 'get while fetching, but no stale data to return') | ||
}) | ||
|
||
t.test('fetchMethod must be a function', async t => { | ||
t.throws(() => new LRU({fetchMethod: true, max: 2})) | ||
}) | ||
|
||
t.test('fetch without fetch method', async t => { | ||
const c = new LRU({ max: 3 }) | ||
c.set(0, 0) | ||
c.set(1, 1) | ||
t.same(await Promise.all([ | ||
c.fetch(0), | ||
c.fetch(1), | ||
]), [0, 1]) | ||
}) |