UNPKG

@httpx/lru

Version:

LruCache implementations with O(1) complexity

1 lines 26.6 kB
{"version":3,"sources":["../src/doubly-linked-node.ts","../src/lru-cache.ts","../src/null-lru-cache.ts","../src/null-time-lru-cache.ts","../src/time-lru-cache.ts"],"names":["DoublyLinkedNode","key","LruCache","#maxSize","#touchOnHas","#onEviction","#cache","#head","#tail","params","maxSize","touchOnHas","onEviction","size","options","hasEntry","#moveToHead","value","data","newNode","#removeTail","valueOrFn","val","node","#removeNode","current","tailKey","NullLruCache","_params","_key","_options","_value","NullTimeLruCache","_ttl","TimeLruCache","#ttl","defaultTTL","ttl"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { BaseCacheKeyTypes } from './types';\n\nexport class DoublyLinkedNode<TValue, TKey extends BaseCacheKeyTypes = string> {\n readonly key: TKey;\n prev: DoublyLinkedNode<TValue, TKey> | null = null;\n next: DoublyLinkedNode<TValue, TKey> | null = null;\n constructor(key: TKey) {\n this.key = key;\n }\n}\n","import { DoublyLinkedNode } from './doubly-linked-node';\nimport type { ILruCache } from './lru-cache.interface';\nimport type {\n BaseCacheKeyTypes,\n LruCacheHasOptions,\n SupportedCacheValues,\n} from './types';\n\ntype LruCacheEntry<TValue, TKey extends BaseCacheKeyTypes = string> = {\n value: TValue;\n node: DoublyLinkedNode<TValue, TKey>;\n};\n\nexport type LruCacheParams<\n TValue = unknown,\n TKey extends BaseCacheKeyTypes = string,\n> = {\n /**\n * The maximum number of items that the cache can hold.\n */\n maxSize: number;\n /**\n * If true, the item will be marked as recently used when calling has.\n * @default false\n */\n touchOnHas?: boolean;\n /**\n * Callback that will be called before an item is evicted from the cache.\n * Useful for side effects or for items like object URLs that need explicit cleanup (revokeObjectURL).\n */\n onEviction?: (key: TKey, value: TValue) => void;\n};\n\n/**\n * Double linked list based lru cache that supports get in O(1)\n */\nexport class LruCache<\n TValue extends SupportedCacheValues = SupportedCacheValues,\n TKey extends BaseCacheKeyTypes = string,\n> implements ILruCache<TValue, TKey>\n{\n #maxSize: number;\n #touchOnHas: boolean;\n #onEviction?: ((key: TKey, value: TValue) => void) | undefined;\n\n #cache: Map<TKey, LruCacheEntry<TValue, TKey>>;\n #head: DoublyLinkedNode<TValue, TKey> | null = null;\n #tail: DoublyLinkedNode<TValue, TKey> | null = null;\n\n /**\n * Create a new LruCache instance\n *\n * @example\n * ```typescript\n * import { LruCache } from '@httpx/lru';\n *\n * const lru = new LruCache({ maxSize: 1000 });\n * lru.set('🦄', ['cool', 'stuff']);\n * if (lru.has('🦄')) {;\n * console.log(lru.get('🦄'));\n * // ['cool', 'stuff']\n * }\n * console.log(lru.size); // 1\n * lru.delete('🦄');\n * console.log(lru.size); // 0\n * lru.clear();\n * ```\n */\n constructor(params: LruCacheParams<TValue, TKey>) {\n const { maxSize, touchOnHas = false, onEviction } = params;\n if (!Number.isSafeInteger(maxSize) || maxSize < 1) {\n throw new TypeError('Invalid maxSize');\n }\n this.#touchOnHas = touchOnHas;\n this.#onEviction = onEviction;\n this.#maxSize = maxSize;\n this.#cache = new Map();\n }\n\n get params(): ILruCache['params'] {\n return {\n maxSize: this.#maxSize,\n };\n }\n\n /**\n * Return the current number of items in the cache\n */\n get size(): number {\n return this.#cache.size;\n }\n\n clear(): number {\n const size = this.#cache.size;\n this.#cache.clear();\n this.#head = this.#tail = null;\n return size;\n }\n\n has(key: TKey, options?: LruCacheHasOptions): boolean {\n const hasEntry = this.#cache.has(key);\n if (hasEntry && (options?.touch ?? this.#touchOnHas)) {\n this.#moveToHead(this.#cache.get(key)!.node);\n }\n return hasEntry;\n }\n\n set(key: TKey, value: TValue): boolean {\n if (this.#cache.has(key)) {\n const data = this.#cache.get(key)!;\n data.value = value;\n this.#moveToHead(data.node);\n return false;\n }\n\n const newNode = new DoublyLinkedNode(key);\n const data: LruCacheEntry<TValue, TKey> = { value, node: newNode };\n\n this.#cache.set(key, data);\n this.#moveToHead(newNode);\n\n if (this.#cache.size > this.#maxSize) {\n this.#removeTail();\n }\n return true;\n }\n\n get(key: TKey): TValue | undefined {\n const data = this.#cache.get(key);\n if (data === undefined) {\n return;\n }\n this.#moveToHead(data.node);\n return data.value;\n }\n\n getOrSet<T extends TValue>(key: TKey, valueOrFn: T | (() => T)): T {\n const val = this.get(key);\n if (val === undefined) {\n const value =\n typeof valueOrFn === 'function' ? (valueOrFn as () => T)() : valueOrFn;\n this.set(key, value as unknown as TValue);\n return value;\n }\n return val as unknown as T;\n }\n\n peek(key: TKey): TValue | undefined {\n return this.#cache.get(key)?.value;\n }\n\n delete(key: TKey): boolean {\n const node = this.#cache.get(key)?.node;\n if (node === undefined) {\n return false;\n }\n this.#removeNode(node);\n return this.#cache.delete(key);\n }\n\n *[Symbol.iterator](): IterableIterator<[TKey, TValue]> {\n let current = this.#tail;\n\n while (current) {\n const data = this.#cache.get(current.key)!;\n yield [current.key, data.value];\n current = current.prev;\n }\n }\n\n #moveToHead(node: DoublyLinkedNode<TValue, TKey>): void {\n if (node === this.#head) {\n return;\n }\n this.#removeNode(node);\n node.next = this.#head;\n node.prev = null;\n if (this.#head) {\n this.#head.prev = node;\n }\n this.#head = node;\n this.#tail ??= node;\n }\n\n #removeNode(node: DoublyLinkedNode<TValue, TKey>): void {\n if (node.prev) {\n node.prev.next = node.next;\n }\n if (node.next) {\n node.next.prev = node.prev;\n }\n if (node === this.#head) {\n this.#head = node.next;\n }\n if (node === this.#tail) {\n this.#tail = node.prev;\n }\n }\n\n #removeTail(): void {\n if (this.#tail === null) {\n return;\n }\n const tailKey = this.#tail.key;\n this.#removeNode(this.#tail);\n if (this.#onEviction) {\n this.#onEviction(tailKey, this.#cache.get(tailKey)!.value);\n }\n this.#cache.delete(tailKey);\n }\n}\n","import type { LruCacheParams } from './lru-cache';\nimport type { ILruCache } from './lru-cache.interface';\nimport type {\n BaseCacheKeyTypes,\n LruCacheHasOptions,\n SupportedCacheValues,\n} from './types';\n\nexport class NullLruCache<\n TValue extends SupportedCacheValues = SupportedCacheValues,\n TKey extends BaseCacheKeyTypes = string,\n> implements ILruCache<TValue, TKey>\n{\n /**\n * Create a new NullLruCache (does cache nothing)\n *\n * @example\n * ```typescript\n * import { NullLruCache } from '@httpx/lru';\n *\n * const lru = new NullLruCache({ maxSize: 1000 });\n * ```\n */\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n constructor(_params: LruCacheParams<TValue, TKey>) {}\n\n readonly size = 0;\n readonly params = {\n maxSize: 0,\n };\n\n clear(): number {\n return 0;\n }\n\n has(_key: TKey, _options?: LruCacheHasOptions): boolean {\n return false;\n }\n\n set(_key: TKey, _value: TValue): boolean {\n return false;\n }\n\n get(_key: TKey): undefined {\n return undefined;\n }\n\n getOrSet<T extends TValue>(_key: TKey, valueOrFn: T | (() => T)): T {\n return typeof valueOrFn === 'function'\n ? (valueOrFn as () => T)()\n : valueOrFn;\n }\n\n peek(_key: TKey): undefined {\n return undefined;\n }\n\n delete(_key: TKey): boolean {\n return false;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n *[Symbol.iterator](): IterableIterator<[TKey, TValue]> {}\n}\n","import type { TimeLruCacheParams } from './time-lru-cache';\nimport type { ITimeLruCache } from './time-lru-cache.interface';\nimport type {\n BaseCacheKeyTypes,\n LruCacheHasOptions,\n Milliseconds,\n SupportedCacheValues,\n} from './types';\n\nexport class NullTimeLruCache<\n TValue extends SupportedCacheValues = SupportedCacheValues,\n TKey extends BaseCacheKeyTypes = string,\n> implements ITimeLruCache<TValue, TKey>\n{\n /**\n * Create a new NullTimeLruCache (does cache nothing)\n *\n * @example\n * ```typescript\n * import { NullTimeLruCache } from '@httpx/lru';\n *\n * const lru = new NullTimeLruCache({ maxSize: 1000 });\n * ```\n */\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n constructor(_params: TimeLruCacheParams<TValue, TKey>) {}\n\n readonly size = 0;\n readonly params = {\n maxSize: 0,\n defaultTTL: 0,\n };\n\n clear(): number {\n return 0;\n }\n\n has(_key: TKey, _options?: LruCacheHasOptions): boolean {\n return false;\n }\n\n set(_key: TKey, _value: TValue, _ttl?: Milliseconds): boolean {\n return false;\n }\n\n get(_key: TKey): undefined {\n return undefined;\n }\n\n getOrSet<T = TValue>(\n _key: TKey,\n valueOrFn: T | (() => T),\n _ttl?: Milliseconds\n ): T {\n return typeof valueOrFn === 'function'\n ? (valueOrFn as () => T)()\n : valueOrFn;\n }\n\n peek(_key: TKey): undefined {\n return undefined;\n }\n\n delete(_key: TKey): boolean {\n return false;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n *[Symbol.iterator](): IterableIterator<[TKey, TValue]> {}\n}\n","import { DoublyLinkedNode } from './doubly-linked-node';\nimport type { LruCacheParams } from './lru-cache';\nimport type { ITimeLruCache } from './time-lru-cache.interface';\nimport type {\n BaseCacheKeyTypes,\n EpochTimeInMilliseconds,\n LruCacheHasOptions,\n Milliseconds,\n SupportedCacheValues,\n} from './types';\n\ntype TimeLruCacheEntry<TValue, TKey extends BaseCacheKeyTypes = string> = {\n value: TValue;\n expiry: EpochTimeInMilliseconds;\n node: DoublyLinkedNode<TValue, TKey>;\n};\n\nexport type TimeLruCacheParams<\n TValue = unknown,\n TKey extends BaseCacheKeyTypes = string,\n> = LruCacheParams<TValue, TKey> & {\n /**\n * Default time to live for each entry in milliseconds\n */\n defaultTTL: Milliseconds;\n};\n\n/**\n * Double linked list based lru cache that supports get in O(1) and time to live for each entry\n */\nexport class TimeLruCache<\n TValue extends SupportedCacheValues = SupportedCacheValues,\n TKey extends BaseCacheKeyTypes = string,\n> implements ITimeLruCache<TValue, TKey>\n{\n #maxSize: number;\n #touchOnHas: boolean;\n\n #ttl: Milliseconds;\n\n #onEviction?: ((key: TKey, value: TValue) => void) | undefined;\n\n #cache: Map<TKey, TimeLruCacheEntry<TValue, TKey>>;\n #head: DoublyLinkedNode<TValue, TKey> | null = null;\n #tail: DoublyLinkedNode<TValue, TKey> | null = null;\n\n /**\n * Create a new LruCache instance\n *\n * @example\n * ```typescript\n * import { TimeLruCache } from '@httpx/lru';\n *\n * const THIRTY_SECONDS_IN_MILLIS = 30_000\n *\n * const lru = new TimeLruCache({ maxSize: 1000, defaultTTL: THIRTY_SECONDS_IN_MILLIS});\n * lru.set('🦄', ['cool', 'stuff'], THIRTY_SECONDS_IN_MILLIS);\n * if (lru.has('🦄')) {;\n * console.log(lru.get('🦄'));\n * // ['cool', 'stuff']\n * }\n * console.log(lru.size); // 1\n * lru.delete('🦄');\n * console.log(lru.size); // 0\n * lru.clear();\n * ```\n */\n constructor(params: TimeLruCacheParams<TValue, TKey>) {\n const { maxSize, touchOnHas = false, onEviction, defaultTTL } = params;\n if (!Number.isSafeInteger(maxSize) || maxSize < 1) {\n throw new TypeError('Invalid maxSize');\n }\n if (!Number.isSafeInteger(defaultTTL) || defaultTTL < 1) {\n throw new TypeError('Invalid ttl');\n }\n\n this.#touchOnHas = touchOnHas;\n this.#onEviction = onEviction;\n this.#maxSize = maxSize;\n this.#ttl = defaultTTL;\n this.#cache = new Map();\n }\n\n /**\n * Return the current size of the cache\n */\n get params(): ITimeLruCache['params'] {\n return {\n maxSize: this.#maxSize,\n defaultTTL: this.#ttl,\n };\n }\n\n /**\n * Return the current number of entries in the cache\n */\n get size(): number {\n return this.#cache.size;\n }\n\n clear(): number {\n const size = this.#cache.size;\n this.#cache.clear();\n this.#head = this.#tail = null;\n return size;\n }\n\n has(key: TKey, options?: LruCacheHasOptions): boolean {\n const value = this.#cache.get(key);\n const hasEntry = value !== undefined;\n const hasExpired = hasEntry && value.expiry < Date.now();\n\n if (hasExpired) {\n if (this.#onEviction) {\n this.#onEviction(key, this.#cache.get(key)!.value);\n }\n this.#removeNode(value.node);\n return false;\n }\n\n if (hasEntry && (options?.touch ?? this.#touchOnHas)) {\n this.#moveToHead(this.#cache.get(key)!.node);\n }\n return hasEntry;\n }\n\n set(key: TKey, value: TValue, ttl?: Milliseconds): boolean {\n if (this.#cache.has(key)) {\n const data = this.#cache.get(key)!;\n data.value = value;\n data.expiry = Date.now() + (ttl ?? this.#ttl);\n this.#moveToHead(data.node);\n return false;\n }\n\n const newNode = new DoublyLinkedNode(key);\n const data: TimeLruCacheEntry<TValue, TKey> = {\n value,\n expiry: Date.now() + (ttl ?? this.#ttl),\n node: newNode,\n };\n\n this.#cache.set(key, data);\n this.#moveToHead(newNode);\n\n if (this.#cache.size > this.#maxSize) {\n this.#removeTail();\n }\n return true;\n }\n\n get(key: TKey): TValue | undefined {\n const data = this.#cache.get(key);\n if (data === undefined) {\n return;\n }\n if (data.expiry < Date.now()) {\n if (this.#onEviction) {\n this.#onEviction(key, data.value);\n }\n this.#removeNode(data.node);\n return;\n }\n\n this.#moveToHead(data.node);\n\n return data.value;\n }\n\n getOrSet<T extends TValue>(\n key: TKey,\n valueOrFn: T | (() => T),\n ttl?: Milliseconds\n ): T {\n const val = this.get(key);\n if (val === undefined) {\n const value =\n typeof valueOrFn === 'function' ? (valueOrFn as () => T)() : valueOrFn;\n this.set(key, value as unknown as TValue, ttl);\n return value;\n }\n return val as unknown as T;\n }\n\n peek(key: TKey): TValue | undefined {\n const val = this.#cache.get(key);\n if (val === undefined) {\n return;\n }\n return val.expiry < Date.now() ? undefined : val.value;\n }\n\n delete(key: TKey): boolean {\n const node = this.#cache.get(key)?.node;\n if (node === undefined) {\n return false;\n }\n this.#removeNode(node);\n return this.#cache.delete(key);\n }\n\n /**\n * Iterate over the cache from the least recently used to the most recently used.\n *\n * ```typescript\n * const lru = new LruCache({ maxSize: 2 });\n * lru.set('key1', 'value1');\n * lru.set('key2', 'value2');\n * lru.set('key3', 'value3');\n * // trigger a get to move key2 to the head\n * lru.get('key2');\n * const results = [];\n * // iterate over the cache entries\n * for (const [key, value] of lru) {\n * results.push([key, value]);\n * }\n * expect(results).toStrictEqual([\n * ['key3', 'value3'], // Least recently used\n * ['key2', 'value2'], // Most recently used\n * ]);\n * ```\n */\n *[Symbol.iterator](): IterableIterator<[TKey, TValue]> {\n let current = this.#tail;\n\n while (current) {\n const data = this.#cache.get(current.key)!;\n yield [current.key, data.value];\n current = current.prev;\n }\n }\n\n #moveToHead(node: DoublyLinkedNode<TValue, TKey>): void {\n if (node === this.#head) {\n return;\n }\n this.#removeNode(node);\n node.next = this.#head;\n node.prev = null;\n if (this.#head) {\n this.#head.prev = node;\n }\n this.#head = node;\n this.#tail ??= node;\n }\n\n #removeNode(node: DoublyLinkedNode<TValue, TKey>): void {\n if (node.prev) {\n node.prev.next = node.next;\n }\n if (node.next) {\n node.next.prev = node.prev;\n }\n if (node === this.#head) {\n this.#head = node.next;\n }\n if (node === this.#tail) {\n this.#tail = node.prev;\n }\n }\n\n #removeTail(): void {\n if (this.#tail === null) {\n return;\n }\n const tailKey = this.#tail.key;\n this.#removeNode(this.#tail);\n if (this.#onEviction) {\n this.#onEviction(tailKey, this.#cache.get(tailKey)!.value);\n }\n this.#cache.delete(tailKey);\n }\n}\n"]}