Skip to content

Commit

Permalink
Added ttl
Browse files Browse the repository at this point in the history
  • Loading branch information
mcollina committed Jul 16, 2021
1 parent f933f02 commit dad0e43
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 4 deletions.
41 changes: 37 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ const kValues = require('./symbol')
const stringify = require('safe-stable-stringify')
const LRUCache = require('mnemonist/lru-cache')

const kCacheSize = Symbol('kCacheSize')
const kTTL = Symbol('kTTL')

class Cache {
constructor (opts) {
opts = opts || {}
this[kValues] = {}
this._cacheSize = opts.cacheSize || 1024
this[kCacheSize] = opts.cacheSize || 1024
this[kTTL] = opts.ttl || 0
}

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

const cacheSize = opts.cacheSize || this._cacheSize
const cacheSize = opts.cacheSize || this[kCacheSize]
const ttl = opts.ttl || this[kTTL]

const wrapper = new Wrapper(func, key, serialize, cacheSize)
const wrapper = new Wrapper(func, key, serialize, cacheSize, ttl)

this[kValues][key] = wrapper
this[key] = wrapper.add.bind(wrapper)
}
}

let _currentSecond

function currentSecond () {
if (_currentSecond !== undefined) {
return _currentSecond
}
_currentSecond = Math.floor(Date.now() / 1000)
setTimeout(_clearSecond, 1000).unref()
return _currentSecond
}

function _clearSecond () {
_currentSecond = undefined
}

class Wrapper {
constructor (func, key, serialize, cacheSize) {
constructor (func, key, serialize, cacheSize, ttl) {
this.ids = new LRUCache(cacheSize)
this.error = null
this.started = false
this.func = func
this.key = key
this.serialize = serialize
this.ttl = ttl
}

add (args) {
Expand All @@ -55,8 +76,15 @@ class Wrapper {
if (!query) {
query = new Query(id, args, this.func)
this.ids.set(key, query)
} else if (this.ttl > 0) {
if (currentSecond() - query.lastAccessed > this.ttl) {
// restart
query.promise = this.func.call(null, args)
}
}

query.touch()

return query.promise
}
}
Expand All @@ -65,6 +93,11 @@ class Query {
constructor (id, args, func) {
this.id = id
this.promise = func(args)
this.lastAccessed = null
}

touch () {
this.lastAccessed = currentSecond()
}
}

Expand Down
23 changes: 23 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

const { test } = require('tap')
const { Cache } = require('.')
const { promisify } = require('util')

const sleep = promisify(setTimeout)

const kValues = require('./symbol')

Expand Down Expand Up @@ -214,3 +217,23 @@ test('cacheSize on constructor', async (t) => {
{ k: 42 }
])
})

test('ttl', async (t) => {
t.plan(5)

const cache = new Cache({
ttl: 1 // seconds
})

cache.define('fetchSomething', async (query) => {
t.equal(query, 42)
return { k: query }
})

t.same(await cache.fetchSomething(42), { k: 42 })
t.same(await cache.fetchSomething(42), { k: 42 })

await sleep(2000)

t.same(await cache.fetchSomething(42), { k: 42 })
})

0 comments on commit dad0e43

Please sign in to comment.