Skip to content

Commit

Permalink
add cache.info()
Browse files Browse the repository at this point in the history
  • Loading branch information
isaacs committed Nov 22, 2023
1 parent e8feab5 commit 0d3a416
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 2 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# cringe lorg

## 10.1.0

- add `cache.info(key)` to get value as well as ttl and size
information.

## 10.0.0

- `cache.fetch()` return type is now `Promise<V | undefined>`
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,21 @@ If the key is not found, `get()` will return `undefined`.
For the usage of the `status` option, see **Status Tracking**
below.

### `info(key) => Entry | undefined`

Return an `Entry` object containing the currently cached value,
as well as ttl and size information if available. Returns
undefined if the key is not found in the cache.

Unlike `dump()` (which is designed to be portable and survive
serialization), the `start` value is always the current
timestamp, and the `ttl` is a calculated remaining time to live
(negative if expired).

Note that stale values are always returned, rather than being
pruned and treated as if they were not in the cache. If you wish
to exclude stale entries, guard against a negative `ttl` value.

### `async fetch(key, options = {}) => Promise`

The following options are supported:
Expand Down
35 changes: 33 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ class ZeroArray extends Array<number> {
}
}
export type { ZeroArray }
export type { Stack }

export type StackLike = Stack | Index[]
class Stack {
Expand Down Expand Up @@ -164,7 +165,6 @@ class Stack {
return this.heap[--this.length] as Index
}
}
export type { Stack }

/**
* Promise representing an in-progress {@link LRUCache#fetch} call
Expand Down Expand Up @@ -792,7 +792,8 @@ export namespace LRUCache {
| OptionsTTLLimit<K, V, FC>

/**
* Entry objects used by {@link LRUCache#load} and {@link LRUCache#dump}
* Entry objects used by {@link LRUCache#load} and {@link LRUCache#dump},
* and returned by {@link LRUCache#info}.
*/
export interface Entry<V> {
value: V
Expand Down Expand Up @@ -1563,6 +1564,36 @@ export class LRUCache<K extends {}, V extends {}, FC = unknown> {
return deleted
}

/**
* Get the extended info about a given entry, to get its value, size, and
* TTL info simultaneously. Like {@link LRUCache#dump}, but just for a
* single key. Always returns stale values, if their info is found in the
* cache, so be sure to check for expired TTLs if relevant.
*/
info(key: K): LRUCache.Entry<V> | undefined {
const i = this.#keyMap.get(key)
if (i === undefined) return undefined
const v = this.#valList[i]
const value: V | undefined = this.#isBackgroundFetch(v)
? v.__staleWhileFetching
: v
if (value === undefined) return undefined
const entry: LRUCache.Entry<V> = { value }
if (this.#ttls && this.#starts) {
const ttl = this.#ttls[i]
const start = this.#starts[i]
if (ttl && start) {
const remain = ttl - (perf.now() - start)
entry.ttl = remain
entry.start = Date.now()
}
}
if (this.#sizes) {
entry.size = this.#sizes[i]
}
return entry
}

/**
* Return an array of [key, {@link LRUCache.Entry}] tuples which can be
* passed to cache.load()
Expand Down
38 changes: 38 additions & 0 deletions test/info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import t from 'tap'
import { LRUCache } from '../dist/esm/index.js'

t.test('just kv', t => {
const c = new LRUCache<number, number>({ max: 2 })
c.set(1, 10)
c.set(2, 20)
c.set(3, 30)
t.equal(c.info(1), undefined)
t.strictSame(c.info(2), { value: 20 })
t.strictSame(c.info(3), { value: 30 })
t.end()
})

t.test('other info', t => {
const c = new LRUCache<number, number>({
max: 2,
ttl: 1000,
maxSize: 10000,
})
c.set(1, 10, { size: 100 })
c.set(2, 20, { size: 200 })
c.set(3, 30, { size: 300 })
t.equal(c.info(1), undefined)
t.match(c.info(2), {
value: 20,
size: 200,
ttl: Number,
start: Number,
})
t.match(c.info(3), {
value: 30,
size: 300,
ttl: Number,
start: Number,
})
t.end()
})

0 comments on commit 0d3a416

Please sign in to comment.