Skip to content

Commit e8dffb5

Browse files
author
Ben Clark
authored
Add refresh method to handle invalidation (#2)
1 parent 2468098 commit e8dffb5

7 files changed

+69
-4
lines changed

.vscode/settings.json

+3
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,8 @@
5050
"**/.eslintcache": true,
5151
"**/.cache": true,
5252
"**/.fuse_hidden*": true
53+
},
54+
"editor.codeActionsOnSave": {
55+
"source.fixAll.eslint": true
5356
}
5457
}

README.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ const myObjectCache = new LeprechaunCache({
3434
onBackgroundError: e => { console.error(e); }
3535
})
3636

37-
const myObject = myObjectCache.get('object-id') //get the object with key 'object-id'. If it doesn't exist, onMiss will be called, and the data will be stored in the cache with a soft TTL of 1000ms
37+
const myObject = await myObjectCache.get('object-id') //get the object with key 'object-id'. If it doesn't exist, onMiss will be called, and the data will be stored in the cache with a soft TTL of 1000ms
38+
39+
const myObject = await myObjectCache.refresh('object-id') //Force refresh (calls the onMiss handler and updates the cache) and return the result
40+
41+
await myObjectCache.clear('object-id') //Remove the item from the cache
3842
```
3943

4044
## Constructor Options

package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@acuris/leprechaun-cache",
3-
"version": "0.0.6",
3+
"version": "0.0.7",
44
"private": false,
55
"description": "Caching library that supports double checked caching and stale returns to avoid stampede and slow responses",
66
"keywords": [

src/leprechaun-cache.ts

+4
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ export class LeprechaunCache<T extends Cacheable = Cacheable> {
7272
return promise
7373
}
7474

75+
public async refresh(key: string): Promise<T> {
76+
return this.updateCache(key, this.softTtlMs, true)
77+
}
78+
7579
private async doGet(key: string, ttl: number): Promise<T> {
7680
const result = await this.cacheStore.get(this.keyPrefix + key)
7781
if (!result) {

test/integration/leprechaun-cache-redis.spec.ts

+28
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ describe('Leprechaun Cache (integration)', () => {
224224
const results2 = await cache.get(key)
225225
expect(results2).to.deep.equal(data2)
226226
})
227+
227228
it('should save and return undefined and null and false correctly', async () => {
228229
const onMissStub = sandbox.stub()
229230
onMissStub.withArgs('key-undefined').resolves(undefined)
@@ -263,4 +264,31 @@ describe('Leprechaun Cache (integration)', () => {
263264
expect(result5).to.equal(0)
264265
expect(await cache.get('key-zero')).to.equal(0)
265266
})
267+
268+
it('should refresh the cache when refresh is called when not yet expired', async () => {
269+
const onMissStub = sandbox.stub()
270+
const res1 = { res: 1 }
271+
const res2 = { res: 2 }
272+
onMissStub.onCall(0).resolves(res1)
273+
onMissStub.onCall(1).resolves(res2)
274+
275+
const cache = new LeprechaunCache({
276+
softTtlMs: 10000,
277+
hardTtlMs: 10000,
278+
waitForUnlockMs: 1000,
279+
spinMs: 50,
280+
lockTtlMs: 1000,
281+
cacheStore,
282+
returnStale: true,
283+
onMiss: onMissStub
284+
})
285+
286+
const result1 = await cache.get('key')
287+
expect(result1).to.deep.equal(res1)
288+
await delay(10)
289+
290+
await cache.refresh('key')
291+
const result2 = await cache.get('key')
292+
expect(result2).to.deep.equal(res2)
293+
})
266294
})

test/unit/leprechaun-cache.spec.ts

+26
Original file line numberDiff line numberDiff line change
@@ -274,4 +274,30 @@ describe('Leprechaun Cache', () => {
274274

275275
expect(await memoryCacheStore.get('prefix-key')).to.not.be.null
276276
})
277+
278+
it('should refresh the cache when refresh is called when not yet expired', async () => {
279+
const onMissStub = sandbox.stub()
280+
const res1 = { res: 1 }
281+
const res2 = { res: 2 }
282+
onMissStub.onCall(0).resolves(res1)
283+
onMissStub.onCall(1).resolves(res2)
284+
285+
const cache = new LeprechaunCache({
286+
softTtlMs: 10000,
287+
hardTtlMs: 10000,
288+
waitForUnlockMs: 1000,
289+
spinMs: 50,
290+
lockTtlMs: 1000,
291+
cacheStore: memoryCacheStore,
292+
returnStale: true,
293+
onMiss: onMissStub
294+
})
295+
296+
const result1 = await cache.get('key')
297+
expect(result1).to.deep.equal(res1)
298+
299+
await cache.refresh('key')
300+
const result2 = await cache.get('key')
301+
expect(result2).to.deep.equal(res2)
302+
})
277303
})

0 commit comments

Comments
 (0)