Skip to content

Commit

Permalink
feat(memoize): add a way to invalidate on demand
Browse files Browse the repository at this point in the history
  • Loading branch information
Kikobeats committed Aug 19, 2021
1 parent dd584d4 commit 82e713b
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 6 deletions.
14 changes: 13 additions & 1 deletion packages/memoize/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,24 @@ Default: `identity`

It defines how the get will be obtained.

The signature of the function should be a `String` to be used as key associated with the cache copy:

```js
key: ({req}) => req.url
```

Just in case you need a more granular control, you can return an `Array`, where the second value determines the expiration behavior:

```js
key: ({req}) => [req.url, req.query.forceExpiration]
```

##### objectMode

Type: `Boolean`<br/>
Default: `false`

When is `true`, the result will be an Array, being the second item in the array some information about the item:
When is `true`, the result will be an `Array`, being the second item in the `Array` some information about the item:

```js
const fn = () => Promise.reject(new Error('NOPE'))
Expand Down
9 changes: 6 additions & 3 deletions packages/memoize/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ function memoize (
* @return {Promise<*>}
*/
function memoized (...args) {
const key = getKey(...args)
const rawKey = getKey(...args)
const [key, forceExpiration] = Array.isArray(rawKey) ? rawKey : [rawKey]

if (!isUndefined(pending[key])) {
return pAny([getStoredValue(key), pending[key]])
Expand All @@ -82,8 +83,10 @@ function memoize (
const ttlValue = hasExpires ? data.expires - Date.now() : undefined
const staleTtlValue =
hasExpires && !isUndefined(staleTtl) ? staleTtl(data.value) : false

const isExpired = staleTtlValue === false && hasExpires && ttlValue < 0
const isExpired =
forceExpiration !== undefined
? forceExpiration
: staleTtlValue === false && hasExpires && ttlValue < 0
const isStale = staleTtlValue !== false && ttlValue < staleTtlValue
const info = { hasValue, key, isExpired, isStale }
const done = value => (objectMode ? [value, info] : value)
Expand Down
34 changes: 32 additions & 2 deletions packages/memoize/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ test('should store result with static ttl', async t => {
t.deepEqual(calls, [1, 3, 5])
})

test('ttl as function', async t => {
test('should accept `ttl` as function', async t => {
let calls = []

const store = new Map()
Expand All @@ -247,7 +247,7 @@ test('ttl as function', async t => {
t.deepEqual(calls, [1, 6, 6])
})

test('staleTtl as function', async t => {
test('should accept `staleTtl` as function', async t => {
const memoizeFn = memoize(() => ({ value: 'foo', stale: 1 }), new Map(), {
ttl: 1,
staleTtl: ({ stale }) => stale,
Expand All @@ -262,3 +262,33 @@ test('staleTtl as function', async t => {
t.true(infoTwo.isStale)
t.true(infoTwo.hasValue)
})

test('should be possible force expiration', async t => {
let index = 0

const store = new Map()
const fn = () => ++index
const key = ({ key, forceExpiration }) => [key, forceExpiration]

const memoizeFn = memoize(fn, store, { ttl: Infinity, key, objectMode: true })

const [valueOne] = await memoizeFn({
key: 'foo',
forceExpiration: false
})

const [valueTwo] = await memoizeFn({
key: 'foo',
forceExpiration: false
})

t.is(valueOne, 1)
t.is(valueOne, valueTwo)

const [valueThree] = await memoizeFn({
key: 'foo',
forceExpiration: true
})

t.is(valueThree, 2)
})

0 comments on commit 82e713b

Please sign in to comment.