Skip to content

Commit dad0e43

Browse files
committed
Added ttl
1 parent f933f02 commit dad0e43

File tree

2 files changed

+60
-4
lines changed

2 files changed

+60
-4
lines changed

index.js

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@ const kValues = require('./symbol')
44
const stringify = require('safe-stable-stringify')
55
const LRUCache = require('mnemonist/lru-cache')
66

7+
const kCacheSize = Symbol('kCacheSize')
8+
const kTTL = Symbol('kTTL')
9+
710
class Cache {
811
constructor (opts) {
912
opts = opts || {}
1013
this[kValues] = {}
11-
this._cacheSize = opts.cacheSize || 1024
14+
this[kCacheSize] = opts.cacheSize || 1024
15+
this[kTTL] = opts.ttl || 0
1216
}
1317

1418
define (key, opts, func) {
@@ -28,23 +32,40 @@ class Cache {
2832
throw new TypeError('serialize must be a function')
2933
}
3034

31-
const cacheSize = opts.cacheSize || this._cacheSize
35+
const cacheSize = opts.cacheSize || this[kCacheSize]
36+
const ttl = opts.ttl || this[kTTL]
3237

33-
const wrapper = new Wrapper(func, key, serialize, cacheSize)
38+
const wrapper = new Wrapper(func, key, serialize, cacheSize, ttl)
3439

3540
this[kValues][key] = wrapper
3641
this[key] = wrapper.add.bind(wrapper)
3742
}
3843
}
3944

45+
let _currentSecond
46+
47+
function currentSecond () {
48+
if (_currentSecond !== undefined) {
49+
return _currentSecond
50+
}
51+
_currentSecond = Math.floor(Date.now() / 1000)
52+
setTimeout(_clearSecond, 1000).unref()
53+
return _currentSecond
54+
}
55+
56+
function _clearSecond () {
57+
_currentSecond = undefined
58+
}
59+
4060
class Wrapper {
41-
constructor (func, key, serialize, cacheSize) {
61+
constructor (func, key, serialize, cacheSize, ttl) {
4262
this.ids = new LRUCache(cacheSize)
4363
this.error = null
4464
this.started = false
4565
this.func = func
4666
this.key = key
4767
this.serialize = serialize
68+
this.ttl = ttl
4869
}
4970

5071
add (args) {
@@ -55,8 +76,15 @@ class Wrapper {
5576
if (!query) {
5677
query = new Query(id, args, this.func)
5778
this.ids.set(key, query)
79+
} else if (this.ttl > 0) {
80+
if (currentSecond() - query.lastAccessed > this.ttl) {
81+
// restart
82+
query.promise = this.func.call(null, args)
83+
}
5884
}
5985

86+
query.touch()
87+
6088
return query.promise
6189
}
6290
}
@@ -65,6 +93,11 @@ class Query {
6593
constructor (id, args, func) {
6694
this.id = id
6795
this.promise = func(args)
96+
this.lastAccessed = null
97+
}
98+
99+
touch () {
100+
this.lastAccessed = currentSecond()
68101
}
69102
}
70103

test.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
const { test } = require('tap')
44
const { Cache } = require('.')
5+
const { promisify } = require('util')
6+
7+
const sleep = promisify(setTimeout)
58

69
const kValues = require('./symbol')
710

@@ -214,3 +217,23 @@ test('cacheSize on constructor', async (t) => {
214217
{ k: 42 }
215218
])
216219
})
220+
221+
test('ttl', async (t) => {
222+
t.plan(5)
223+
224+
const cache = new Cache({
225+
ttl: 1 // seconds
226+
})
227+
228+
cache.define('fetchSomething', async (query) => {
229+
t.equal(query, 42)
230+
return { k: query }
231+
})
232+
233+
t.same(await cache.fetchSomething(42), { k: 42 })
234+
t.same(await cache.fetchSomething(42), { k: 42 })
235+
236+
await sleep(2000)
237+
238+
t.same(await cache.fetchSomething(42), { k: 42 })
239+
})

0 commit comments

Comments
 (0)