Skip to content

Instantly share code, notes, and snippets.

@gaberogan
Last active August 9, 2024 20:04
Show Gist options
  • Save gaberogan/c4ce13ce2dac7b6fa46c4ba95da81a94 to your computer and use it in GitHub Desktop.
Save gaberogan/c4ce13ce2dac7b6fa46c4ba95da81a94 to your computer and use it in GitHub Desktop.
LazyExpireMap
/**
* A JavaScript map that lazily expires entries on read
* @param ttl TTL in seconds
* @param autoGc Optional garbage collection interval in seconds
* @example new LazyExpireMap({ ttl : 60, autoGc: 60 })
*/
export class LazyExpireMap extends Map {
constructor({ ttl, autoGc } = {}) {
super()
if (!ttl) {
throw new Error('Must provide a ttl in seconds')
}
if (autoGc) {
setInterval(() => this.gcAll(), autoGc * 1000)
}
this.ttl = ttl
}
gcAll() {
const now = Date.now()
for (const [key, { timestamp }] of super.entries()) {
if (timestamp + this.ttl * 1000 < now) {
super.delete(key)
}
}
return this
}
gc(key) {
const value = super.get(key)
const now = Date.now()
if (value && value.timestamp + this.ttl * 1000 < now) {
super.delete(key)
}
return this
}
set(key, data) {
return super.set(key, { data, timestamp: Date.now() })
}
get(key) {
this.gc(key)
return super.get(key)?.data
}
*values() {
this.gcAll()
for (const value of super.values()) {
yield value.data
}
}
has(key) {
this.gc(key)
return super.has(key)
}
keys() {
this.gcAll()
return super.keys()
}
*entries() {
this.gcAll()
for (const [key, value] of super.entries()) {
yield [key, value.data]
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment