@isaacs/ttlcache
Advanced tools
Comparing version 1.2.0 to 1.2.1
@@ -139,2 +139,9 @@ // Type definitions for ttlcache 1.0.0 | ||
/** | ||
* Do not call dispose() function when overwriting a key with a new value | ||
* | ||
* @default false | ||
*/ | ||
noDisposeOnSet?: boolean | ||
/** | ||
* Function that is called on items when they are dropped from the cache. | ||
@@ -153,6 +160,4 @@ * This can be handy if you want to close file descriptors or do other | ||
/** | ||
* Set to true to suppress calling the dispose() function if the entry | ||
* key is still accessible within the cache. | ||
* | ||
* @default false | ||
* Do not call dispose() function when overwriting a key with a new value | ||
* Overrides the value set in the constructor. | ||
*/ | ||
@@ -159,0 +164,0 @@ noDisposeOnSet?: boolean |
79
index.js
@@ -6,11 +6,9 @@ // A simple TTL cache with max capacity option, ms resolution, | ||
const maybeReqPerfHooks = fallback => { | ||
try { | ||
return require('perf_hooks').performance | ||
} catch (e) { | ||
return fallback | ||
} | ||
} | ||
const timeProvider = maybeReqPerfHooks(Date) | ||
const now = () => timeProvider.now() | ||
const perf = | ||
typeof performance === 'object' && | ||
performance && | ||
typeof performance.now === 'function' | ||
? performance | ||
: Date | ||
const now = () => perf.now() | ||
const isPosInt = n => n && n === Math.floor(n) && n > 0 && isFinite(n) | ||
@@ -26,2 +24,3 @@ const isPosIntOrInf = n => n === Infinity || isPosInt(n) | ||
dispose, | ||
noDisposeOnSet = false, | ||
} = {}) { | ||
@@ -46,2 +45,3 @@ // {[expirationTime]: [keys]} | ||
this.noUpdateTTL = noUpdateTTL | ||
this.noDisposeOnSet = noDisposeOnSet | ||
if (dispose !== undefined) { | ||
@@ -53,4 +53,17 @@ if (typeof dispose !== 'function') { | ||
} | ||
this.timers = new Set() | ||
} | ||
// hang onto the timer so we can clearTimeout if all items | ||
// are deleted. Deno doesn't have Timer.unref(), so it | ||
// hangs otherwise. | ||
cancelTimers() { | ||
for (const t of this.timers) { | ||
clearTimeout(t) | ||
this.timers.delete(t) | ||
} | ||
} | ||
clear() { | ||
@@ -61,2 +74,4 @@ const entries = | ||
this.expirationMap.clear() | ||
// no need for any purging now | ||
this.cancelTimers() | ||
this.expirations = Object.create(null) | ||
@@ -84,5 +99,9 @@ for (const [key, val] of entries) { | ||
if (!this.expirations[expiration]) { | ||
const t = setTimeout(() => this.purgeStale(), ttl) | ||
const t = setTimeout(() => { | ||
this.timers.delete(t) | ||
this.purgeStale() | ||
}, ttl) | ||
/* istanbul ignore else - affordance for non-node envs */ | ||
if (t.unref) t.unref() | ||
this.timers.add(t) | ||
this.expirations[expiration] = [] | ||
@@ -165,8 +184,13 @@ } | ||
const exp = this.expirations[current] | ||
if (exp && exp.length <= 1) { | ||
delete this.expirations[current] | ||
} else { | ||
this.expirations[current] = exp.filter(k => k !== key) | ||
if (exp) { | ||
if (exp.length <= 1) { | ||
delete this.expirations[current] | ||
} else { | ||
this.expirations[current] = exp.filter(k => k !== key) | ||
} | ||
} | ||
this.dispose(value, key, 'delete') | ||
if (this.size === 0) { | ||
this.cancelTimers() | ||
} | ||
return true | ||
@@ -181,19 +205,25 @@ } | ||
if (this.size - keys.length >= this.max) { | ||
delete this.expirations[exp] | ||
const entries = [] | ||
for (const key of keys) { | ||
const val = this.data.get(key) | ||
entries.push([key, this.data.get(key)]) | ||
this.data.delete(key) | ||
this.expirationMap.delete(key) | ||
} | ||
for (const [key, val] of entries) { | ||
this.dispose(val, key, 'evict') | ||
} | ||
delete this.expirations[exp] | ||
} else { | ||
const s = this.size - this.max | ||
const entries = [] | ||
for (const key of keys.splice(0, s)) { | ||
const val = this.data.get(key) | ||
entries.push([key, this.data.get(key)]) | ||
this.data.delete(key) | ||
this.expirationMap.delete(key) | ||
} | ||
for (const [key, val] of entries) { | ||
this.dispose(val, key, 'evict') | ||
} | ||
return | ||
} | ||
return | ||
} | ||
@@ -212,10 +242,17 @@ } | ||
} | ||
for (const key of this.expirations[exp]) { | ||
const val = this.data.get(key) | ||
const keys = [...this.expirations[exp]] | ||
const entries = [] | ||
delete this.expirations[exp] | ||
for (const key of keys) { | ||
entries.push([key, this.data.get(key)]) | ||
this.data.delete(key) | ||
this.expirationMap.delete(key) | ||
} | ||
for (const [key, val] of entries) { | ||
this.dispose(val, key, 'stale') | ||
} | ||
delete this.expirations[exp] | ||
} | ||
if (this.size === 0) { | ||
this.cancelTimers() | ||
} | ||
} | ||
@@ -222,0 +259,0 @@ |
{ | ||
"name": "@isaacs/ttlcache", | ||
"version": "1.2.0", | ||
"version": "1.2.1", | ||
"files": [ | ||
@@ -5,0 +5,0 @@ "index.js", |
@@ -32,3 +32,3 @@ # @isaacs/ttlcache | ||
```js | ||
const TTLCache = require('ttlcache') | ||
const TTLCache = require('@isaacs/ttlcache') | ||
const cache = new TTLCache({ max: 10000, ttl: 1000 }) | ||
@@ -48,2 +48,15 @@ | ||
## Caveat Regarding Timers and Graceful Exits | ||
On Node.js, this module uses the `Timeout.unref()` method to | ||
prevent its internal `setTimeout` calls from keeping the process | ||
running indefinitely. However, on other systems such as Deno, | ||
where the `setTimeout` method does not return an object with an | ||
`unref()` method, the process will stay open as long as any | ||
unexpired entry exists in the cache. | ||
You may delete all entries (by using `cache.clear()` or | ||
`cache.delete(key)` with every key) in order to clear the | ||
timeouts and allow the process to exit normally. | ||
## API | ||
@@ -55,3 +68,3 @@ | ||
### `new TTLCache({ ttl, max = Infinty, updateAgeOnGet = false, noUpdateTTL = false })` | ||
### `new TTLCache({ ttl, max = Infinty, updateAgeOnGet = false, noUpdateTTL = false, noDisposeOnSet = false })` | ||
@@ -58,0 +71,0 @@ Create a new `TTLCache` object. |
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
21846
417
230
0