@loipv/nestjs-cache 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +81 -0
- package/LICENSE +21 -0
- package/README.md +118 -2
- package/dist/index.cjs +5777 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1861 -0
- package/dist/index.d.ts +1861 -0
- package/dist/index.js +5737 -0
- package/dist/index.js.map +1 -0
- package/package.json +131 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/core/key-builder.ts","../src/module/tokens.ts","../src/decorators/metadata.ts","../src/decorators/method-wrapper.ts","../src/core/envelope.ts","../src/core/strategies/classify.ts","../src/core/strategies/fixed.strategy.ts","../src/core/strategies/sliding.strategy.ts","../src/core/strategies/swr.strategy.ts","../src/core/strategies/expiry-strategy.ts","../src/decorators/inject-engine.ts","../src/decorators/cacheable.ts","../src/decorators/cache-put.ts","../src/core/engine-tags.ts","../src/decorators/cache-evict.ts","../src/http/http-cache.decorator.ts","../src/http/http-cache.interceptor.ts","../src/http/http-cache-key.ts","../src/serializers/json.serializer.ts","../src/serializers/compressed.serializer.ts","../src/core/events.ts","../src/stores/memory.store.ts","../src/resilience/circuit-breaker.store.ts","../src/health/cache-health.indicator.ts","../src/module/cache.module.ts","../src/observability/cache-tracing.ts","../src/core/engine-envelope.ts","../src/core/engine-keys.ts","../src/core/engine-io.ts","../src/core/engine-batch.ts","../src/core/lock-runner.ts","../src/core/single-flight.ts","../src/core/engine-load.ts","../src/core/version-tokens.ts","../src/core/namespace-versions.ts","../src/core/cache-engine.ts","../src/core/cache.service.ts","../src/module/cache.explorer.ts","../src/module/cache.lifecycle.ts","../src/module/cache.logger.ts","../src/module/cache.options.ts","../src/stores/redis-lock.ts","../src/stores/key-slot.ts","../src/stores/cluster-ops.ts","../src/stores/redis-client.adapter.ts","../src/stores/subscriber-support.ts","../src/stores/ioredis.adapter.ts","../src/stores/redis-invalidation-bus.ts","../src/stores/redis.store.ts","../src/stores/node-redis.adapter.ts","../src/stores/tiered.store.ts","../src/observability/prometheus.module.ts","../src/observability/prometheus.types.ts","../src/observability/metrics.collector.ts","../src/observability/tracing.module.ts"],"sourcesContent":["export { CacheConfigError } from './errors.js';\nexport { Cacheable } from './decorators/cacheable.js';\nexport { CachePut } from './decorators/cache-put.js';\nexport { CacheEvict } from './decorators/cache-evict.js';\nexport { HttpCache } from './http/http-cache.decorator.js';\nexport type {\n HttpCacheOptions,\n HttpCacheRequest,\n HttpCacheTags,\n} from './http/http-cache.decorator.js';\nexport { HttpCacheInterceptor } from './http/http-cache.interceptor.js';\nexport type {\n CacheableOptions,\n CacheEvictOptions,\n CachePutOptions,\n KeySpec,\n LoadStrategyOptions,\n StrategyOptions,\n TagSpec,\n} from './decorators/options.js';\nexport type { CacheEnvelope } from './core/envelope.js';\nexport type { Serializer } from './serializers/json.serializer.js';\nexport { jsonSerializer } from './serializers/json.serializer.js';\nexport { compressedSerializer } from './serializers/compressed.serializer.js';\nexport type { CompressedSerializerOptions } from './serializers/compressed.serializer.js';\nexport { CacheEvents } from './core/events.js';\nexport type {\n BreakerState,\n CacheEventMap,\n CacheEventSink,\n CacheLogLevel,\n CacheOperation,\n} from './core/events.js';\nexport type {\n CacheStore,\n InvalidationBus,\n InvalidationMessage,\n LockHandle,\n LockProvider,\n} from './stores/cache-store.interface.js';\nexport { MemoryStore, memoryStore } from './stores/memory.store.js';\nexport type { MemoryStoreOptions } from './stores/memory.store.js';\nexport type {\n CacheDefaults,\n CacheLockDefaults,\n CacheModuleAsyncOptions,\n CacheModuleOptions,\n} from './module/cache.options.js';\nexport { CacheHealthIndicator } from './health/cache-health.indicator.js';\nexport type { CacheHealthResult } from './health/cache-health.indicator.js';\nexport { CacheModule } from './module/cache.module.js';\nexport { CacheService } from './core/cache.service.js';\nexport type {\n GetOrSetManyOptions,\n GetOrSetOptions,\n KeyOptions,\n WriteManyOptions,\n WriteOptions,\n} from './core/cache.service.js';\nexport { RedisStore, redisStore } from './stores/redis.store.js';\nexport { redisInvalidationBus } from './stores/redis-invalidation-bus.js';\nexport type { RedisStoreOptions } from './stores/redis.store.js';\nexport type { RedisInvalidationBusOptions } from './stores/redis-invalidation-bus.js';\nexport { ioredisAdapter } from './stores/ioredis.adapter.js';\nexport type { IoredisClusterLike, IoredisLike } from './stores/ioredis.adapter.js';\nexport { nodeRedisAdapter } from './stores/node-redis.adapter.js';\nexport type {\n NodeRedisClusterLike,\n NodeRedisLike,\n NodeRedisSentinelLike,\n} from './stores/node-redis.adapter.js';\nexport type { RedisClientAdapter, RedisSubscriberAdapter } from './stores/redis-client.adapter.js';\nexport { TieredStore, tieredStore } from './stores/tiered.store.js';\nexport type { TieredStoreOptions } from './stores/tiered.store.js';\nexport {\n circuitBreakerStore,\n CircuitBreakerStore,\n CircuitOpenError,\n} from './resilience/circuit-breaker.store.js';\nexport type { CircuitBreakerStoreOptions } from './resilience/circuit-breaker.store.js';\nexport type {\n CachePrometheusAsyncOptions,\n CachePrometheusOptions,\n PrometheusClientLike,\n RegistryLike,\n} from './observability/prometheus.types.js';\nexport { CachePrometheusModule } from './observability/prometheus.module.js';\nexport type {\n CacheTracingAsyncOptions,\n CacheTracingOptions,\n SpanAttributeValue,\n SpanContextLike,\n SpanLike,\n SpanOptionsLike,\n TracerLike,\n} from './observability/tracing.types.js';\nexport { CacheTracingModule } from './observability/tracing.module.js';\n","/**\n * Thrown for invalid configuration: bad decorator or module options, an unknown store name, or\n * an invalid per-call argument.\n */\nexport class CacheConfigError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CacheConfigError';\n }\n\n /**\n * The ESM and CommonJS builds each define this class, so `instanceof` also accepts any `Error`\n * named `CacheConfigError`. Subclasses keep the normal prototype check.\n */\n static override [Symbol.hasInstance](value: unknown): boolean {\n if (Function.prototype[Symbol.hasInstance].call(this, value)) return true;\n return this === CacheConfigError && value instanceof Error && value.name === 'CacheConfigError';\n }\n}\n","import { createHash } from 'node:crypto';\nimport { CacheConfigError } from '../errors.js';\n\ntype Segment = string | { readonly index: number; readonly path: readonly string[] };\n\nconst PLACEHOLDER = /\\{(\\d+)((?:\\.[A-Za-z_$][A-Za-z0-9_$]*)*)\\}/y;\n\nexport function stableStringify(value: unknown): string {\n return stringifyValue(value, new Set());\n}\n\n/** `ancestors` holds the objects on the path from the root: one seen again there is a cycle. */\nfunction stringifyValue(value: unknown, ancestors: Set<object>): string {\n switch (typeof value) {\n case 'undefined':\n return 'undefined';\n case 'string':\n return JSON.stringify(value);\n case 'number':\n return Number.isFinite(value) ? JSON.stringify(value) : String(value);\n case 'boolean':\n return String(value);\n case 'bigint':\n return `${value.toString()}n`;\n case 'symbol':\n throw new TypeError('Cannot build a cache key from a symbol');\n case 'function':\n throw new TypeError('Cannot build a cache key from a function');\n default:\n break;\n }\n if (value === null) return 'null';\n const obj = value as object;\n if (\n obj instanceof Map ||\n obj instanceof Set ||\n obj instanceof WeakMap ||\n obj instanceof WeakSet\n ) {\n throw new TypeError(`Cannot build a cache key from a ${obj.constructor.name}`);\n }\n if (ancestors.has(obj)) {\n throw new TypeError('Cannot build a cache key from a circular structure');\n }\n ancestors.add(obj);\n try {\n const toJSON = (obj as { toJSON?: unknown }).toJSON;\n if (typeof toJSON === 'function') {\n return stringifyValue((toJSON as () => unknown).call(obj), ancestors);\n }\n if (Array.isArray(obj)) {\n const items: string[] = [];\n for (let i = 0; i < obj.length; i++) {\n items.push(stringifyValue(obj[i], ancestors));\n }\n return `[${items.join(',')}]`;\n }\n const record = obj as Record<string, unknown>;\n const parts: string[] = [];\n for (const key of Object.keys(record).sort()) {\n const v = record[key];\n if (v === undefined) continue;\n parts.push(`${JSON.stringify(key)}:${stringifyValue(v, ancestors)}`);\n }\n return `{${parts.join(',')}}`;\n } finally {\n ancestors.delete(obj);\n }\n}\n\nfunction parseTemplate(template: string): Segment[] {\n const segments: Segment[] = [];\n let literal = '';\n let i = 0;\n while (i < template.length) {\n const ch = template[i] as string;\n if (ch === '{') {\n PLACEHOLDER.lastIndex = i;\n const match = PLACEHOLDER.exec(template);\n if (match === null) {\n throw new CacheConfigError(\n `Invalid cache key template \"${template}\": malformed placeholder at index ${String(i)}`,\n );\n }\n if (literal !== '') {\n segments.push(literal);\n literal = '';\n }\n const rest = match[2] ?? '';\n segments.push({\n index: Number(match[1]),\n path: rest === '' ? [] : rest.slice(1).split('.'),\n });\n i += match[0].length;\n } else if (ch === '}') {\n throw new CacheConfigError(\n `Invalid cache key template \"${template}\": unmatched \"}\" at index ${String(i)}`,\n );\n } else {\n literal += ch;\n i++;\n }\n }\n if (literal !== '') segments.push(literal);\n return segments;\n}\n\n/** Percent-encodes `%` first, then `:`, so a rendered argument cannot add a key separator. */\nexport function escapeKeyArg(value: string): string {\n return value.replaceAll('%', '%25').replaceAll(':', '%3A');\n}\n\nfunction renderValue(value: unknown, escape: boolean): string {\n if (value === null) return 'null';\n switch (typeof value) {\n case 'string':\n return escape ? escapeKeyArg(value) : value;\n case 'number':\n return escape ? escapeKeyArg(String(value)) : String(value);\n case 'boolean':\n case 'bigint':\n case 'undefined':\n return String(value);\n default:\n return stableStringify(value);\n }\n}\n\nfunction resolve(args: readonly unknown[], index: number, path: readonly string[]): unknown {\n let current: unknown = args[index];\n for (const prop of path) {\n if (current === null || current === undefined) return undefined;\n current = (Object(current) as Record<string, unknown>)[prop];\n }\n return current;\n}\n\nexport function compileTemplate(\n template: string,\n): (args: readonly unknown[], escape?: boolean) => string {\n const segments = parseTemplate(template);\n return (args, escape = false) => {\n let out = '';\n for (const segment of segments) {\n out +=\n typeof segment === 'string'\n ? segment\n : renderValue(resolve(args, segment.index, segment.path), escape);\n }\n return out;\n };\n}\n\nexport function defaultKey(\n className: string,\n methodName: string,\n args: readonly unknown[],\n): string {\n const base = `${className}.${methodName}`;\n if (args.length === 0) return base;\n const hash = createHash('sha1').update(stableStringify(args)).digest('hex').slice(0, 16);\n return `${base}:${hash}`;\n}\n\n/**\n * An empty key is a key error: `fullKey(prefix, namespace, '')` collapses to `prefix:namespace`,\n * which collides with a namespace-less key and is not covered by `clear(namespace)`.\n */\nexport function isEmptyKey(key: string): boolean {\n return key === '';\n}\n\nexport function emptyKeyError(): TypeError {\n return new TypeError('Cache key must not be empty');\n}\n\n/**\n * Without a namespace a key starting with `__` is a key error: `fullKey` would place it in the\n * reserved `__` space of `__version__`, `__tag__` and `__lock__`, where a caller-controlled key\n * (for example an untrusted `{0}` template) could read or delete the library's own entries.\n */\nexport function isReservedKey(namespace: string | undefined, key: string): boolean {\n // `fullKey` drops an empty namespace, so '' is no namespace.\n return (namespace === undefined || namespace === '') && key.startsWith('__');\n}\n\nexport function reservedKeyError(): TypeError {\n return new TypeError('Invalid key: keys starting with \"__\" are reserved; use a namespace');\n}\n\n/** The key error for `key` in `namespace`, or `undefined` when it is valid. */\nexport function keyErrorOf(namespace: string | undefined, key: string): TypeError | undefined {\n if (isEmptyKey(key)) return emptyKeyError();\n if (isReservedKey(namespace, key)) return reservedKeyError();\n return undefined;\n}\n\nexport function fullKey(\n prefix: string | undefined,\n namespace: string | undefined,\n key: string,\n): string {\n return [prefix, namespace, key].filter((p): p is string => p !== undefined && p !== '').join(':');\n}\n\n/** `<prefix>:__lock__:<namespace>:<key>`; the `__` namespace space is reserved, so it cannot collide with data. */\nexport function lockKey(\n prefix: string | undefined,\n namespace: string | undefined,\n key: string,\n): string {\n return fullKey(prefix, '__lock__', fullKey(undefined, namespace, key));\n}\n\nexport function isReservedNamespace(ns: string): boolean {\n return ns.startsWith('__');\n}\n\nexport function namespacePrefix(prefix: string | undefined, namespace: string): string {\n return `${fullKey(prefix, namespace, '')}:`;\n}\n","export const CACHE_ENGINE: unique symbol = Symbol.for('@loipv/nestjs-cache:engine');\nexport const CACHE_OPTIONS: unique symbol = Symbol.for('@loipv/nestjs-cache:options');\nexport const CACHE_ENGINE_PROPERTY: unique symbol = Symbol.for(\n '@loipv/nestjs-cache:engine-property',\n);\nexport const CACHE_METADATA: unique symbol = Symbol.for('@loipv/nestjs-cache:metadata');\n/** @internal The module's `CacheLogger`; exported by `CacheModule` for the metrics module. */\nexport const CACHE_LOGGER: unique symbol = Symbol.for('@loipv/nestjs-cache:logger');\nexport const CACHE_PROMETHEUS_OPTIONS: unique symbol = Symbol.for(\n '@loipv/nestjs-cache:prometheus-options',\n);\n/** @internal The `CacheTracingModule` options; `CacheTracing.use` validates them. */\nexport const CACHE_TRACING_OPTIONS: unique symbol = Symbol.for(\n '@loipv/nestjs-cache:tracing-options',\n);\n/** @internal The `CacheTracingModule` provider that registers the tracer with `CacheTracing`. */\nexport const CACHE_TRACING_REGISTRATION: unique symbol = Symbol.for(\n '@loipv/nestjs-cache:tracing-registration',\n);\n","import { CacheConfigError } from '../errors.js';\nimport { isReservedNamespace } from '../core/key-builder.js';\nimport { CACHE_METADATA } from '../module/tokens.js';\n\nexport interface CacheMetadataEntry {\n kind: 'cacheable' | 'put' | 'evict' | 'http';\n method: string | symbol;\n store: string;\n lock: boolean | undefined;\n}\n\ntype Holder = { [CACHE_METADATA]?: CacheMetadataEntry[] };\n\nexport function getCacheMetadata(ctor: object): readonly CacheMetadataEntry[] {\n return (ctor as Holder)[CACHE_METADATA] ?? [];\n}\n\n/** The `method` of the entry a class-level `@HttpCache` registers. Internal; messages name the class alone. */\nexport const CLASS_LEVEL = '*';\n\n/** `Class.method`, or `Class` for a class-level entry. */\nexport function memberName(className: string, method: string | symbol): string {\n return method === CLASS_LEVEL ? className : `${className}.${String(method)}`;\n}\n\nexport function describeMethod(target: object, method: string | symbol): string {\n return memberName((target as { constructor: { name: string } }).constructor.name, method);\n}\n\nexport function addCacheMetadata(target: object, entry: CacheMetadataEntry): void {\n const ctor = (target as { constructor: Holder }).constructor;\n const own = Object.prototype.hasOwnProperty.call(ctor, CACHE_METADATA);\n const current = own ? (ctor[CACHE_METADATA] ?? []) : [...getCacheMetadata(ctor)];\n const clash = current.find(\n (e) =>\n e.method === entry.method &&\n ((e.kind === 'cacheable' && entry.kind === 'put') ||\n (e.kind === 'put' && entry.kind === 'cacheable')),\n );\n if (clash) {\n throw new CacheConfigError(\n `${describeMethod(target, entry.method)}: @Cacheable and @CachePut cannot be combined on one method`,\n );\n }\n current.push(entry);\n ctor[CACHE_METADATA] = current;\n}\n\nexport function assertPositiveFinite(\n target: object,\n method: string | symbol,\n field: string,\n value: number | undefined,\n): void {\n if (value === undefined) return;\n if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {\n throw new CacheConfigError(\n `${describeMethod(target, method)}: ${field} must be a finite number > 0, got ${String(value)}`,\n );\n }\n}\n\nexport function assertBoolean(\n target: object,\n method: string | symbol,\n field: string,\n value: boolean | undefined,\n): void {\n if (value === undefined || typeof value === 'boolean') return;\n throw new CacheConfigError(\n `${describeMethod(target, method)}: ${field} must be a boolean, got ${String(value)}`,\n );\n}\n\n/** A callback option (`condition`, `unless`) must be a function when it is set. */\nexport function assertFunction(\n target: object,\n method: string | symbol,\n field: string,\n value: unknown,\n): void {\n if (value === undefined || typeof value === 'function') return;\n throw new CacheConfigError(\n `${describeMethod(target, method)}: ${field} must be a function, got ${typeof value}`,\n );\n}\n\nexport function assertNamespace(\n target: object,\n method: string | symbol,\n namespace: string | undefined,\n): void {\n if (typeof namespace === 'string' && isReservedNamespace(namespace)) {\n throw new CacheConfigError(\n `${describeMethod(target, method)}: namespace \"${namespace}\" is reserved (names starting with \"__\")`,\n );\n }\n}\n\n/**\n * Validates `staleTtl`/`maxTtl`/`softTimeout` and the `maxTtl >= ttl` relation at definition\n * time. `noSoftTimeout` names a decorator that does not load (`@CachePut`): any defined\n * `softTimeout` is then rejected. Otherwise `softTimeout` needs `strategy: 'swr'`.\n */\nexport function assertStrategyTtls(\n target: object,\n method: string | symbol,\n options:\n | { strategy?: string; ttl?: number; staleTtl?: number; maxTtl?: number; softTimeout?: number }\n | undefined,\n noSoftTimeout?: string,\n): void {\n if (noSoftTimeout !== undefined && options?.softTimeout !== undefined) {\n throw new CacheConfigError(\n `${describeMethod(target, method)}: ${noSoftTimeout} does not support softTimeout`,\n );\n }\n assertPositiveFinite(target, method, 'staleTtl', options?.staleTtl);\n assertPositiveFinite(target, method, 'maxTtl', options?.maxTtl);\n assertPositiveFinite(target, method, 'softTimeout', options?.softTimeout);\n if (options?.softTimeout !== undefined && options.strategy !== 'swr') {\n throw new CacheConfigError(\n `${describeMethod(target, method)}: softTimeout needs strategy 'swr', got '${options.strategy ?? 'fixed'}'`,\n );\n }\n const { ttl, maxTtl } = options ?? {};\n if (ttl !== undefined && maxTtl !== undefined && maxTtl < ttl) {\n throw new CacheConfigError(\n `${describeMethod(target, method)}: maxTtl (${String(maxTtl)}) must be >= ttl (${String(ttl)})`,\n );\n }\n}\n\n/** True when `tags` is an array with a string that contains a brace, i.e. looks like a template. */\nexport function hasBraceTag(tags: unknown): boolean {\n return Array.isArray(tags) && tags.some((t) => typeof t === 'string' && /[{}]/.test(t));\n}\n\n/** `tags` must be an array of non-empty strings or a function (spec 2.5). */\nexport function assertTags(target: object, method: string | symbol, tags: unknown): void {\n if (tags === undefined || typeof tags === 'function') return;\n if (Array.isArray(tags) && tags.every((tag) => typeof tag === 'string' && tag !== '')) return;\n throw new CacheConfigError(\n `${describeMethod(target, method)}: tags must be an array of non-empty strings or a function`,\n );\n}\n","import 'reflect-metadata';\nimport { Logger } from '@nestjs/common';\nimport type { CacheEngine, PutOptions } from '../core/cache-engine.js';\nimport type { TagOption } from '../core/engine-tags.js';\nimport { compileTemplate, defaultKey, emptyKeyError, isEmptyKey } from '../core/key-builder.js';\nimport {\n createStrategy,\n strategyOptionsOf,\n type ExpiryStrategy,\n} from '../core/strategies/expiry-strategy.js';\nimport { CacheConfigError } from '../errors.js';\nimport { engineOf, injectEngine } from './inject-engine.js';\nimport {\n addCacheMetadata,\n assertTags,\n describeMethod,\n type CacheMetadataEntry,\n} from './metadata.js';\nimport type { KeySpec, LoadStrategyOptions } from './options.js';\n\nexport interface MethodCall {\n args: unknown[];\n /** Runs the next layer down (the original method, or the decorator applied below). */\n invoke: () => Promise<unknown>;\n className: string;\n methodName: string;\n /** The engine's `escapeKeyArgs`: template keys percent-encode `%` and `:` in arguments. */\n escapeKeyArgs: boolean;\n}\n\ntype AnyMethod = (this: unknown, ...args: unknown[]) => unknown;\n\ninterface WritePolicy {\n ttl?: number | undefined;\n cacheNull?: boolean | undefined;\n nullTtl?: number | undefined;\n unless?: ((result: never) => boolean) | undefined;\n}\n\nconst logger = new Logger('CacheModule');\nconst warned = new Set<string>();\n\nfunction isEngine(value: unknown): value is CacheEngine {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { getOrSet?: unknown }).getOrSet === 'function'\n );\n}\n\n/** Runs `run` and always yields a Promise; a synchronous throw becomes a rejection. */\nfunction settle(run: () => unknown): Promise<unknown> {\n return new Promise((resolve) => {\n resolve(run());\n });\n}\n\nfunction warnOnce(className: string, methodName: string): void {\n const id = `${className}.${methodName}`;\n if (warned.has(id)) return;\n warned.add(id);\n logger.warn(`${id} was called on an instance not created by Nest; caching is skipped.`);\n}\n\n/**\n * Rejects a static method. Decorators call it before validating their options, so a static\n * method is reported as such rather than under the misleading name `Function.method`.\n */\nexport function assertInstanceMethod(target: object, propertyKey: string | symbol): void {\n if (typeof target === 'function') {\n throw new CacheConfigError(\n `${(target as { name: string }).name}.${String(propertyKey)}: cache decorators cannot be used on static methods`,\n );\n }\n}\n\n/** Engine write options from decorator options, carrying only the fields that are defined. */\nexport function putOptionsOf(\n options: (LoadStrategyOptions & WritePolicy) | undefined,\n): PutOptions<unknown> {\n if (options === undefined) return {};\n const put: PutOptions<unknown> = strategyOptionsOf(options);\n if (options.ttl !== undefined) put.ttl = options.ttl;\n if (options.cacheNull !== undefined) put.cacheNull = options.cacheNull;\n if (options.nullTtl !== undefined) put.nullTtl = options.nullTtl;\n if (options.unless !== undefined) put.unless = options.unless as (result: unknown) => boolean;\n return put;\n}\n\n/**\n * Builds the strategy of fixed decorator options once, at decoration time. Options that\n * `createStrategy` rejects yield `undefined`, so the engine still rejects each call with its\n * usual message, as before.\n */\nexport function presetStrategy(options: LoadStrategyOptions): ExpiryStrategy | undefined {\n try {\n return createStrategy(options);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Records the cache metadata, registers engine injection on the prototype and\n * replaces the method with a wrapper that routes calls through `handler`.\n * Stacked decorators each wrap the function produced by the one below.\n */\nexport function wrapMethod(\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n entry: CacheMetadataEntry,\n handler: (engine: CacheEngine, call: MethodCall) => Promise<unknown>,\n): void {\n // Cheap guard for callers that skip their own check; each decorator also asserts first so\n // option validation never masks the static-method message.\n assertInstanceMethod(target, propertyKey);\n const original: unknown = descriptor.value;\n if (typeof original !== 'function') {\n throw new CacheConfigError(\n `${describeMethod(target, propertyKey)}: decorator requires a method`,\n );\n }\n const next = original as AnyMethod;\n addCacheMetadata(target, entry);\n injectEngine(target);\n const className = (target as { constructor: { name: string } }).constructor.name;\n const methodName = String(propertyKey);\n\n const wrapper = function (this: unknown, ...args: unknown[]): Promise<unknown> {\n const invoke = (): Promise<unknown> => settle(() => next.apply(this, args));\n const engine = engineOf(this);\n if (!isEngine(engine)) {\n warnOnce(className, methodName);\n return invoke();\n }\n return settle(() =>\n handler(engine, {\n args,\n invoke,\n className,\n methodName,\n escapeKeyArgs: engine.escapeKeyArgs,\n }),\n );\n };\n\n for (const key of Reflect.getMetadataKeys(next) as unknown[]) {\n Reflect.defineMetadata(key, Reflect.getMetadata(key, next), wrapper);\n }\n Object.defineProperty(wrapper, 'name', { value: next.name });\n descriptor.value = wrapper;\n}\n\n/**\n * Compiles a key spec at declaration time; a malformed template throws here. The built\n * function throws for a key that cannot be built and, unless `allowEmpty` is set, for one\n * that renders empty. `@CacheEvict` allows it: the engine drops empty or reserved keys from a\n * delete.\n */\nexport function compileKey(\n spec: KeySpec<never[]> | undefined,\n allowEmpty = false,\n): (call: MethodCall) => string {\n const build = compileRawKey(spec);\n if (allowEmpty) return build;\n return (call) => {\n const key = build(call);\n if (isEmptyKey(key)) throw emptyKeyError();\n return key;\n };\n}\n\nfunction compileRawKey(spec: KeySpec<never[]> | undefined): (call: MethodCall) => string {\n if (spec === undefined) {\n return (call) => defaultKey(call.className, call.methodName, call.args);\n }\n if (typeof spec === 'string') {\n const render = compileTemplate(spec);\n return (call) => render(call.args, call.escapeKeyArgs);\n }\n const build = spec as (...args: unknown[]) => unknown;\n return (call) => {\n const key = build(...call.args);\n if (typeof key !== 'string') {\n throw new TypeError(`Key callback returned ${typeof key}, expected a string`);\n }\n return key;\n };\n}\n\n/** Runs a declaration-time compile with the declaring class and method named in its error. */\nfunction compileAt<T>(target: object, propertyKey: string | symbol, compile: () => T): T {\n try {\n return compile();\n } catch (error) {\n if (error instanceof CacheConfigError) {\n throw new CacheConfigError(`${describeMethod(target, propertyKey)}: ${error.message}`);\n }\n throw error;\n }\n}\n\n/** `compileKey` with the declaring class and method named in a template error. */\nexport function compileKeyAt(\n target: object,\n propertyKey: string | symbol,\n spec: KeySpec<never[]> | undefined,\n allowEmpty = false,\n): (call: MethodCall) => string {\n return compileAt(target, propertyKey, () => compileKey(spec, allowEmpty));\n}\n\n/**\n * Validates a tags array at declaration time (spec 2.5) and compiles its templates, naming the\n * declaring method in an error. The built function renders every template against the call's\n * arguments (escaped as template keys are, with `escapeKeyArgs`); it throws for an argument that\n * cannot be rendered.\n */\nfunction compileTagTemplates(\n target: object,\n propertyKey: string | symbol,\n tags: readonly string[],\n): (call: MethodCall) => string[] {\n const renders = compileAt(target, propertyKey, () => tags.map((tag) => compileTemplate(tag)));\n return (call) => renders.map((render) => render(call.args, call.escapeKeyArgs));\n}\n\n/**\n * Compiles the `tags` of `@Cacheable` or `@CachePut` (spec 2.1) into the engine tags of a call\n * (D2): a template array becomes the array rendered from the call's arguments, so its tokens are\n * taken before the method runs; a callback `(result, ...args)` becomes a function of the value.\n * `undefined` when no tag is declared (an empty array included). The built function never\n * throws: an argument a template cannot render gives a function that throws, so the write is\n * skipped and reported as a `tag` error, as for a callback that throws.\n */\nexport function compileTags(\n target: object,\n propertyKey: string | symbol,\n spec: unknown,\n): ((call: MethodCall) => TagOption<unknown>) | undefined {\n assertTags(target, propertyKey, spec);\n if (spec === undefined) return undefined;\n if (typeof spec === 'function') {\n const callback = spec as (result: unknown, ...args: unknown[]) => readonly string[];\n return (call) => (value) => callback(value, ...call.args);\n }\n const tags = spec as readonly string[];\n if (tags.length === 0) return undefined;\n const render = compileTagTemplates(target, propertyKey, tags);\n return (call) => {\n try {\n return render(call);\n } catch (error) {\n return () => {\n throw error;\n };\n }\n };\n}\n\n/**\n * Compiles the `tags` of `@CacheEvict` (spec 2.2): a template array rendered from the call's\n * arguments, or a callback of the arguments, whose result is returned unchecked. An empty array\n * is rejected, as an empty key list is.\n */\nexport function compileEvictTags(\n target: object,\n propertyKey: string | symbol,\n spec: unknown,\n): ((call: MethodCall) => unknown) | undefined {\n assertTags(target, propertyKey, spec);\n if (spec === undefined) return undefined;\n if (typeof spec === 'function') {\n const callback = spec as (...args: unknown[]) => unknown;\n return (call) => callback(...call.args);\n }\n const tags = spec as readonly string[];\n if (tags.length === 0) {\n throw new CacheConfigError(\n `${describeMethod(target, propertyKey)}: tags must not be an empty array`,\n );\n }\n return compileTagTemplates(target, propertyKey, tags);\n}\n","/** What the engine stores per entry; a `Serializer` turns it into the stored string. */\nexport interface CacheEnvelope {\n /** The envelope format version. */\n v: 1;\n /** The cached value; `null` when `nil` is set. */\n value: unknown;\n /** When the entry was written, in ms since the epoch. */\n storedAt: number;\n /** When the entry expires (ms since the epoch); under `swr`, when its stale window ends. */\n expiresAt?: number;\n /** `swr` only: when the entry turns stale (ms since the epoch); it is fresh before. */\n staleAt?: number;\n /** Set on a stored empty value (`cacheNull`): which one it was, as `value` is `null`. */\n nil?: 'null' | 'undefined';\n /** The tag versions the entry was written with, tag to token; absent on an untagged entry. */\n tags?: Readonly<Record<string, string>>;\n}\n\nexport function wrap(value: unknown, storedAt: number, ttlMs: number): CacheEnvelope {\n const expiresAt = storedAt + ttlMs;\n if (value === null || value === undefined) {\n return { v: 1, value: null, storedAt, expiresAt, nil: value === null ? 'null' : 'undefined' };\n }\n return { v: 1, value, storedAt, expiresAt };\n}\n\nexport function unwrap(envelope: CacheEnvelope): unknown {\n if (envelope.nil === 'undefined') return undefined;\n if (envelope.nil === 'null') return null;\n return envelope.value;\n}\n\n/**\n * Whether `value` looks like an envelope this library wrote, of any version: a plain object with\n * an own `v`. Used with `isNewerEnvelope` to decide whether an unreadable entry may be deleted.\n */\nexport function hasOwnVersion(value: unknown): boolean {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n Object.prototype.hasOwnProperty.call(value, 'v')\n );\n}\n\n/**\n * Whether `candidate` is an envelope written by a newer version of this library: an own `v` that\n * is a finite number greater than 1. Such an entry is a miss and no read deletes it. A later miss\n * or write (`getOrSet`, `set`, `@CachePut`) may still overwrite it with a `v: 1` entry.\n */\nexport function isNewerEnvelope(candidate: unknown): boolean {\n if (!hasOwnVersion(candidate)) return false;\n const v = (candidate as Record<string, unknown>)['v'];\n return typeof v === 'number' && Number.isFinite(v) && v > 1;\n}\n\nexport function isEnvelope(candidate: unknown): candidate is CacheEnvelope {\n if (typeof candidate !== 'object' || candidate === null) return false;\n const c = candidate as Record<string, unknown>;\n if (c['v'] !== 1 || !('value' in c)) return false;\n if (typeof c['storedAt'] !== 'number' || !Number.isFinite(c['storedAt'])) return false;\n for (const key of ['expiresAt', 'staleAt']) {\n const t = c[key];\n if (t !== undefined && (typeof t !== 'number' || !Number.isFinite(t))) return false;\n }\n const nil = c['nil'];\n if (nil !== undefined && nil !== 'null' && nil !== 'undefined') return false;\n return c['tags'] === undefined || isTagStamp(c['tags']);\n}\n\n/** A plain object whose own values are all strings; `{}` included. */\nfunction isTagStamp(tags: unknown): boolean {\n if (typeof tags !== 'object' || tags === null || Array.isArray(tags)) return false;\n return Object.values(tags).every((token) => typeof token === 'string');\n}\n","import type { CacheEnvelope } from '../envelope.js';\n\n// Leaf module of the strategies: the factories and `expiry-strategy.ts` import it, and it\n// imports none of them, so there is no runtime import cycle.\n\nexport type Classification = 'fresh' | 'stale' | 'expired';\n\nexport interface ExpiryStrategy {\n readonly kind: 'fixed' | 'swr' | 'sliding';\n /** The engine adds jitter to the ttl before calling `wrap` when true. */\n readonly jittered: boolean;\n /** Only receives non-null/undefined-or-nil values; `ttl` is an integer >= 1. */\n wrap(value: unknown, now: number, ttl: number): { envelope: CacheEnvelope; storeTtl: number };\n read(ttl: number): { touch: false } | { touch: true; touchTtl: number };\n classify(envelope: CacheEnvelope, now: number): Classification;\n}\n\n/** Shared by every strategy, so envelopes written by one strategy are readable by any other. */\nexport function classifyEnvelope(envelope: CacheEnvelope, now: number): Classification {\n if (envelope.expiresAt !== undefined && now >= envelope.expiresAt) return 'expired';\n if (envelope.staleAt !== undefined && now >= envelope.staleAt) return 'stale';\n return 'fresh';\n}\n","import { wrap } from '../envelope.js';\nimport { classifyEnvelope, type ExpiryStrategy } from './classify.js';\n\nexport function fixedStrategy(): ExpiryStrategy {\n return {\n kind: 'fixed',\n jittered: true,\n wrap: (value, now, ttl) => ({ envelope: wrap(value, now, ttl), storeTtl: ttl }),\n read: () => ({ touch: false }),\n classify: classifyEnvelope,\n };\n}\n","import type { CacheEnvelope } from '../envelope.js';\nimport { classifyEnvelope, type ExpiryStrategy } from './classify.js';\n\nexport function slidingStrategy(maxTtl?: number): ExpiryStrategy {\n return {\n kind: 'sliding',\n jittered: false,\n wrap: (value, now, ttl) => {\n // No expiresAt: the store TTL slides on every read, so the envelope carries no deadline.\n const envelope: CacheEnvelope = { v: 1, value, storedAt: now };\n return { envelope, storeTtl: ttl };\n },\n read: (ttl) => ({ touch: true, touchTtl: ttl }),\n classify: (envelope, now) =>\n maxTtl !== undefined && now >= envelope.storedAt + maxTtl\n ? 'expired'\n : classifyEnvelope(envelope, now),\n };\n}\n","import { wrap } from '../envelope.js';\nimport { classifyEnvelope, type ExpiryStrategy } from './classify.js';\n\nexport function swrStrategy(staleTtl: number): ExpiryStrategy {\n const window = Math.max(1, Math.round(staleTtl));\n return {\n kind: 'swr',\n jittered: true,\n wrap: (value, now, ttl) => {\n const staleAt = now + ttl;\n const envelope = { ...wrap(value, now, ttl), staleAt, expiresAt: staleAt + window };\n return { envelope, storeTtl: ttl + window };\n },\n read: () => ({ touch: false }),\n classify: classifyEnvelope,\n };\n}\n","import { CacheConfigError } from '../../errors.js';\nimport type { LoadStrategyOptions } from '../../decorators/options.js';\nimport type { ExpiryStrategy } from './classify.js';\nimport { fixedStrategy } from './fixed.strategy.js';\nimport { slidingStrategy } from './sliding.strategy.js';\nimport { swrStrategy } from './swr.strategy.js';\n\nexport { classifyEnvelope, type Classification, type ExpiryStrategy } from './classify.js';\n\n/**\n * Copies the defined `strategy`/`staleTtl`/`maxTtl`/`softTimeout` fields, so callers can forward\n * strategy options without carrying undefined-valued keys (`exactOptionalPropertyTypes`).\n */\nexport function strategyOptionsOf(options: LoadStrategyOptions): LoadStrategyOptions {\n const picked: { strategy?: string; staleTtl?: number; maxTtl?: number; softTimeout?: number } =\n {};\n if (options.strategy !== undefined) picked.strategy = options.strategy;\n if (options.staleTtl !== undefined) picked.staleTtl = options.staleTtl;\n if (options.maxTtl !== undefined) picked.maxTtl = options.maxTtl;\n if (options.softTimeout !== undefined) picked.softTimeout = options.softTimeout;\n // The picked fields come from one LoadStrategyOptions value, so they form one again.\n return picked as LoadStrategyOptions;\n}\n\nexport function createStrategy(options?: LoadStrategyOptions): ExpiryStrategy {\n const name: unknown = options?.strategy;\n switch (name) {\n case undefined:\n case 'fixed':\n return fixedStrategy();\n case 'swr':\n return swrStrategy((options as { staleTtl: number }).staleTtl);\n case 'sliding':\n return slidingStrategy((options as { maxTtl?: number }).maxTtl);\n default:\n throw new CacheConfigError(\n `Unknown cache strategy: ${String(name)}. Use 'fixed', 'swr' or 'sliding'.`,\n );\n }\n}\n","import 'reflect-metadata';\nimport { Inject } from '@nestjs/common';\nimport { CACHE_ENGINE, CACHE_ENGINE_PROPERTY } from '../module/tokens.js';\n\nconst injected = new WeakSet<object>();\n\n/**\n * Registers property injection of the cache engine on a class prototype.\n * Idempotent per prototype. Deliberately not `@Optional()`: a missing\n * CacheModule must fail at application start-up.\n */\nexport function injectEngine(target: object): void {\n if (injected.has(target)) return;\n injected.add(target);\n Inject(CACHE_ENGINE)(target, CACHE_ENGINE_PROPERTY);\n}\n\n/** Reads the engine injected into a provider instance, if any. */\nexport function engineOf(instance: unknown): unknown {\n if (typeof instance !== 'object' || instance === null) return undefined;\n return (instance as Record<symbol, unknown>)[CACHE_ENGINE_PROPERTY];\n}\n","import type { LoadOptions } from '../core/cache-engine.js';\nimport {\n assertBoolean,\n assertFunction,\n assertNamespace,\n assertPositiveFinite,\n assertStrategyTtls,\n} from './metadata.js';\nimport {\n assertInstanceMethod,\n compileKeyAt,\n compileTags,\n presetStrategy,\n putOptionsOf,\n wrapMethod,\n} from './method-wrapper.js';\nimport type { AsyncMethodDecorator, CacheableOptions, KeySpec } from './options.js';\n\n/**\n * Caches the result of an async method: a hit returns the cached value without running the\n * method; a miss runs it and stores the result. Invalid options throw `CacheConfigError` at\n * class definition.\n */\nexport function Cacheable<\n K extends unknown[] = never[],\n C extends unknown[] = never[],\n R = unknown,\n G extends unknown[] = never[],\n>(options?: CacheableOptions<K, C, R, G>): AsyncMethodDecorator<K, C, R, G> {\n return (target, propertyKey, descriptor) => {\n assertInstanceMethod(target, propertyKey);\n assertNamespace(target, propertyKey, options?.namespace);\n assertPositiveFinite(target, propertyKey, 'ttl', options?.ttl);\n assertPositiveFinite(target, propertyKey, 'nullTtl', options?.nullTtl);\n assertBoolean(target, propertyKey, 'cacheNull', options?.cacheNull);\n assertBoolean(target, propertyKey, 'lock', options?.lock);\n assertFunction(target, propertyKey, 'condition', options?.condition);\n assertFunction(target, propertyKey, 'unless', options?.unless);\n assertStrategyTtls(target, propertyKey, options);\n const keyOf = compileKeyAt(target, propertyKey, options?.key as KeySpec<never[]> | undefined);\n const tagsOf = compileTags(target, propertyKey, options?.tags);\n const condition = options?.condition as ((...args: unknown[]) => boolean) | undefined;\n const store = options?.store ?? 'default';\n const namespace = options?.namespace;\n const loadOptions: LoadOptions<unknown> = putOptionsOf(options);\n if (options?.lock !== undefined) loadOptions.lock = options.lock;\n const strategy = presetStrategy(loadOptions);\n wrapMethod(\n target,\n propertyKey,\n descriptor,\n { kind: 'cacheable', method: propertyKey, store, lock: options?.lock },\n (engine, call) => {\n let key: string;\n try {\n if (condition !== undefined && !condition(...call.args)) return call.invoke();\n key = keyOf(call);\n } catch (error) {\n engine.reportError(store, 'key', error);\n return call.invoke();\n }\n // Untagged calls share the options built once; tags are per call (D2).\n const options = tagsOf === undefined ? loadOptions : { ...loadOptions, tags: tagsOf(call) };\n return engine.getOrSet({ store, namespace, key }, call.invoke, options, strategy);\n },\n );\n };\n}\n","import {\n assertBoolean,\n assertFunction,\n assertNamespace,\n assertPositiveFinite,\n assertStrategyTtls,\n} from './metadata.js';\nimport {\n assertInstanceMethod,\n compileKeyAt,\n compileTags,\n presetStrategy,\n putOptionsOf,\n wrapMethod,\n} from './method-wrapper.js';\nimport type { AsyncMethodDecorator, CachePutOptions, KeySpec } from './options.js';\n\n/**\n * Always runs the async method and writes its result to the cache (unless `condition` is false\n * or `unless` is true). Invalid options throw `CacheConfigError` at class definition.\n */\nexport function CachePut<\n K extends unknown[] = never[],\n C extends unknown[] = never[],\n R = unknown,\n G extends unknown[] = never[],\n>(options?: CachePutOptions<K, C, R, G>): AsyncMethodDecorator<K, C, R, G> {\n return (target, propertyKey, descriptor) => {\n assertInstanceMethod(target, propertyKey);\n assertNamespace(target, propertyKey, options?.namespace);\n assertPositiveFinite(target, propertyKey, 'ttl', options?.ttl);\n assertPositiveFinite(target, propertyKey, 'nullTtl', options?.nullTtl);\n assertBoolean(target, propertyKey, 'cacheNull', options?.cacheNull);\n assertFunction(target, propertyKey, 'condition', options?.condition);\n assertFunction(target, propertyKey, 'unless', options?.unless);\n assertStrategyTtls(target, propertyKey, options, '@CachePut');\n const keyOf = compileKeyAt(target, propertyKey, options?.key as KeySpec<never[]> | undefined);\n const tagsOf = compileTags(target, propertyKey, options?.tags);\n const condition = options?.condition as ((...args: unknown[]) => boolean) | undefined;\n const store = options?.store ?? 'default';\n const namespace = options?.namespace;\n const putOptions = putOptionsOf(options);\n const strategy = presetStrategy(putOptions);\n wrapMethod(\n target,\n propertyKey,\n descriptor,\n { kind: 'put', method: propertyKey, store, lock: undefined },\n async (engine, call) => {\n // Condition and key are evaluated before the method runs, so a method\n // that mutates its arguments still writes under the key the caller asked for.\n let key: string | undefined;\n try {\n if (condition === undefined || condition(...call.args)) key = keyOf(call);\n } catch (error) {\n engine.reportError(store, 'key', error);\n }\n const tags = key === undefined ? undefined : tagsOf?.(call);\n // Tags known before the method (templates) have their tokens taken now, and the write\n // uses exactly those: an invalidation while the method runs is not lost (spec 3.3).\n const taken =\n tags === undefined || typeof tags === 'function'\n ? undefined\n : await engine.takeTags(store, tags);\n const result = await call.invoke();\n if (key !== undefined) {\n const options = tags === undefined ? putOptions : { ...putOptions, tags };\n await engine.put({ store, namespace, key }, result, options, strategy, taken);\n }\n return result;\n },\n );\n };\n}\n","import type { Target } from './engine-keys.js';\nimport type { ReportError } from './events.js';\nimport type { VersionTokens } from './version-tokens.js';\n\n/** The most tags one entry carries, counted after de-duplication (spec 2.5). */\nexport const MAX_TAGS = 32;\n\n/** The tag versions an entry was written with: each tag mapped to its token. */\nexport type TagStamp = Readonly<Record<string, string>>;\n\n/**\n * The engine-level tags of a single write (D2). An array is known before the load, so its tokens\n * are taken before the loader runs; a function gets the value once the write is decided.\n */\nexport type TagOption<T> = readonly string[] | ((value: T) => readonly string[]);\n\n/** The tags of a batch write (D2): an array for every entry, or a function of each entry. */\nexport type BatchTagOption<T> = readonly string[] | ((value: T, key: string) => readonly string[]);\n\n/**\n * How a write is stamped: a stamp (empty means the untagged 0.6 envelope), or `'skip'` after a\n * reported failure, and the entry is then not written.\n */\nexport type Stamping = TagStamp | 'skip';\n\n/**\n * How a read entry's stamp compares with the current tag tokens: `valid` (served), `invalid`\n * (a miss, loaded and written as usual), `unconfirmed` (the same miss, but it rests only on\n * process-cached tokens that may themselves be out of date, so the entry is never deleted;\n * ruling T4-C) or `uncertain` (the tokens could not be read: a miss that is loaded without\n * writing, spec 3.2 step 4).\n */\nexport type TagCheck = 'valid' | 'invalid' | 'unconfirmed' | 'uncertain';\n\n/**\n * `raw` as a tag list: an array of non-empty strings, de-duplicated (first occurrence kept), at\n * most `MAX_TAGS` long. Always a new array. Throws a `TypeError` naming the broken rule.\n */\nexport function normalizeTags(raw: unknown): string[] {\n if (!Array.isArray(raw)) {\n throw new TypeError(`Invalid tags: ${String(raw)}. Tags must be an array of strings.`);\n }\n const unique = new Set<string>();\n for (const tag of raw as readonly unknown[]) {\n if (typeof tag !== 'string') {\n throw new TypeError(`Invalid tag: ${String(tag)}. Every tag must be a string.`);\n }\n if (tag === '') throw new TypeError('Invalid tag: a tag must not be an empty string.');\n unique.add(tag);\n }\n if (unique.size > MAX_TAGS) {\n throw new TypeError(\n `Too many tags: ${String(unique.size)}. An entry carries at most ${String(MAX_TAGS)} tags.`,\n );\n }\n return [...unique];\n}\n\n/**\n * The stamp of `names` from `tokens`; built with own keys, so `__proto__` is a plain tag. A name\n * without a token makes it `'skip'`: a partial stamp would survive that tag's invalidation.\n */\nfunction stampOf(names: readonly string[], tokens: ReadonlyMap<string, string>): Stamping {\n const entries: [string, string][] = [];\n for (const name of names) {\n const token = tokens.get(name);\n if (token === undefined) return 'skip';\n entries.push([name, token]);\n }\n return Object.fromEntries(entries);\n}\n\n/**\n * The check of one stamp against `current`. A missing current token (the tag key is gone) is\n * `invalid`; with `fallback` (the last known tokens after a failed read) it is `uncertain`,\n * unless another tag of the stamp is known to differ. A stamp that differs only in tokens of\n * `cachedOnly` (taken from the process cache, not read from the store in this call) is\n * `unconfirmed` instead of `invalid`.\n */\nfunction checkStamp(\n stamp: TagStamp,\n current: ReadonlyMap<string, string | undefined>,\n fallback: boolean,\n cachedOnly: ReadonlySet<string>,\n): TagCheck {\n let unknown = false;\n let differs = false;\n for (const [tag, token] of Object.entries(stamp)) {\n const now = current.get(tag);\n if (now === undefined && fallback) unknown = true;\n else if (now !== token) {\n if (!cachedOnly.has(tag)) return 'invalid';\n differs = true;\n }\n }\n if (differs) return 'unconfirmed';\n return unknown ? 'uncertain' : 'valid';\n}\n\n/**\n * The tags worth re-reading (spec 3.3 step 1): those of each stamp that differs from `current`\n * only in tokens this call took from the process cache. A stamp that differs in a token just\n * read from the store (or a missing one) is a miss whatever the cached tokens say.\n */\nfunction suspectTags(\n stamps: readonly TagStamp[],\n current: ReadonlyMap<string, string | undefined>,\n fromCache: ReadonlySet<string>,\n): Set<string> {\n const suspects = new Set<string>();\n for (const stamp of stamps) {\n const differing = Object.entries(stamp).flatMap(([tag, token]) =>\n current.get(tag) === token ? [] : [tag],\n );\n if (differing.every((tag) => fromCache.has(tag))) {\n for (const tag of differing) suspects.add(tag);\n }\n }\n return suspects;\n}\n\n/** Whether `stamp` adds a `tags` field: an absent or empty stamp does not. */\nexport function hasTags(stamp: TagStamp | undefined): stamp is TagStamp {\n return stamp !== undefined && Object.keys(stamp).length > 0;\n}\n\n/**\n * Whether the tags are known before the load: anything set that is not a function (an array, or\n * an invalid value that `normalizeTags` then reports). Their tokens are taken before the loader.\n */\nexport function knownTags<O>(option: O | undefined): option is Exclude<O, CallableFunction> {\n return option !== undefined && typeof option !== 'function';\n}\n\n/** `items` with their stamps (same order); a skipped item is left out. */\nfunction applyStamps<I>(\n items: readonly I[],\n stamps: readonly Stamping[],\n): (I & { tags: TagStamp })[] {\n return items.flatMap((item, i) => {\n const stamp = stamps[i];\n return stamp === undefined || stamp === 'skip' ? [] : [{ ...item, tags: stamp }];\n });\n}\n\n/**\n * Tag stamps for writes (spec 3.3). An invalid tag list (a throwing callback included) is one\n * `tag` error per call; a failure to take the tokens is one `version` error. Either way the\n * affected entries are skipped, never the caller's call.\n */\nexport class EngineTags {\n constructor(\n private readonly tokens: VersionTokens,\n private readonly reportError: ReportError,\n ) {}\n\n /** The stamp of one write; `produce` returns the raw tags (a list, or a callback's result). */\n async stamp(target: Target, produce: () => unknown): Promise<Stamping> {\n const [stamping] = await this.stampEach(target, [produce]);\n return stamping ?? 'skip';\n }\n\n /**\n * The stamp of `option` for `value`: an array as is, a function called with the value. Used\n * where the value is known (set, put, the write after a load with a tag function).\n */\n stampFor<T>(target: Target, option: TagOption<T>, value: T): Promise<Stamping> {\n return this.stamp(target, () => (typeof option === 'function' ? option(value) : option));\n }\n\n /**\n * The stamps of several writes, in input order, with one `ensureMany` for all their tags.\n * One `tag` error covers every invalid list; one `version` error every failed token.\n */\n async stampEach(target: Target, produce: readonly (() => unknown)[]): Promise<Stamping[]> {\n const lists: (string[] | undefined)[] = [];\n let invalid: { error: unknown } | undefined;\n for (const tags of produce) {\n try {\n lists.push(normalizeTags(tags()));\n } catch (error) {\n invalid ??= { error };\n lists.push(undefined);\n }\n }\n if (invalid !== undefined) this.reportError(target.name, 'tag', invalid.error);\n const names = [...new Set(lists.flatMap((list) => list ?? []))];\n let tokens: ReadonlyMap<string, string> = new Map();\n if (names.length > 0) {\n try {\n tokens = await this.tokens.ensureMany(target, 'tag', names);\n } catch (error) {\n this.reportError(target.name, 'version', error);\n return lists.map((list) => (list?.length === 0 ? {} : 'skip'));\n }\n }\n return lists.map((list) => (list === undefined ? 'skip' : stampOf(list, tokens)));\n }\n\n /**\n * The checks of read entries' stamps, in input order, with one `currentMany` for the union of\n * their tags (spec 3.2). A failed token read is one `version` error for the call; a store with\n * `getStrict` then compares with the tokens this process last knew (even past `cacheTtl`), and\n * any other store makes every stamp `uncertain`. A stamp that differs only in tokens served\n * from the process cache gets those tags re-read (`recheck`), then is checked again (3.3); a\n * mismatch that still rests only on cached tokens (fallback included) is `unconfirmed`.\n */\n async verify(target: Target, stamps: readonly TagStamp[]): Promise<TagCheck[]> {\n const names = [...new Set(stamps.flatMap((stamp) => Object.keys(stamp)))];\n // The tags whose token comes from the process cache, not from a store read in this call.\n const cachedOnly = new Set<string>();\n let current: ReadonlyMap<string, string | undefined>;\n let fallback = false;\n try {\n current = await this.tokens.currentMany(target, 'tag', names, cachedOnly);\n } catch (error) {\n this.reportError(target.name, 'version', error);\n if (target.store.getStrict === undefined) return stamps.map(() => 'uncertain');\n current = new Map(names.map((name) => [name, this.tokens.cached(target, 'tag', name)]));\n for (const name of names) cachedOnly.add(name);\n fallback = true;\n }\n if (!fallback) {\n const suspects = suspectTags(stamps, current, cachedOnly);\n if (suspects.size > 0) current = await this.recheck(target, current, suspects, cachedOnly);\n }\n return stamps.map((stamp) => checkStamp(stamp, current, fallback, cachedOnly));\n }\n\n /**\n * `current` with `suspects` re-read, each at most once and in parallel; a tag refused by the\n * rate limit, or whose re-read fails, keeps its cached token (so its stamps stay a miss). A\n * re-read tag is removed from `cachedOnly`. Failed re-reads are one `version` error. Without\n * any re-read, `current` as it is, at once.\n */\n private async recheck(\n target: Target,\n current: ReadonlyMap<string, string | undefined>,\n suspects: ReadonlySet<string>,\n cachedOnly: Set<string>,\n ): Promise<ReadonlyMap<string, string | undefined>> {\n const reads: (readonly [string, Promise<string | undefined>])[] = [];\n for (const name of suspects) {\n const read = this.tokens.recheck(target, 'tag', name);\n if (read !== undefined) reads.push([name, read]);\n }\n if (reads.length === 0) return current;\n const updated = new Map(current);\n const failures: unknown[] = [];\n await Promise.all(\n reads.map(([name, read]) =>\n read.then(\n (token) => {\n updated.set(name, token);\n cachedOnly.delete(name);\n },\n (error: unknown) => {\n failures.push(error);\n },\n ),\n ),\n );\n if (failures.length > 0) this.reportError(target.name, 'version', failures[0]);\n return updated;\n }\n\n /**\n * Gives each of `names` (valid, de-duplicated) a new token (spec 3.4); this instance uses the\n * new tokens at once. Every tag is tried; a failure is one `version` error, then the call\n * rejects with the first failing tag's error.\n */\n async invalidate(target: Target, names: readonly string[]): Promise<void> {\n try {\n await this.tokens.bumpMany(target, 'tag', names);\n } catch (error) {\n this.reportError(target.name, 'version', error);\n throw error;\n }\n }\n\n /**\n * The batch writes `items` stamped for `option` together (one token call), in input order; an\n * item whose tags fail is left out. Without tags or items, `items` as they are.\n */\n async stampWrites<T, I extends { readonly value: T; readonly ref: { readonly key: string } }>(\n target: Target,\n option: BatchTagOption<T> | undefined,\n items: readonly I[],\n ): Promise<readonly I[]> {\n if (option === undefined || items.length === 0) return items;\n const entries = items.map(({ value, ref }) => ({ value, key: ref.key }));\n return applyStamps(items, await this.stampBatch(target, option, entries));\n }\n\n /**\n * The stamps of batch entries for `option`: an array is stamped once for all of them, a\n * function is called with each entry's value and key.\n */\n async stampBatch<T>(\n target: Target,\n option: BatchTagOption<T>,\n entries: readonly { readonly value: T; readonly key: string }[],\n ): Promise<Stamping[]> {\n if (typeof option !== 'function') {\n const stamping = await this.stamp(target, () => option);\n return entries.map(() => stamping);\n }\n const produce = entries.map(\n ({ value, key }) =>\n () =>\n option(value, key),\n );\n return this.stampEach(target, produce);\n }\n}\n","import type { CacheEngine } from '../core/cache-engine.js';\nimport { normalizeTags } from '../core/engine-tags.js';\nimport { CacheConfigError } from '../errors.js';\nimport { assertBoolean, assertNamespace, describeMethod } from './metadata.js';\nimport {\n assertInstanceMethod,\n compileEvictTags,\n compileKeyAt,\n wrapMethod,\n type MethodCall,\n} from './method-wrapper.js';\nimport type { AsyncMethodDecorator, CacheEvictOptions, KeySpec } from './options.js';\n\n/**\n * The tags one eviction invalidates (spec 2.5): empty tags are dropped; an invalid list (a\n * callback that throws, not an array, a non-string tag, more than 32 tags) is one `tag` error\n * and invalidates nothing. `undefined` when nothing is left to invalidate.\n */\nfunction tagsToEvict(\n engine: CacheEngine,\n store: string,\n build: (call: MethodCall) => unknown,\n call: MethodCall,\n): string[] | undefined {\n try {\n const raw = build(call);\n const names = normalizeTags(\n Array.isArray(raw) ? (raw as unknown[]).filter((tag) => tag !== '') : raw,\n );\n return names.length === 0 ? undefined : names;\n } catch (error) {\n engine.reportError(store, 'tag', error);\n return undefined;\n }\n}\n\n/** Gives the tags new versions; a failed token write is already a `version` error (spec 3.4). */\nasync function invalidate(engine: CacheEngine, store: string, tags: string[]): Promise<void> {\n try {\n await engine.invalidateTags(tags, store);\n } catch {\n // @CacheEvict never rejects for the cache: the failure surfaces as the event only.\n }\n}\n\n/**\n * Evicts cache entries around an async method: keys, tags or a whole namespace, after the\n * method succeeds (or before it, with `beforeInvocation`). Eviction failures never reject the\n * call. Invalid options throw `CacheConfigError` at class definition.\n */\nexport function CacheEvict<K extends unknown[] = never[], G extends unknown[] = never[]>(\n options?: CacheEvictOptions<K, G>,\n): AsyncMethodDecorator<K, never[], unknown, G> {\n return (target, propertyKey, descriptor) => {\n assertInstanceMethod(target, propertyKey);\n const loose = (options ?? {}) as {\n namespace?: string;\n store?: string;\n key?: KeySpec<never[]> | readonly KeySpec<never[]>[];\n allEntries?: boolean;\n beforeInvocation?: boolean;\n tags?: unknown;\n };\n assertBoolean(target, propertyKey, 'allEntries', loose.allEntries);\n assertBoolean(target, propertyKey, 'beforeInvocation', loose.beforeInvocation);\n const { namespace, allEntries = false, beforeInvocation = false } = loose;\n assertNamespace(target, propertyKey, namespace);\n const store = loose.store ?? 'default';\n if (allEntries) {\n const where = describeMethod(target, propertyKey);\n if (typeof namespace !== 'string' || namespace === '') {\n throw new CacheConfigError(`${where}: allEntries requires a namespace`);\n }\n if (loose.key !== undefined) {\n throw new CacheConfigError(`${where}: allEntries cannot be combined with key`);\n }\n }\n if (Array.isArray(loose.key) && loose.key.length === 0) {\n throw new CacheConfigError(\n `${describeMethod(target, propertyKey)}: key must not be an empty array`,\n );\n }\n const tagsOf = compileEvictTags(target, propertyKey, loose.tags);\n // Without a key, tags alone evict no key; with neither, the default key is evicted, as in 0.6.\n const keySpecs: readonly (KeySpec<never[]> | undefined)[] = Array.isArray(loose.key)\n ? (loose.key as readonly KeySpec<never[]>[])\n : loose.key === undefined && tagsOf !== undefined\n ? []\n : [loose.key as KeySpec<never[]> | undefined];\n // A key that renders empty is allowed here: engine.delete drops and reports it, and still\n // deletes the other keys. A builder that throws skips the whole key eviction.\n const keyBuilders = allEntries\n ? []\n : keySpecs.map((spec) => compileKeyAt(target, propertyKey, spec, true));\n\n wrapMethod(\n target,\n propertyKey,\n descriptor,\n { kind: 'evict', method: propertyKey, store, lock: undefined },\n async (engine, call) => {\n // Keys and tags are built before the method runs, from the arguments as passed.\n let evictKeys: (() => Promise<void>) | undefined;\n try {\n if (allEntries) {\n evictKeys = () => engine.clear(namespace as string, store);\n } else if (keyBuilders.length > 0) {\n const keys = keyBuilders.map((build) => build(call));\n evictKeys = () => engine.delete({ store, namespace }, keys);\n }\n } catch (error) {\n engine.reportError(store, 'key', error);\n }\n const tags = tagsOf === undefined ? undefined : tagsToEvict(engine, store, tagsOf, call);\n if (evictKeys === undefined && tags === undefined) return call.invoke();\n // The key or namespace first, then the tags (spec 2.2).\n const evict = async (): Promise<void> => {\n if (evictKeys !== undefined) await evictKeys();\n if (tags !== undefined) await invalidate(engine, store, tags);\n };\n if (beforeInvocation) {\n await evict();\n return call.invoke();\n }\n const result = await call.invoke();\n await evict();\n return result;\n },\n );\n };\n}\n","import { applyDecorators, SetMetadata, StreamableFile, UseInterceptors } from '@nestjs/common';\nimport type { LoadOptions } from '../core/cache-engine.js';\nimport { createStrategy, type ExpiryStrategy } from '../core/strategies/expiry-strategy.js';\nimport {\n addCacheMetadata,\n assertBoolean,\n assertFunction,\n assertNamespace,\n assertPositiveFinite,\n assertStrategyTtls,\n assertTags,\n CLASS_LEVEL,\n describeMethod,\n hasBraceTag,\n} from '../decorators/metadata.js';\nimport { presetStrategy, putOptionsOf } from '../decorators/method-wrapper.js';\nimport type { LoadStrategyOptions } from '../decorators/options.js';\nimport { CacheConfigError } from '../errors.js';\nimport { HttpCacheInterceptor } from './http-cache.interceptor.js';\n\n/** What a `key` callback receives about the request. */\nexport interface HttpCacheRequest {\n method: string;\n /** The raw request URL, as received (query unsorted, nothing escaped). */\n url: string;\n /**\n * The key used when `key` is not set: the path plus the query sorted by name then value, with\n * `%` and `:` percent-encoded. It varies on path and query only.\n */\n defaultKey: string;\n path: string;\n query: Readonly<Record<string, string | readonly string[]>>;\n params: Readonly<Record<string, string>>;\n headers: Readonly<Record<string, string | readonly string[] | undefined>>;\n}\n\n/** Options of `@HttpCache`; the strategy options include `softTimeout` (a cached route loads). */\nexport type HttpCacheOptions = LoadStrategyOptions & {\n ttl?: number;\n /** Defaults to 'http'. */\n namespace?: string;\n store?: string;\n lock?: boolean;\n cacheNull?: boolean;\n nullTtl?: number;\n /**\n * A string is a fixed key, not a template: a non-empty string without `{` or `}`, and only on a\n * method (a class-level string throws `CacheConfigError` at decoration). A callback derives the\n * key per request; `undefined` skips caching that request.\n */\n key?: string | ((req: HttpCacheRequest) => string | undefined);\n /** Returns `true` to keep the body out of the cache. */\n unless?: (body: unknown) => boolean;\n /**\n * Tags the cached body (spec 2.1): fixed strings (not templates), or a callback of the body\n * and the request, called once the body is to be written.\n */\n tags?: readonly string[] | HttpCacheTags;\n};\n\n/** An `@HttpCache` tags callback. */\nexport type HttpCacheTags = (body: unknown, req: HttpCacheRequest) => readonly string[];\n\nexport const HTTP_CACHE_METADATA: unique symbol = Symbol('nestjs-cache:http-cache');\n\nexport interface HttpCacheMetadata {\n namespace: string;\n store: string | undefined;\n key: HttpCacheOptions['key'];\n loadOptions: LoadOptions<unknown>;\n strategy: ExpiryStrategy | undefined;\n /** A tags callback, called per request; a tags array is in `loadOptions` already. */\n tags: HttpCacheTags | undefined;\n}\n\n/** Bodies that are never cached: files, binary data and streams. */\nfunction isUncacheable(body: unknown): boolean {\n return (\n body instanceof StreamableFile ||\n body instanceof Uint8Array ||\n (typeof body === 'object' &&\n body !== null &&\n typeof (body as { pipe?: unknown }).pipe === 'function')\n );\n}\n\nfunction validate(\n target: object,\n method: string | symbol,\n options: HttpCacheOptions | undefined,\n): void {\n assertNamespace(target, method, options?.namespace);\n assertPositiveFinite(target, method, 'ttl', options?.ttl);\n assertPositiveFinite(target, method, 'nullTtl', options?.nullTtl);\n assertBoolean(target, method, 'cacheNull', options?.cacheNull);\n assertBoolean(target, method, 'lock', options?.lock);\n assertStrategyTtls(target, method, options);\n try {\n createStrategy(options);\n } catch (error) {\n throw new CacheConfigError(\n `${describeMethod(target, method)}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n const key: unknown = options?.key;\n if (key !== undefined && typeof key !== 'function' && (typeof key !== 'string' || key === '')) {\n throw new CacheConfigError(\n `${describeMethod(target, method)}: key must be a non-empty string or a function, got ${typeof key}`,\n );\n }\n if (typeof key === 'string' && method === CLASS_LEVEL) {\n throw new CacheConfigError(\n `${describeMethod(target, method)}: a class-level key would be shared by every route; put the key on each method or use a callback`,\n );\n }\n if (typeof key === 'string' && /[{}]/.test(key)) {\n throw new CacheConfigError(\n `${describeMethod(target, method)}: key is not a template; use a key callback`,\n );\n }\n assertTags(target, method, options?.tags);\n if (hasBraceTag(options?.tags)) {\n throw new CacheConfigError(\n `${describeMethod(target, method)}: tags are not templates; use a tags callback`,\n );\n }\n assertFunction(target, method, 'unless', options?.unless);\n}\n\n/** Caches the HTTP response body of a route (method) or of every route of a controller (class). */\nexport function HttpCache(options?: HttpCacheOptions): MethodDecorator & ClassDecorator {\n return (target: object, propertyKey?: string | symbol, descriptor?: PropertyDescriptor) => {\n const isClass = propertyKey === undefined;\n const holder = isClass ? (target as { prototype: object }).prototype : target;\n const method = isClass ? CLASS_LEVEL : propertyKey;\n validate(holder, method, options);\n const loadOptions: LoadOptions<unknown> = putOptionsOf(options);\n if (options?.lock !== undefined) loadOptions.lock = options.lock;\n // The built-in check first, then the user's: a file or stream never reaches the user's `unless`.\n const unless = options?.unless;\n loadOptions.unless = (body) => isUncacheable(body) || unless?.(body) === true;\n const tags = options?.tags;\n // Fixed tags are the same for every request: their tokens are taken before the handler runs.\n if (Array.isArray(tags) && tags.length > 0) loadOptions.tags = [...(tags as readonly string[])];\n const metadata: HttpCacheMetadata = {\n namespace: options?.namespace ?? 'http',\n store: options?.store,\n key: options?.key,\n loadOptions,\n strategy: presetStrategy(loadOptions),\n tags: typeof tags === 'function' ? tags : undefined,\n };\n addCacheMetadata(holder, {\n kind: 'http',\n method,\n store: options?.store ?? 'default',\n lock: options?.lock,\n });\n const decorate = applyDecorators(\n UseInterceptors(HttpCacheInterceptor),\n SetMetadata(HTTP_CACHE_METADATA, metadata),\n );\n if (isClass) (decorate as ClassDecorator)(target as never);\n else (decorate as MethodDecorator)(target, propertyKey, descriptor as PropertyDescriptor);\n };\n}\n","import {\n Inject,\n Injectable,\n type CallHandler,\n type ExecutionContext,\n type NestInterceptor,\n} from '@nestjs/common';\nimport { SSE_METADATA } from '@nestjs/common/constants.js';\nimport { HttpAdapterHost, Reflector } from '@nestjs/core';\nimport { defer, finalize, from, lastValueFrom, type Observable } from 'rxjs';\nimport type { CacheEngine } from '../core/cache-engine.js';\nimport { emptyKeyError, isEmptyKey } from '../core/key-builder.js';\nimport { CACHE_ENGINE } from '../module/tokens.js';\nimport {\n HTTP_CACHE_METADATA,\n type HttpCacheMetadata,\n type HttpCacheRequest,\n} from './http-cache.decorator.js';\nimport { httpCacheKey, parseHttpUrl } from './http-cache-key.js';\n\ninterface RawRequest {\n params?: Record<string, string>;\n headers?: Record<string, string | string[] | undefined>;\n}\n\n/**\n * Requests whose `@HttpCache` load is running. Nest does not de-duplicate interceptors: a class-level\n * and a method-level `@HttpCache`, or an `APP_INTERCEPTOR` plus a route's `@HttpCache`, run this\n * interceptor twice per request. The inner run is invoked from the outer run's load and must pass\n * through, or its `getOrSet` would join the outer flight and wait for itself. Module-level because\n * the global and the route-level interceptors are different instances.\n */\nconst loading = new WeakSet<object>();\n\n/**\n * Requests an outer run decided not to cache (the key callback returned `undefined` or threw) and\n * is passing through. The nested run passes through too, without calling the key callback again\n * (a throwing callback would report a second `key` error). Cleared once the pass-through settles.\n */\nconst passing = new WeakSet<object>();\n\n/**\n * Caches GET/HEAD response bodies of routes marked with `@HttpCache`; other requests pass through.\n *\n * Created by Nest; inject it, do not construct it. Constructor parameters are not part of the\n * public API.\n */\n@Injectable()\nexport class HttpCacheInterceptor implements NestInterceptor {\n constructor(\n @Inject(CACHE_ENGINE) private readonly engine: CacheEngine,\n @Inject(Reflector) private readonly reflector: Reflector,\n @Inject(HttpAdapterHost) private readonly adapterHost: HttpAdapterHost,\n ) {}\n\n intercept(context: ExecutionContext, next: CallHandler): Observable<unknown> {\n if (context.getType() !== 'http') return next.handle();\n const metadata = this.reflector.getAllAndOverride<HttpCacheMetadata | undefined>(\n HTTP_CACHE_METADATA,\n [context.getHandler(), context.getClass()],\n );\n if (metadata === undefined) return next.handle();\n // A server-sent event route streams many values; caching would buffer it down to the last one.\n if (this.reflector.get<boolean | undefined>(SSE_METADATA, context.getHandler()) === true) {\n return next.handle();\n }\n const req: unknown = context.switchToHttp().getRequest();\n if (isObject(req) && (loading.has(req) || passing.has(req))) return next.handle();\n const adapter = this.adapterHost.httpAdapter;\n const method = adapter.getRequestMethod(req) as string;\n if (method !== 'GET' && method !== 'HEAD') return next.handle();\n const url = adapter.getRequestUrl(req) as string;\n\n let key: string | undefined;\n try {\n key = this.keyOf(metadata, req, method, url);\n } catch (error) {\n this.engine.reportError(metadata.store, 'key', error);\n return passThrough(req, next);\n }\n if (key === undefined) return passThrough(req, next);\n\n const { store, namespace, strategy, tags } = metadata;\n // A tags callback gets the body and the request, once the body is to be written.\n const options =\n tags === undefined\n ? metadata.loadOptions\n : {\n ...metadata.loadOptions,\n tags: (body: unknown) => tags(body, toHttpCacheRequest(req, method, url)),\n };\n // Lazy: nothing reads the store or runs the handler before the caller subscribes.\n return defer(() =>\n from(\n this.engine.getOrSet({ store, namespace, key }, () => load(req, next), options, strategy),\n ),\n );\n }\n\n /** The cache key per spec 3.2; `undefined` skips the cache, a throw is a key error. */\n private keyOf(\n metadata: HttpCacheMetadata,\n req: unknown,\n method: string,\n url: string,\n ): string | undefined {\n const spec = metadata.key;\n if (spec === undefined) return httpCacheKey(url);\n if (typeof spec === 'string') return spec;\n const key: unknown = spec(toHttpCacheRequest(req, method, url));\n if (key === undefined) return undefined;\n if (typeof key !== 'string') {\n throw new TypeError(`HttpCache key callback returned ${typeof key}, expected a string`);\n }\n if (isEmptyKey(key)) throw emptyKeyError();\n return key;\n }\n}\n\nfunction isObject(value: unknown): value is object {\n return (typeof value === 'object' && value !== null) || typeof value === 'function';\n}\n\n/** Runs the rest of the chain with `req` marked as loading, so a nested run of this interceptor passes through. */\nasync function load(req: unknown, next: CallHandler): Promise<unknown> {\n if (!isObject(req)) return lastValueFrom(next.handle(), { defaultValue: undefined });\n loading.add(req);\n try {\n return await lastValueFrom(next.handle(), { defaultValue: undefined });\n } finally {\n loading.delete(req);\n }\n}\n\n/**\n * Runs the rest of the chain with `req` marked as passing through, so a nested run passes through\n * without calling the key callback again.\n */\nfunction passThrough(req: unknown, next: CallHandler): Observable<unknown> {\n if (!isObject(req)) return next.handle();\n return defer(() => {\n passing.add(req);\n return next.handle().pipe(finalize(() => passing.delete(req)));\n });\n}\n\nfunction toHttpCacheRequest(req: unknown, method: string, url: string): HttpCacheRequest {\n const raw = req as RawRequest;\n const { path, query } = parseHttpUrl(url);\n return {\n method,\n url,\n defaultKey: httpCacheKey(url),\n path,\n query,\n params: raw.params ?? {},\n headers: raw.headers ?? {},\n };\n}\n","import { escapeKeyArg } from '../core/key-builder.js';\n\nexport interface ParsedHttpUrl {\n path: string;\n query: Record<string, string | string[]>;\n}\n\nfunction split(url: string): { path: string; pairs: [string, string][] } {\n const index = url.indexOf('?');\n if (index === -1) return { path: url, pairs: [] };\n return {\n path: url.slice(0, index),\n pairs: [...new URLSearchParams(url.slice(index + 1))],\n };\n}\n\n/** Splits a request URL into its path and query. A name seen once is a string, several times an array in input order. */\nexport function parseHttpUrl(url: string): ParsedHttpUrl {\n const { path, pairs } = split(url);\n const query: Record<string, string | string[]> = Object.create(null) as Record<\n string,\n string | string[]\n >;\n for (const [name, value] of pairs) {\n const seen = query[name];\n if (seen === undefined) query[name] = value;\n else if (typeof seen === 'string') query[name] = [seen, value];\n else seen.push(value);\n }\n return { path, query: { ...query } };\n}\n\n/** Default `@HttpCache` key: the path plus the query sorted by name then value, with `%` and `:` percent-encoded. */\nexport function httpCacheKey(url: string): string {\n const { path, pairs } = split(url);\n const sorted = pairs.sort((a, b) =>\n a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0,\n );\n const query = new URLSearchParams(sorted).toString();\n return escapeKeyArg(query === '' ? path : `${path}?${query}`);\n}\n","import { isEnvelope, type CacheEnvelope } from '../core/envelope.js';\n\n/**\n * Turns an entry's envelope into the string a store holds, and back\n * (`CacheModuleOptions.serializer`).\n * `deserialize` must throw on input it does not recognise: the engine reports that as an `error`\n * event with operation `'deserialize'` and treats the entry as a miss.\n *\n * `deserialize(serialize(e))` must keep every field of `e`, including fields this version does\n * not know.\n *\n * Implemented by you. In 1.x, members are only added as optional, and the library checks that\n * they exist before calling them.\n */\nexport interface Serializer {\n serialize(envelope: CacheEnvelope): string;\n deserialize(raw: string): CacheEnvelope;\n}\n\n/** The default serializer: `JSON.stringify` and `JSON.parse`, with an envelope shape check. */\nexport const jsonSerializer: Serializer = {\n serialize(envelope) {\n return JSON.stringify(envelope);\n },\n deserialize(raw) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw new Error('Invalid cache payload: not valid JSON');\n }\n if (!isEnvelope(parsed)) throw new Error('Invalid cache payload: not a cache envelope');\n return parsed;\n },\n};\n","import {\n brotliCompressSync,\n brotliDecompressSync,\n constants,\n gunzipSync,\n gzipSync,\n} from 'node:zlib';\nimport { CacheConfigError } from '../errors.js';\nimport { hasOwnVersion, isNewerEnvelope, type CacheEnvelope } from '../core/envelope.js';\nimport { jsonSerializer, type Serializer } from './json.serializer.js';\n\n/** Options of `compressedSerializer`. */\nexport interface CompressedSerializerOptions {\n /** Produces and reads the string that gets compressed. Default `jsonSerializer`. */\n inner?: Serializer;\n /** Algorithm used for writes; reads follow the prefix of the stored value. Default `'gzip'`. */\n algorithm?: 'gzip' | 'brotli';\n /**\n * Compression level: 0-9 for gzip (default 6, zlib's default) and 0-11 for brotli (default 4).\n * Compression runs synchronously on the event loop. Brotli's own default, 11, is much slower:\n * about 1.6 s for a 724 KB JSON value, against about 2 ms at 4. Reads accept any level.\n */\n level?: number;\n /** UTF-8 byte length of the inner string above which compression is tried. Default 1024. */\n threshold?: number;\n /**\n * Upper bound of a decompressed payload, in bytes. Default 16 MiB. Larger payloads are written\n * uncompressed so they stay readable.\n */\n maxDecompressedBytes?: number;\n}\n\n/**\n * Internal (not exported from the package): the key of the check `compressedSerializer` adds\n * over `jsonSerializer`, which tells the engine whether an unreadable raw string is one of the\n * library's own envelopes, ours and deletable (a newer `v` is kept) (spec 4). The check returns\n * `undefined` when it cannot tell.\n */\nexport const OWN_ENVELOPE: unique symbol = Symbol('nestjs-cache.ownEnvelope');\n\nconst DETECT = '\\u0000nc1:';\nconst PREFIXES = { gzip: `${DETECT}gz:`, brotli: `${DETECT}br:` } as const;\n\n/**\n * Wraps a serializer with gzip or brotli compression of large payloads. A compressed value is\n * `\"\\u0000nc1:gz:\"` or `\"\\u0000nc1:br:\"` plus base64; anything else is read by `inner`.\n * `inner` must not produce strings starting with `\"\\u0000nc1:\"`.\n */\nexport function compressedSerializer(options: CompressedSerializerOptions = {}): Serializer {\n const {\n inner: suppliedInner = jsonSerializer,\n threshold = 1024,\n maxDecompressedBytes = 16 * 1024 * 1024,\n } = options;\n // Runtime values can be anything: validate against the widest types.\n const algorithm: string = options.algorithm ?? 'gzip';\n const inner = suppliedInner as Partial<Serializer> | null;\n if (algorithm !== 'gzip' && algorithm !== 'brotli') {\n throw new CacheConfigError(\"compressedSerializer: algorithm must be 'gzip' or 'brotli'\");\n }\n const maxLevel = algorithm === 'gzip' ? 9 : 11;\n const level: unknown = options.level ?? (algorithm === 'gzip' ? 6 : 4);\n if (typeof level !== 'number' || !Number.isInteger(level) || level < 0 || level > maxLevel) {\n throw new CacheConfigError(\n `compressedSerializer: level must be an integer from 0 to ${String(maxLevel)} for ${algorithm}`,\n );\n }\n if (!Number.isInteger(threshold) || threshold < 0) {\n throw new CacheConfigError('compressedSerializer: threshold must be an integer >= 0');\n }\n if (!Number.isInteger(maxDecompressedBytes) || maxDecompressedBytes <= 0) {\n throw new CacheConfigError('compressedSerializer: maxDecompressedBytes must be an integer > 0');\n }\n if (\n typeof inner !== 'object' ||\n inner === null ||\n typeof inner.serialize !== 'function' ||\n typeof inner.deserialize !== 'function'\n ) {\n throw new CacheConfigError('compressedSerializer: inner needs serialize and deserialize');\n }\n const serializer = inner as Serializer;\n const prefix = PREFIXES[algorithm];\n\n /** The inner string of a prefixed `raw`; throws as `deserialize` does on bad input. */\n const unpack = (raw: string): string => {\n const body = raw.slice(DETECT.length);\n const tag = body.slice(0, 3);\n if (tag !== 'gz:' && tag !== 'br:') {\n throw new Error('Invalid cache payload: unknown compression algorithm');\n }\n const encoded = body.slice(3);\n if (!/^[A-Za-z0-9+/]*={0,2}$/.test(encoded) || encoded.length % 4 === 1) {\n throw new Error('Invalid cache payload: not valid base64');\n }\n const bytes = Buffer.from(encoded, 'base64');\n const unpacked =\n tag === 'gz:'\n ? gunzipSync(bytes, { maxOutputLength: maxDecompressedBytes })\n : brotliDecompressSync(bytes, { maxOutputLength: maxDecompressedBytes });\n return unpacked.toString('utf8');\n };\n\n const compressed: Serializer = {\n serialize(envelope: CacheEnvelope): string {\n const plain = serializer.serialize(envelope);\n const size = Buffer.byteLength(plain, 'utf8');\n if (size <= threshold) return plain;\n // A compressed payload above maxDecompressedBytes could never be read back; plain reads\n // have no such limit.\n if (size > maxDecompressedBytes) return plain;\n const bytes = Buffer.from(plain, 'utf8');\n const packed =\n algorithm === 'gzip'\n ? gzipSync(bytes, { level })\n : brotliCompressSync(bytes, { params: { [constants.BROTLI_PARAM_QUALITY]: level } });\n const out = prefix + packed.toString('base64');\n return out.length < plain.length ? out : plain;\n },\n deserialize(raw: string): CacheEnvelope {\n return serializer.deserialize(raw.startsWith(DETECT) ? unpack(raw) : raw);\n },\n };\n // Only over the built-in JSON serializer, whose format is known. Non-enumerable, so a spread\n // copy with another `deserialize` does not inherit a check that no longer matches it.\n if (serializer === jsonSerializer) {\n Object.defineProperty(compressed, OWN_ENVELOPE, {\n value: (raw: string): boolean | undefined => {\n let plain = raw;\n if (raw.startsWith(DETECT)) {\n try {\n plain = unpack(raw);\n } catch {\n // A value that cannot be decompressed may be anything: never grounds to delete.\n return undefined;\n }\n }\n try {\n const parsed: unknown = JSON.parse(plain);\n return hasOwnVersion(parsed) && !isNewerEnvelope(parsed);\n } catch {\n return false;\n }\n },\n });\n }\n return compressed;\n}\n","/** The state of a `CircuitBreakerStore`, as `breaker` events report it. */\nexport type BreakerState = 'closed' | 'open' | 'half-open';\n\n/** How much the library logs: nothing, errors and warnings (the default), or also one debug line per event. */\nexport type CacheLogLevel = 'off' | 'error' | 'debug';\n\n/**\n * The operation an `error` event reports as failed.\n *\n * Provided by the library. New members, events, fields or values may be added in a minor release;\n * handle unknown ones.\n */\nexport type CacheOperation =\n | 'get'\n | 'set'\n | 'delete'\n | 'clear'\n | 'deserialize'\n | 'key'\n | 'publish'\n | 'subscribe'\n | 'refresh'\n | 'lock'\n | 'version'\n /** An invalid tag list (a throwing tag callback included); the entry is not written. */\n | 'tag';\n\n/**\n * Internal: the operations `CacheLogger` logs; `'metrics'` is a failing metrics update and\n * `'tracing'` a throwing tracer or span method.\n */\nexport type LogOperation = CacheOperation | 'metrics' | 'tracing';\n\n/** Internal: reports a cache failure as an `error` event; `EngineIO.reportError`. */\nexport type ReportError = (\n store: string | undefined,\n operation: CacheOperation,\n error: unknown,\n) => void;\n\n/**\n * The payload of each `CacheEvents` event. `store` is the store name; `key` and `keys` are the\n * user keys, without the prefix, namespace or version token.\n *\n * Provided by the library. New members, events, fields or values may be added in a minor release;\n * handle unknown ones.\n */\nexport interface CacheEventMap {\n /** A read found the entry; `stale` is an `swr` entry past its `ttl`. */\n hit: { store: string; namespace: string | undefined; key: string; stale: boolean };\n miss: { store: string; namespace: string | undefined; key: string };\n set: {\n store: string;\n namespace: string | undefined;\n key: string;\n /**\n * The TTL the store was given, in ms: under `swr` it includes `staleTtl`, and it carries the\n * `defaults.jitter` (not under `sliding`).\n */\n ttl: number;\n };\n delete: {\n store: string;\n namespace: string | undefined;\n /** The user keys deleted, as passed (not the store keys). */\n keys: readonly string[];\n };\n clear: { store: string; namespace: string };\n /** One loader call finished (`success: false` when it threw). */\n load: {\n store: string;\n namespace: string | undefined;\n /** The loaded key; on a batch load, the first of `keys`. */\n key: string;\n /** Only on a batch load (`getOrSetMany`): every key passed to the loader; `key` is the first. */\n keys?: readonly string[];\n durationMs: number;\n success: boolean;\n };\n /** A cache failure the call did not surface; see `CacheOperation`. */\n error: { store: string; operation: CacheOperation; error: unknown };\n lock: {\n store: string;\n namespace: string | undefined;\n key: string;\n waitedMs: number;\n acquired: boolean;\n };\n breaker: { store: string; state: BreakerState };\n}\n\n/**\n * What a store gets from `CacheStore.bind`: it reports its own failures (`error`) and breaker\n * state changes (`breaker`) through it; the module adds the store name.\n *\n * Provided by the library. New members, events, fields or values may be added in a minor release;\n * handle unknown ones.\n */\nexport interface CacheEventSink {\n emit(event: 'error', payload: { operation: CacheOperation; error: unknown }): void;\n emit(event: 'breaker', payload: { state: BreakerState }): void;\n /**\n * The module's log level, so a store can skip its own warnings at `'off'`. Sinks from\n * `CacheModule` always set it; a missing value (a hand-built sink) means `'error'`.\n */\n readonly logLevel?: CacheLogLevel;\n}\n\n/** One tuple per sink overload, so the event name narrows its payload. */\ntype SinkArgs =\n | [event: 'error', payload: { operation: CacheOperation; error: unknown }]\n | [event: 'breaker', payload: { state: BreakerState }];\n\ntype Listener<E extends keyof CacheEventMap> = (payload: CacheEventMap[E]) => void;\n\n/**\n * The cache event bus, provided by `CacheModule`: inject it and subscribe with `on`. Only the\n * library emits events.\n *\n * Created by Nest; inject it, do not construct it. Constructor parameters are not part of the\n * public API.\n */\nexport class CacheEvents {\n private readonly listeners = new Map<keyof CacheEventMap, Set<{ fn: unknown }>>();\n\n constructor(private readonly onListenerError?: (error: unknown) => void) {}\n\n /**\n * Calls `listener` with the payload of every `event`, synchronously, in registration order.\n * A listener that throws is isolated: the module logs it (unless `logging.level` is `'off'`)\n * and it never reaches the cache call. Returns a function that removes this registration.\n */\n on<E extends keyof CacheEventMap>(event: E, listener: Listener<E>): () => void {\n // A fresh entry object per registration keeps duplicates of the same function distinct.\n const entry = { fn: listener as unknown };\n let set = this.listeners.get(event);\n if (!set) {\n set = new Set();\n this.listeners.set(event, set);\n }\n set.add(entry);\n return () => {\n this.listeners.get(event)?.delete(entry);\n };\n }\n\n /** @internal Used by the library to publish events; not part of the public API. */\n emit<E extends keyof CacheEventMap>(event: E, payload: CacheEventMap[E]): void {\n const set = this.listeners.get(event);\n if (!set) return;\n for (const entry of [...set]) {\n try {\n (entry.fn as Listener<E>)(payload);\n } catch (error) {\n try {\n this.onListenerError?.(error);\n } catch {\n // a failing error handler must never reach the emitter\n }\n }\n }\n }\n\n /**\n * @internal Builds the sink passed to `CacheStore.bind`; not part of the public API.\n * The event name alone picks the event; the overloads tie each name to its payload.\n */\n sinkFor(store: string, logLevel: CacheLogLevel = 'error'): CacheEventSink {\n return {\n logLevel,\n emit: (...[event, payload]: SinkArgs): void => {\n switch (event) {\n case 'error':\n this.emit('error', { store, operation: payload.operation, error: payload.error });\n return;\n case 'breaker':\n this.emit('breaker', { store, state: payload.state });\n return;\n default: {\n // Unreachable for typed callers; an untyped store's unknown event is ignored.\n const unreachable: never = event;\n return unreachable;\n }\n }\n },\n };\n }\n}\n","import { CacheConfigError } from '../errors.js';\nimport type { CacheStore } from './cache-store.interface.js';\n\ninterface Entry {\n value: string;\n expiresAt: number;\n}\n\n/** Options of `memoryStore`. */\nexport interface MemoryStoreOptions {\n /** Entries kept before the least recently used one is evicted; an integer >= 1. Default 1 000. */\n maxEntries?: number;\n}\n\nconst DEFAULT_MAX_ENTRIES = 1_000;\n/** At capacity, expired entries are swept at most this often (ms); otherwise the LRU goes. */\nconst SWEEP_INTERVAL_MS = 1_000;\n\n/** One LRU on Map insertion order, bounded by entry count. Expiry is lazy; no timers. */\nclass Partition {\n readonly entries = new Map<string, Entry>();\n private lastSweepAt = Number.NEGATIVE_INFINITY;\n\n constructor(private readonly maxEntries: number) {}\n\n /**\n * Removes an expired entry; moves a live one to most recently used and, given `touchTtl`,\n * resets its TTL.\n */\n read(key: string, touchTtl: number | undefined): string | undefined {\n const entry = this.entries.get(key);\n if (entry === undefined) return undefined;\n this.entries.delete(key);\n const now = Date.now();\n if (now >= entry.expiresAt) return undefined;\n if (touchTtl !== undefined) entry.expiresAt = now + touchTtl;\n this.entries.set(key, entry);\n return entry.value;\n }\n\n write(key: string, entry: Entry): void {\n if (this.entries.has(key)) {\n this.entries.delete(key);\n } else if (this.entries.size >= this.maxEntries) {\n const now = Date.now();\n // A full scan on every insert at capacity is O(n); between sweeps the LRU head is evicted.\n if (now - this.lastSweepAt >= SWEEP_INTERVAL_MS) {\n this.lastSweepAt = now;\n for (const [k, e] of this.entries) {\n if (now >= e.expiresAt) this.entries.delete(k);\n }\n }\n if (this.entries.size >= this.maxEntries) {\n const oldest = this.entries.keys().next();\n if (oldest.done !== true) this.entries.delete(oldest.value);\n }\n }\n this.entries.set(key, entry);\n }\n\n clear(prefix: string): void {\n if (prefix === '') {\n this.entries.clear();\n return;\n }\n for (const key of this.entries.keys()) {\n if (key.startsWith(prefix)) this.entries.delete(key);\n }\n }\n}\n\n/**\n * In-process LRU store on Map insertion order. Expiry is lazy; no timers.\n *\n * The version tokens of namespaces and tags live in a second LRU with the same `maxEntries`, so\n * data writes never evict them. An evicted token would be re-created with a new value, and every\n * entry of its namespace or tag would then read as a miss.\n */\nexport class MemoryStore implements CacheStore {\n private readonly data: Partition;\n private readonly tokens: Partition;\n private reservedPrefixes: readonly string[] = [];\n\n constructor(options: MemoryStoreOptions = {}) {\n const max = options.maxEntries ?? DEFAULT_MAX_ENTRIES;\n if (!Number.isInteger(max) || max < 1) {\n throw new CacheConfigError(`maxEntries must be an integer >= 1, got ${String(max)}`);\n }\n this.data = new Partition(max);\n this.tokens = new Partition(max);\n }\n\n /** The data entries in LRU order, oldest first. */\n private get entries(): Map<string, Entry> {\n return this.data.entries;\n }\n\n /**\n * @internal Called by the engine with the token key prefixes of its `prefix`\n * (`<prefix>:__version__:` and `<prefix>:__tag__:`). Keys under them go to the token LRU, and\n * entries already stored under them move there.\n */\n reserveKeyPrefixes(prefixes: readonly string[]): void {\n const added = prefixes.filter((p) => p !== '' && !this.reservedPrefixes.includes(p));\n if (added.length === 0) return;\n this.reservedPrefixes = [...this.reservedPrefixes, ...new Set(added)];\n for (const [key, entry] of this.data.entries) {\n if (added.some((p) => key.startsWith(p))) {\n this.data.entries.delete(key);\n this.tokens.write(key, entry);\n }\n }\n }\n\n private partitionOf(key: string): Partition {\n for (const prefix of this.reservedPrefixes) {\n if (key.startsWith(prefix)) return this.tokens;\n }\n return this.data;\n }\n\n ping(): Promise<void> {\n return Promise.resolve();\n }\n\n get(key: string): Promise<string | undefined> {\n return Promise.resolve(this.partitionOf(key).read(key, undefined));\n }\n\n /** Reads the entry and resets its TTL to `ttlMs`; a live hit also becomes most recently used. */\n getAndTouch(key: string, ttlMs: number): Promise<string | undefined> {\n return Promise.resolve(this.partitionOf(key).read(key, ttlMs));\n }\n\n set(key: string, value: string, ttlMs: number): Promise<void> {\n this.partitionOf(key).write(key, { value, expiresAt: Date.now() + ttlMs });\n return Promise.resolve();\n }\n\n getMany(keys: readonly string[]): Promise<(string | undefined)[]> {\n return Promise.resolve(keys.map((key) => this.partitionOf(key).read(key, undefined)));\n }\n\n /** Writes every entry in one synchronous step, so no other task can interleave between them. */\n setMany(entries: readonly { key: string; value: string; ttlMs: number }[]): Promise<void> {\n for (const { key, value, ttlMs } of entries) void this.set(key, value, ttlMs);\n return Promise.resolve();\n }\n\n delete(keys: readonly string[]): Promise<void> {\n for (const key of keys) this.partitionOf(key).entries.delete(key);\n return Promise.resolve();\n }\n\n clear(prefix: string): Promise<void> {\n this.data.clear(prefix);\n this.tokens.clear(prefix);\n return Promise.resolve();\n }\n}\n\n/** An in-process LRU store; the default store when `CacheModule` gets no `stores`. */\nexport function memoryStore(options?: MemoryStoreOptions): MemoryStore {\n return new MemoryStore(options);\n}\n","import type { BreakerState, CacheEventSink } from '../core/events.js';\nimport { CacheConfigError } from '../errors.js';\nimport type {\n CacheStore,\n InvalidationBus,\n LockHandle,\n LockProvider,\n} from '../stores/cache-store.interface.js';\n\n/** Options of `circuitBreakerStore`. */\nexport interface CircuitBreakerStoreOptions {\n /** Consecutive failures that open the circuit. Integer >= 1; defaults to 5. */\n failureThreshold?: number;\n /** How long the circuit stays open before a probe is allowed, in ms. Defaults to 10_000. */\n openDuration?: number;\n /**\n * Per-operation timeout in ms; a timeout counts as a failure. Does not apply to `clear`.\n * Defaults to 500.\n */\n timeout?: number;\n}\n\nconst DEFAULT_FAILURE_THRESHOLD = 5;\nconst DEFAULT_OPEN_DURATION = 10_000;\nconst DEFAULT_TIMEOUT = 500;\n/** Largest delay `setTimeout` accepts; anything above overflows to 1 ms. */\nconst MAX_TIMER_DELAY = 2_147_483_647;\n\n/** Rejection of an operation that the circuit breaker did not pass to the store. */\nexport class CircuitOpenError extends Error {\n constructor(message = 'Cache store circuit is open') {\n super(message);\n this.name = 'CircuitOpenError';\n }\n\n /**\n * The ESM and CommonJS builds each define this class, so `instanceof` also accepts any `Error`\n * named `CircuitOpenError`. Subclasses keep the normal prototype check.\n */\n static override [Symbol.hasInstance](value: unknown): boolean {\n if (Function.prototype[Symbol.hasInstance].call(this, value)) return true;\n return this === CircuitOpenError && value instanceof Error && value.name === 'CircuitOpenError';\n }\n}\n\nfunction positiveNumber(name: string, value: number | undefined, fallback: number): number {\n if (value === undefined) return fallback;\n if (\n typeof value !== 'number' ||\n !Number.isFinite(value) ||\n value <= 0 ||\n value > MAX_TIMER_DELAY\n ) {\n throw new CacheConfigError(\n `Invalid circuitBreakerStore option ${name}: ${String(value)} (must be a finite number > 0 and <= ${String(MAX_TIMER_DELAY)})`,\n );\n }\n return value;\n}\n\nfunction positiveInteger(name: string, value: number | undefined, fallback: number): number {\n if (value === undefined) return fallback;\n if (typeof value !== 'number' || !Number.isInteger(value) || value < 1) {\n throw new CacheConfigError(\n `Invalid circuitBreakerStore option ${name}: ${String(value)} (must be an integer >= 1)`,\n );\n }\n return value;\n}\n\n/**\n * Wraps a store with a circuit breaker (spec 0.2, 4.6). `get`, `set`, `delete`, `clear`,\n * `getAndTouch`, `getMany`, `setMany`, `getStrict`, `setStrict`, `ping`, `lock.acquire` and\n * `LockHandle.release` are guarded: each races a timeout, except `clear`. `clear` runs only\n * while the circuit is closed (open or half-open it rejects with `CircuitOpenError`, and it is\n * never the half-open probe); it is not bounded by `timeout`, so set a command or socket timeout\n * on the client. Its real outcome is recorded once. `failureThreshold` consecutive failures open\n * the circuit so calls reject with\n * `CircuitOpenError` without reaching the store. After `openDuration` one probe is let through.\n * `invalidation`, `bind` and `close` are forwarded unchanged.\n */\nexport class CircuitBreakerStore implements CacheStore {\n /** Present only when the inner store has `getAndTouch`. */\n declare readonly getAndTouch?: (key: string, ttlMs: number) => Promise<string | undefined>;\n /** Present only when the inner store has `getMany`; one batch counts as one outcome. */\n declare readonly getMany?: (keys: readonly string[]) => Promise<(string | undefined)[]>;\n /** Present only when the inner store has `setMany`; one batch counts as one outcome. */\n declare readonly setMany?: (\n entries: readonly { key: string; value: string; ttlMs: number }[],\n ) => Promise<void>;\n /** Present only when the inner store has `getStrict`. */\n declare readonly getStrict?: (key: string) => Promise<string | undefined>;\n /** Present only when the inner store has `setStrict`. */\n declare readonly setStrict?: (key: string, value: string, ttlMs: number) => Promise<void>;\n /** Present only when the inner store has a lock; `acquire` and `release` are guarded. */\n declare readonly lock?: LockProvider;\n /** Present only when the inner store has `ping`; guarded like every other operation. */\n declare readonly ping?: () => Promise<void>;\n /** The inner store's bus, when it has one. */\n declare readonly invalidation?: InvalidationBus;\n\n private readonly inner: CacheStore;\n private readonly failureThreshold: number;\n private readonly openDuration: number;\n private readonly timeout: number;\n private current: BreakerState = 'closed';\n private failures = 0;\n private openedAt = 0;\n /**\n * Bumped on every state change. An operation only affects the state if no change happened\n * since it was admitted, so late outcomes from an earlier state are ignored.\n */\n private generation = 0;\n private sink: CacheEventSink | undefined;\n\n constructor(inner: CacheStore, options: CircuitBreakerStoreOptions = {}) {\n this.failureThreshold = positiveInteger(\n 'failureThreshold',\n options.failureThreshold,\n DEFAULT_FAILURE_THRESHOLD,\n );\n this.openDuration = positiveNumber('openDuration', options.openDuration, DEFAULT_OPEN_DURATION);\n this.timeout = positiveNumber('timeout', options.timeout, DEFAULT_TIMEOUT);\n this.inner = inner;\n if (inner.getAndTouch !== undefined) {\n const touch = inner.getAndTouch.bind(inner);\n this.getAndTouch = (key, ttlMs) => this.guard(() => touch(key, ttlMs));\n }\n if (inner.getMany !== undefined) {\n const getMany = inner.getMany.bind(inner);\n this.getMany = (keys) => this.guard(() => getMany(keys));\n }\n if (inner.setMany !== undefined) {\n const setMany = inner.setMany.bind(inner);\n this.setMany = (entries) => this.guard(() => setMany(entries));\n }\n if (inner.getStrict !== undefined) {\n const getStrict = inner.getStrict.bind(inner);\n this.getStrict = (key) => this.guard(() => getStrict(key));\n }\n if (inner.setStrict !== undefined) {\n const setStrict = inner.setStrict.bind(inner);\n this.setStrict = (key, value, ttlMs) => this.guard(() => setStrict(key, value, ttlMs));\n }\n if (inner.lock !== undefined) {\n const lock = inner.lock;\n this.lock = {\n acquire: async (key, ttlMs) => {\n let raw: Promise<LockHandle | undefined> | undefined;\n let handle: LockHandle | undefined;\n try {\n handle = await this.guard(() => (raw = lock.acquire(key, ttlMs)));\n } catch (error) {\n // A handle that arrives after the call was rejected would hold the lock until its\n // ttl. Release it directly: unguarded, so it neither counts nor gets refused.\n raw\n ?.then(\n (late) => late?.release(),\n () => undefined,\n )\n .catch(() => undefined);\n throw error;\n }\n return handle === undefined ? undefined : this.guardHandle(handle);\n },\n };\n }\n if (inner.ping !== undefined) {\n const ping = inner.ping.bind(inner);\n this.ping = () => this.guard(() => ping());\n }\n if (inner.invalidation !== undefined) this.invalidation = inner.invalidation;\n }\n\n get state(): BreakerState {\n return this.current;\n }\n\n get(key: string): Promise<string | undefined> {\n return this.guard(() => this.inner.get(key));\n }\n\n set(key: string, value: string, ttlMs: number): Promise<void> {\n return this.guard(() => this.inner.set(key, value, ttlMs));\n }\n\n delete(keys: readonly string[]): Promise<void> {\n return this.guard(() => this.inner.delete(keys));\n }\n\n clear(prefix: string): Promise<void> {\n // Never the half-open probe: an untimed probe that hangs would pin the circuit half-open.\n if (this.current !== 'closed') return Promise.reject(new CircuitOpenError());\n // Not raced against `timeout`: a large clear legitimately runs long. Its outcome is recorded.\n return this.guard(() => this.inner.clear(prefix), false);\n }\n\n bind(sink: CacheEventSink): void {\n this.sink = sink;\n this.inner.bind?.(sink);\n }\n\n async close(): Promise<void> {\n await this.inner.close?.();\n }\n\n private guardHandle(handle: LockHandle): LockHandle {\n return { release: () => this.guard(() => handle.release()) };\n }\n\n /**\n * Admits the call or rejects it with `CircuitOpenError`, then races it against the timeout\n * (unless `timed` is false, as for `clear`). The first outcome (result, rejection or timeout)\n * settles the call and is recorded once.\n */\n private guard<T>(call: () => Promise<T>, timed = true): Promise<T> {\n if (this.current === 'half-open') return Promise.reject(new CircuitOpenError());\n if (this.current === 'open') {\n if (Date.now() - this.openedAt < this.openDuration) {\n return Promise.reject(new CircuitOpenError());\n }\n // This call becomes the single probe; half-open lasts until it settles.\n this.transition('half-open');\n }\n const admitted = this.generation;\n\n // The executor runs `call` at once and turns a synchronous throw into a rejection.\n const pending = new Promise<T>((resolve) => {\n resolve(call());\n });\n\n if (!timed) {\n return pending.then(\n (value) => {\n this.record(true, admitted);\n return value;\n },\n (error: unknown) => {\n this.record(false, admitted);\n throw error;\n },\n );\n }\n\n let settled = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timedOut = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n if (settled) return;\n settled = true;\n this.record(false, admitted);\n reject(new Error(`Cache store operation timed out after ${String(this.timeout)} ms`));\n }, this.timeout);\n timer.unref();\n });\n // Only the first outcome is recorded. After a timeout the late result is dropped, and a late\n // rejection is caught by the race below.\n const outcome = pending.then(\n (value) => {\n if (!settled) {\n settled = true;\n clearTimeout(timer);\n this.record(true, admitted);\n }\n return value;\n },\n (error: unknown) => {\n if (!settled) {\n settled = true;\n clearTimeout(timer);\n this.record(false, admitted);\n }\n throw error;\n },\n );\n return Promise.race([outcome, timedOut]);\n }\n\n private record(success: boolean, admitted: number): void {\n if (admitted !== this.generation) return;\n if (this.current === 'half-open') {\n if (success) this.reset();\n else this.open();\n return;\n }\n if (success) {\n this.failures = 0;\n return;\n }\n this.failures += 1;\n if (this.failures >= this.failureThreshold) this.open();\n }\n\n private open(): void {\n this.openedAt = Date.now();\n this.transition('open');\n }\n\n private reset(): void {\n this.failures = 0;\n this.transition('closed');\n }\n\n private transition(state: BreakerState): void {\n this.current = state;\n this.generation += 1;\n if (this.sink === undefined) return;\n try {\n this.sink.emit('breaker', { state });\n } catch {\n // a failing sink must never reach the caller\n }\n }\n}\n\n/** Wraps `store` with a circuit breaker. Throws `CacheConfigError` for invalid options. */\nexport function circuitBreakerStore(\n store: CacheStore,\n options?: CircuitBreakerStoreOptions,\n): CircuitBreakerStore {\n return new CircuitBreakerStore(store, options);\n}\n","import { CacheConfigError } from '../errors.js';\nimport type { ResolvedCacheOptions } from '../module/cache.options.js';\nimport { CircuitOpenError } from '../resilience/circuit-breaker.store.js';\n\n/** Terminus-compatible result for one indicator key. */\nexport type CacheHealthResult =\n { status: 'up'; ping?: 'unsupported' } | { status: 'down'; message: string };\n\nconst DEFAULT_TIMEOUT = 1_000;\nconst MAX_TIMEOUT = 2_147_483_647;\n\n/**\n * Probes a configured store with `ping()` and returns a result in the shape `@nestjs/terminus`\n * expects, without importing it. `check` never rejects except with `CacheConfigError` for an\n * unknown store or an invalid timeout; a failing store is reported as `down`.\n */\nexport class CacheHealthIndicator {\n /** Created by `CacheModule`; do not construct it, inject it. */\n constructor(private readonly options: ResolvedCacheOptions) {}\n\n async check<K extends string>(\n key: K,\n options: { store?: string; timeout?: number } = {},\n ): Promise<Record<K, CacheHealthResult>> {\n const name = options.store ?? 'default';\n const timeout = options.timeout ?? DEFAULT_TIMEOUT;\n const store = this.options.stores.get(name);\n if (store === undefined) {\n throw new CacheConfigError(\n `Unknown cache store \"${name}\". Configured stores: ${[...this.options.stores.keys()].join(', ')}`,\n );\n }\n if (\n typeof timeout !== 'number' ||\n !Number.isFinite(timeout) ||\n timeout < 1 ||\n timeout > MAX_TIMEOUT\n ) {\n throw new CacheConfigError(\n `Invalid timeout: ${String(timeout)}. It must be a finite number between 1 and ${String(MAX_TIMEOUT)}.`,\n );\n }\n if (store.ping === undefined) {\n return { [key]: { status: 'up', ping: 'unsupported' } } as Record<K, CacheHealthResult>;\n }\n const result = await probe(() => store.ping?.() ?? Promise.resolve(), timeout);\n return { [key]: result } as Record<K, CacheHealthResult>;\n }\n}\n\nasync function probe(ping: () => Promise<void>, timeout: number): Promise<CacheHealthResult> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timedOut = new Promise<CacheHealthResult>((resolve) => {\n timer = setTimeout(() => {\n resolve({ status: 'down', message: `timed out after ${String(timeout)} ms` });\n }, timeout);\n timer.unref();\n });\n // The executor turns a synchronous throw into a rejection. Settling to a value here also\n // handles a rejection that arrives after the timeout, so it is never unhandled.\n const pinged = new Promise<void>((resolve) => {\n resolve(ping());\n }).then(\n (): CacheHealthResult => ({ status: 'up' }),\n (error: unknown): CacheHealthResult => ({ status: 'down', message: describe(error) }),\n );\n try {\n return await Promise.race([pinged, timedOut]);\n } finally {\n clearTimeout(timer);\n }\n}\n\nfunction describe(error: unknown): string {\n if (error instanceof CircuitOpenError) return 'circuit open';\n return error instanceof Error ? error.message : String(error);\n}\n","import { DiscoveryService, DiscoveryModule } from '@nestjs/core';\nimport { Module, type DynamicModule, type Provider } from '@nestjs/common';\nimport { CacheEngine } from '../core/cache-engine.js';\nimport { CacheService } from '../core/cache.service.js';\nimport { CacheEvents } from '../core/events.js';\nimport { CacheHealthIndicator } from '../health/cache-health.indicator.js';\nimport { CacheTracing } from '../observability/cache-tracing.js';\nimport { CacheExplorer } from './cache.explorer.js';\nimport { CacheLifecycle } from './cache.lifecycle.js';\nimport { CacheLogger } from './cache.logger.js';\nimport {\n resolveOptions,\n type CacheModuleAsyncOptions,\n type CacheModuleOptions,\n type ResolvedCacheOptions,\n} from './cache.options.js';\nimport { CACHE_ENGINE, CACHE_LOGGER, CACHE_OPTIONS } from './tokens.js';\n\nfunction sharedProviders(): Provider[] {\n return [\n {\n provide: CACHE_LOGGER,\n useFactory: (options: ResolvedCacheOptions) => new CacheLogger(options.logging.level),\n inject: [CACHE_OPTIONS],\n },\n {\n provide: CacheEvents,\n useFactory: (logger: CacheLogger) =>\n new CacheEvents((error) => {\n logger.error(\n `A cache event listener threw: ${error instanceof Error ? error.message : String(error)}`,\n );\n }),\n inject: [CACHE_LOGGER],\n },\n {\n provide: CacheTracing,\n useFactory: (logger: CacheLogger) => new CacheTracing(logger),\n inject: [CACHE_LOGGER],\n },\n {\n provide: CACHE_ENGINE,\n useFactory: (options: ResolvedCacheOptions, events: CacheEvents, tracing: CacheTracing) =>\n new CacheEngine(options, events, tracing),\n inject: [CACHE_OPTIONS, CacheEvents, CacheTracing],\n },\n {\n provide: CacheService,\n useFactory: (engine: CacheEngine) => new CacheService(engine),\n inject: [CACHE_ENGINE],\n },\n {\n provide: CacheHealthIndicator,\n useFactory: (options: ResolvedCacheOptions) => new CacheHealthIndicator(options),\n inject: [CACHE_OPTIONS],\n },\n {\n provide: CacheLifecycle,\n useFactory: (options: ResolvedCacheOptions, events: CacheEvents, logger: CacheLogger) =>\n new CacheLifecycle(options, events, logger),\n inject: [CACHE_OPTIONS, CacheEvents, CACHE_LOGGER],\n },\n {\n provide: CacheExplorer,\n useFactory: (discovery: DiscoveryService, engine: CacheEngine) =>\n new CacheExplorer(discovery, engine),\n inject: [DiscoveryService, CACHE_ENGINE],\n },\n ];\n}\n\nconst EXPORTS = [\n CacheService,\n CacheEvents,\n CACHE_ENGINE,\n CacheHealthIndicator,\n CACHE_LOGGER,\n CacheTracing,\n];\n\n/**\n * The cache module: provides `CacheService`, `CacheEvents` and `CacheHealthIndicator`, and\n * wires the cache decorators of every provider. Register it once, usually with `isGlobal`.\n */\n@Module({})\nexport class CacheModule {\n /** Registers the module with options known up front. Invalid options throw `CacheConfigError`. */\n static forRoot(options: CacheModuleOptions & { isGlobal?: boolean } = {}): DynamicModule {\n const { isGlobal, ...moduleOptions } = options;\n const resolved = resolveOptions(moduleOptions);\n return {\n module: CacheModule,\n global: isGlobal ?? false,\n imports: [DiscoveryModule],\n providers: [{ provide: CACHE_OPTIONS, useValue: resolved }, ...sharedProviders()],\n exports: EXPORTS,\n };\n }\n\n /** Registers the module with options built by `useFactory`, which can inject providers. */\n static forRootAsync(options: CacheModuleAsyncOptions): DynamicModule {\n return {\n module: CacheModule,\n global: options.isGlobal ?? false,\n imports: [DiscoveryModule, ...(options.imports ?? [])],\n providers: [\n {\n provide: CACHE_OPTIONS,\n useFactory: async (...args: never[]) => resolveOptions(await options.useFactory(...args)),\n inject: options.inject ?? [],\n },\n ...sharedProviders(),\n ],\n exports: EXPORTS,\n };\n }\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { CacheOperation } from '../core/events.js';\nimport { CacheConfigError } from '../errors.js';\nimport type { CacheLogger } from '../module/cache.logger.js';\nimport type {\n CacheTracingOptions,\n SpanAttributeValue,\n SpanLike,\n SpanOptionsLike,\n TracerLike,\n} from './tracing.types.js';\n\n/** @internal The validated `CacheTracingModule` options. */\nexport interface ResolvedTracingOptions {\n tracer: TracerLike;\n recordKeys: boolean;\n}\n\n/** @internal Validates the `CacheTracingModule` options and fills the defaults. */\nexport function resolveTracingOptions(options: unknown): ResolvedTracingOptions {\n const given = (typeof options === 'object' && options !== null ? options : {}) as {\n tracer?: unknown;\n recordKeys?: unknown;\n };\n const tracer = given.tracer as Partial<TracerLike> | null | undefined;\n if (\n typeof tracer !== 'object' ||\n tracer === null ||\n typeof tracer.startActiveSpan !== 'function' ||\n typeof tracer.startSpan !== 'function'\n ) {\n throw new CacheConfigError(\n 'Invalid cacheTracing option tracer: must provide startActiveSpan and startSpan',\n );\n }\n const recordKeys = given.recordKeys ?? false;\n if (typeof recordKeys !== 'boolean') {\n throw new CacheConfigError('Invalid cacheTracing option recordKeys: must be a boolean');\n }\n return { tracer: tracer as TracerLike, recordKeys };\n}\n\n/** `SpanStatusCode.ERROR` in OpenTelemetry. */\nconst STATUS_ERROR = 2;\n\n/** The store (and namespace) a main or refresh span is about. */\ninterface TraceBase {\n store: string;\n namespace?: string;\n}\n\n/** The counters of a batch scope, set on its span when it ends (0 when none). */\ninterface BatchCounts {\n hits: number;\n stale: number;\n misses: number;\n}\n\n/** The current cache span: a main span or a `cache.refresh`, held in the `AsyncLocalStorage`. */\ninterface Scope {\n readonly span: SpanLike;\n readonly store: string;\n /** Only on a batch scope. */\n readonly batch: BatchCounts | undefined;\n /** Set once the span ended; recorders then do nothing. */\n ended: boolean;\n /** Set once the span's status is `ERROR`. */\n failed: boolean;\n /** The errors recorded on the span, so each is recorded once; created on the first one. */\n recorded: Set<unknown> | undefined;\n}\n\ninterface Enabled {\n readonly tracer: TracerLike;\n readonly recordKeys: boolean;\n readonly als: AsyncLocalStorage<Scope>;\n}\n\n/** What the traced body produced: the promise the caller gets, or a synchronous throw. */\ntype Outcome<T> = { promise: Promise<T> } | { thrown: unknown };\n\nconst NO_LOCK = { end: (): void => undefined };\n\nfunction attributesOf(base: TraceBase): Record<string, SpanAttributeValue> {\n return base.namespace === undefined\n ? { 'cache.store': base.store }\n : { 'cache.store': base.store, 'cache.namespace': base.namespace };\n}\n\n/**\n * Internal: not part of the public API. Owns the user's tracer once `CacheTracingModule`\n * registers it, and the current cache scope (an `AsyncLocalStorage`, created on registration).\n * Until then every method calls its function directly or does nothing. A throwing tracer or span\n * method is logged (as `'tracing'`) and never reaches the caller, and never runs a function twice.\n */\nexport class CacheTracing {\n private on: Enabled | undefined;\n\n /** @internal `CacheModule` builds it with its `CacheLogger`. */\n constructor(private readonly logger?: CacheLogger) {}\n\n /** Whether a tracer is registered. */\n get enabled(): boolean {\n return this.on !== undefined;\n }\n\n /** Whether `cache.key` is recorded; lets a caller skip building a key list for `key`. */\n get recordKeys(): boolean {\n return this.on?.recordKeys === true;\n }\n\n /** Registers the tracer; throws `CacheConfigError` for invalid options or a second call. */\n use(options: CacheTracingOptions): void {\n if (this.on !== undefined) {\n throw new CacheConfigError('CacheTracingModule is already registered');\n }\n const { tracer, recordKeys } = resolveTracingOptions(options);\n this.on = { tracer, recordKeys, als: new AsyncLocalStorage<Scope>() };\n }\n\n /**\n * Runs `fn` in a new active main span `name` and its own scope. A rejection (or a\n * synchronous throw) records the exception and sets `ERROR`, then reaches the caller as is.\n * A `'batch'` scope counts hits, stale hits and misses instead of setting `cache.result`, and\n * its span always gets the three counters, 0 when none.\n */\n span<T>(\n name: string,\n base: TraceBase,\n fn: () => Promise<T>,\n kind: 'single' | 'batch' = 'single',\n ): Promise<T> {\n const on = this.on;\n if (on === undefined) return fn();\n // If the tracer fails, `fn` runs untraced outside any scope, so a nested call never writes\n // onto the span of the call it runs in.\n return this.scoped(on, name, base, { attributes: attributesOf(base) }, kind, fn, () =>\n on.als.exit(fn),\n );\n }\n\n /**\n * Runs `fn` in an active child span of the current one. A rejection marks the child and the\n * current scope's span `ERROR`. Untraced outside a scope or after the scope ended.\n */\n child<T>(name: 'cache.load', fn: () => Promise<T>): Promise<T> {\n const on = this.on;\n if (on === undefined) return fn();\n const scope = on.als.getStore();\n if (scope === undefined || scope.ended) return fn();\n return this.activate(on.tracer, scope.store, name, {}, fn, (span) =>\n this.settle(span, scope.store, fn, (error) => {\n this.fail(span, scope.store, error);\n this.failScope(scope, error);\n }),\n );\n }\n\n /**\n * Runs `fn` in a new root span `cache.refresh` linked to the current scope's span (no link\n * outside a scope), in a scope of its own: a background refresh outlives its trigger. If the\n * tracer fails, `fn` runs untraced outside any scope, so it never writes to its trigger.\n */\n root<T>(base: TraceBase, fn: () => Promise<T>): Promise<T> {\n const on = this.on;\n if (on === undefined) return fn();\n const options: SpanOptionsLike = { attributes: attributesOf(base), root: true };\n const current = on.als.getStore();\n if (current !== undefined && !current.ended) {\n this.guard(base.store, () => {\n options.links = [{ context: current.span.spanContext() }];\n });\n }\n return this.scoped(on, 'cache.refresh', base, options, 'single', fn, () => on.als.exit(fn));\n }\n\n /**\n * Starts `cache.lock` under the active span, not activated. `end` is idempotent; `true` or\n * `false` sets `cache.lock.acquired`, `undefined` (the acquire failed) sets nothing.\n */\n lockSpan(): { end(acquired: boolean | undefined): void } {\n const on = this.on;\n const scope = on?.als.getStore();\n if (on === undefined || scope === undefined || scope.ended) return NO_LOCK;\n let span: SpanLike;\n try {\n span = on.tracer.startSpan('cache.lock');\n } catch (error) {\n this.report(scope.store, error);\n return NO_LOCK;\n }\n let ended = false;\n return {\n end: (acquired) => {\n if (ended) return;\n ended = true;\n if (acquired !== undefined) {\n this.guard(scope.store, () => {\n span.setAttribute('cache.lock.acquired', acquired);\n });\n }\n this.guard(scope.store, () => {\n span.end();\n });\n },\n };\n }\n\n /** A hit: `cache.result` `'hit'`/`'stale'` on a single scope, a count on a batch scope. */\n hit(stale: boolean): void {\n const scope = this.current();\n if (scope === undefined) return;\n if (scope.batch) {\n if (stale) scope.batch.stale += 1;\n else scope.batch.hits += 1;\n } else {\n this.attribute(scope, 'cache.result', stale ? 'stale' : 'hit');\n }\n }\n\n /** A miss: `cache.result = 'miss'` on a single scope, a count on a batch scope. */\n miss(): void {\n const scope = this.current();\n if (scope === undefined) return;\n if (scope.batch) {\n scope.batch.misses += 1;\n } else {\n this.attribute(scope, 'cache.result', 'miss');\n }\n }\n\n /** Sets `cache.result` (`'bypass'`: the call skipped the cache). */\n result(value: 'bypass'): void {\n const scope = this.current();\n if (scope !== undefined) this.attribute(scope, 'cache.result', value);\n }\n\n /** Sets one attribute on the current scope's span. */\n set(key: string, value: SpanAttributeValue): void {\n const scope = this.current();\n if (scope !== undefined) this.attribute(scope, key, value);\n }\n\n /** Sets `cache.key` (a full key, or a list of them) when `recordKeys` is on. */\n key(full: string | readonly string[]): void {\n if (!this.recordKeys) return;\n const scope = this.current();\n if (scope !== undefined) {\n this.attribute(scope, 'cache.key', typeof full === 'string' ? full : [...full]);\n }\n }\n\n /**\n * A failure the library swallowed: records the exception (unless the span already has it) and\n * a `cache.error` event carrying `cache.error.operation`. The status stays unset, since the\n * caller still gets a result.\n */\n error(operation: CacheOperation, error: unknown): void {\n const scope = this.current();\n if (scope === undefined) return;\n this.record(scope, error);\n this.guard(scope.store, () => {\n scope.span.addEvent('cache.error', { 'cache.error.operation': operation });\n });\n }\n\n /** The live scope, or `undefined` when tracing is off, outside a scope, or after it ended. */\n private current(): Scope | undefined {\n const scope = this.on?.als.getStore();\n return scope === undefined || scope.ended ? undefined : scope;\n }\n\n /** Starts an active span that owns a new scope (`span`, `root`). */\n private scoped<T>(\n on: Enabled,\n name: string,\n base: TraceBase,\n options: SpanOptionsLike,\n kind: 'single' | 'batch',\n fn: () => Promise<T>,\n untraced: () => Promise<T>,\n ): Promise<T> {\n return this.activate(on.tracer, base.store, name, options, untraced, (span) => {\n const scope: Scope = {\n span,\n store: base.store,\n batch: kind === 'batch' ? { hits: 0, stale: 0, misses: 0 } : undefined,\n ended: false,\n failed: false,\n recorded: undefined,\n };\n return this.settle(\n span,\n scope.store,\n () => on.als.run(scope, fn),\n (error) => {\n this.failScope(scope, error);\n },\n scope,\n );\n });\n }\n\n /**\n * Calls `tracer.startActiveSpan` with `body`. If the tracer throws before calling `body`, or\n * returns without calling it, `untraced` runs instead; if it throws after, the outcome of\n * `body` is kept. Either way the user function runs once: a callback the tracer invokes again,\n * or late (after the fallback ran), only ends its span. A synchronous throw of the user\n * function is rethrown here, not mistaken for a tracer error.\n */\n private activate<T>(\n tracer: TracerLike,\n store: string,\n name: string,\n options: SpanOptionsLike,\n untraced: () => Promise<T>,\n body: (span: SpanLike) => Outcome<T>,\n ): Promise<T> {\n const state: { invoked: boolean; outcome: Outcome<T> | undefined } = {\n invoked: false,\n outcome: undefined,\n };\n try {\n void tracer.startActiveSpan(name, options, (span: SpanLike) => {\n if (state.invoked) {\n this.guard(store, () => {\n span.end();\n });\n return undefined;\n }\n state.invoked = true;\n const outcome = body(span);\n state.outcome = outcome;\n return 'promise' in outcome ? outcome.promise : undefined;\n });\n } catch (error) {\n this.report(store, error);\n }\n const outcome = state.outcome;\n if (outcome === undefined) {\n state.invoked = true;\n return untraced();\n }\n if ('thrown' in outcome) throw outcome.thrown;\n return outcome.promise;\n }\n\n /**\n * Runs `run` and ends `span` once when it settles, on a side branch: the caller gets the\n * promise `run` returned, so tracing adds no tick, and the side branch's reactions (registered\n * first) end the span before the caller resumes. The side branch handles the rejection, which\n * still reaches the caller through the original promise. A rejection or synchronous throw\n * first calls `onError`, which records it. With a `scope`, the scope is closed (its batch\n * counters set) before the span ends.\n */\n private settle<T>(\n span: SpanLike,\n store: string,\n run: () => Promise<T>,\n onError: (error: unknown) => void,\n scope?: Scope,\n ): Outcome<T> {\n const close = (): void => {\n if (scope) this.close(scope);\n this.guard(store, () => {\n span.end();\n });\n };\n let promise: Promise<T>;\n try {\n promise = run();\n } catch (thrown) {\n onError(thrown);\n close();\n return { thrown };\n }\n promise.then(close, (error: unknown) => {\n onError(error);\n close();\n });\n return { promise };\n }\n\n /**\n * Marks the scope's span `ERROR` for an error that reaches its caller (a failed child, or the\n * call's own rejection). An error the span already has (from the child, or a swallowed one) is\n * not recorded again.\n */\n private failScope(scope: Scope, error: unknown): void {\n if (scope.ended) return;\n this.record(scope, error);\n if (scope.failed) return;\n scope.failed = true;\n this.guard(scope.store, () => {\n scope.span.setStatus({ code: STATUS_ERROR });\n });\n }\n\n /** Records `error` on the scope's span, once per error. */\n private record(scope: Scope, error: unknown): void {\n const recorded = (scope.recorded ??= new Set());\n if (recorded.has(error)) return;\n recorded.add(error);\n this.guard(scope.store, () => {\n scope.span.recordException(error);\n });\n }\n\n private fail(span: SpanLike, store: string, error: unknown): void {\n this.guard(store, () => {\n span.recordException(error);\n });\n this.guard(store, () => {\n span.setStatus({ code: STATUS_ERROR });\n });\n }\n\n /** Sets the batch counters and closes the scope; the caller ends the span. */\n private close(scope: Scope): void {\n const counts = scope.batch;\n if (counts !== undefined) {\n this.attribute(scope, 'cache.hits', counts.hits);\n this.attribute(scope, 'cache.stale', counts.stale);\n this.attribute(scope, 'cache.misses', counts.misses);\n }\n scope.ended = true;\n }\n\n private attribute(scope: Scope, key: string, value: SpanAttributeValue): void {\n this.guard(scope.store, () => {\n scope.span.setAttribute(key, value);\n });\n }\n\n /** Runs one tracer or span call; a throw is logged and never escapes. */\n private guard(store: string, call: () => void): void {\n try {\n call();\n } catch (error) {\n this.report(store, error);\n }\n }\n\n private report(store: string, error: unknown): void {\n this.logger?.storeError(store, 'tracing', error);\n }\n}\n","import type { LoadStrategyOptions } from '../decorators/options.js';\nimport type { ResolvedCacheOptions } from '../module/cache.options.js';\nimport { OWN_ENVELOPE } from '../serializers/compressed.serializer.js';\nimport { jsonSerializer } from '../serializers/json.serializer.js';\nimport type { Target } from './engine-keys.js';\nimport {\n hasTags,\n type BatchTagOption,\n type TagCheck,\n type TagOption,\n type TagStamp,\n} from './engine-tags.js';\nimport {\n hasOwnVersion,\n isEnvelope,\n isNewerEnvelope,\n unwrap,\n type CacheEnvelope,\n} from './envelope.js';\nimport type { ReportError } from './events.js';\nimport {\n classifyEnvelope,\n createStrategy,\n type ExpiryStrategy,\n} from './strategies/expiry-strategy.js';\n\n/** The write policy a loaded or put value is checked against (`writePlan`). */\nexport interface WritePolicy<T> {\n ttl?: number;\n cacheNull?: boolean;\n nullTtl?: number;\n unless?: (result: T) => boolean;\n}\n\n/** `tags` per D2: an array is known before the load, a function gets the value. */\nexport type PutOptions<T> = WritePolicy<T> & { tags?: TagOption<T> } & LoadStrategyOptions;\n\n/** `PutOptions` of a batch load: a tag function also gets each entry's key (D2). */\nexport type BatchPutOptions<T> = WritePolicy<T> & {\n tags?: BatchTagOption<T>;\n} & LoadStrategyOptions;\n\n/**\n * A read entry. `tags` is set only by a read that defers the tag check (`EngineIO.readMany`):\n * the stamp still to check, and `touched` is then the entry's store key when that read extended\n * its TTL with `getAndTouch` on a store without `getStrict` (deleted if the check finds it\n * invalid). `uncertain` marks a tagged\n * entry whose tag tokens could not be read (spec 3.2 step 4): a miss loaded without writing.\n */\nexport type Lookup =\n | { found: true; value: unknown; stale: boolean; tags?: TagStamp; touched?: string }\n | { found: false; uncertain?: true };\n\n/** Checks the stamp of a read entry against the current tag tokens (`EngineTags.verify`). */\nexport type VerifyStamp = (stamp: TagStamp) => Promise<TagCheck>;\n\n/** Whether `lookup` is a miss because its tag tokens could not be read: load, do not write. */\nexport function uncertain(lookup: Lookup): boolean {\n return !lookup.found && lookup.uncertain === true;\n}\n\n/** How a value is written: with a strategy and ttl, or not at all (`empty`: uncached null). */\nexport type WritePlan = { strategy: ExpiryStrategy; ttl: number } | 'skip' | 'empty';\n\n/** What the envelope functions take from the engine: its options, error reporting and ttl. */\nexport interface EnvelopeContext {\n readonly options: ResolvedCacheOptions;\n readonly reportError: ReportError;\n /** `EngineIO.ttlFor`. */\n readonly ttlFor: (strategy: ExpiryStrategy, ttl: number) => number;\n}\n\n/** Empty values always use `fixed`: it is the strategy that keeps the `nil` marker. */\nexport const EMPTY_STRATEGY = createStrategy();\n\nexport function toIntegerMs(ms: number): number {\n return Math.max(1, Math.round(ms));\n}\n\n/** A stale entry is served only under swr; any other reader has a loader and reloads now. */\nexport function servable(\n lookup: Lookup,\n strategy: ExpiryStrategy,\n): lookup is Extract<Lookup, { found: true }> {\n return lookup.found && (!lookup.stale || strategy.kind === 'swr');\n}\n\nexport function isEmpty(value: unknown): value is null | undefined {\n return value === null || value === undefined;\n}\n\n/**\n * Classifies a raw string read from `key`. `touched` tells whether the read reset the\n * entry's TTL; `reSetTtl` is set when a touching read had to use `get` and must re-set.\n * A tagged entry is checked with `verify` before any re-set; without `verify` its stamp is\n * returned in `tags` for the caller to check. An untagged entry adds no await (the 0.6 path).\n */\nexport async function decode(\n ctx: EnvelopeContext,\n { name, store }: Target,\n key: string,\n raw: string | undefined,\n strategy: ExpiryStrategy,\n touched: boolean,\n reSetTtl: number | undefined,\n verify?: VerifyStamp,\n): Promise<Lookup> {\n if (raw === undefined) return { found: false };\n let envelope: CacheEnvelope;\n let decoded: { value: unknown } | undefined;\n try {\n const candidate: unknown = ctx.options.serializer.deserialize(raw);\n decoded = { value: candidate };\n if (!isEnvelope(candidate)) throw new TypeError('Deserialized value is not a cache envelope');\n envelope = candidate;\n } catch (error) {\n ctx.reportError(name, 'deserialize', error);\n // Keys can name entries this library did not write (a lock token, another app's key on\n // a shared Redis): only an entry that looks like one of our envelopes is deleted.\n if (ownEnvelope(ctx, raw, decoded)) {\n try {\n await store.delete([key]);\n } catch {\n // cleanup is best effort; the failure is already reported\n }\n }\n return { found: false };\n }\n const now = Date.now();\n const state = strategy.classify(envelope, now);\n if (state === 'expired') {\n // The store TTL would keep the entry alive when only the strategy expired it (sliding\n // maxTtl), or when this read just touched it. A non-touching read of an entry past its\n // own expiresAt is left for the store to drop, as in 0.1: no delete command is added.\n if (touched || classifyEnvelope(envelope, now) !== 'expired') {\n try {\n await store.delete([key]);\n } catch {\n // cleanup is best effort; the read is a miss either way\n }\n }\n return { found: false };\n }\n const { tags } = envelope;\n const deferred = hasTags(tags) && verify === undefined ? tags : undefined;\n // `getAndTouch` extended the entry's TTL before its tags could be checked. A store with\n // `getStrict` (tiered) may answer token reads from a local tier that lags, so a mismatch\n // there is never grounds to delete (T4-F): such an entry is a plain miss.\n const extended = touched && reSetTtl === undefined && store.getStrict === undefined;\n if (hasTags(tags) && verify !== undefined) {\n const check = await verify(tags);\n // A tag miss leaves the entry in the store: the next write replaces it (spec 3.2). Only an\n // entry this read just extended, and that a store read confirmed invalid, is deleted (spec\n // 3.3, T4-C); an `unconfirmed` miss may rest on this instance's out-of-date tokens.\n if (check === 'uncertain') return { found: false, uncertain: true };\n if (check !== 'valid') {\n // Not compare-and-delete: an entry rewritten since this read is removed too. That costs\n // one extra miss, never stale data.\n if (check === 'invalid' && extended) await deleteInvalid(ctx, { name, store }, [key]);\n return { found: false };\n }\n }\n // Only a touching reader re-sets, and only a fresh entry: an expired one returned above, so\n // maxTtl still bounds a sliding entry, and a stale one is reloaded (getOrSet) or only read\n // (get) by a reader that is not swr. Not atomic.\n if (reSetTtl !== undefined && state === 'fresh') {\n try {\n await store.set(key, raw, reSetTtl);\n } catch (error) {\n ctx.reportError(name, 'set', error);\n }\n }\n const lookup: Lookup = { found: true, value: unwrap(envelope), stale: state === 'stale' };\n if (deferred !== undefined) {\n lookup.tags = deferred;\n if (extended) lookup.touched = key;\n }\n return lookup;\n}\n\n/**\n * Deletes entries a tag check found invalid after a `getAndTouch` read extended them (spec\n * 3.3). Best effort: a failure is one `delete` error, never the caller's.\n */\nexport async function deleteInvalid(\n ctx: EnvelopeContext,\n { name, store }: Target,\n keys: readonly string[],\n): Promise<void> {\n try {\n await store.delete(keys);\n } catch (error) {\n ctx.reportError(name, 'delete', error);\n }\n}\n\n/**\n * Whether an unreadable entry was written by this library and may be deleted: an envelope of\n * ours that this version cannot read and that is not from a newer version, i.e. an object with\n * an own `v` unless that `v` is a finite number above 1 (such an entry is kept).\n * `decoded` is what the serializer returned, or `undefined` when it threw. The built-in JSON\n * serializer validates the envelope itself, so for it the raw JSON is inspected;\n * `compressedSerializer` over it carries an `OWN_ENVELOPE` check that does the same behind the\n * compression prefix (`undefined`, so no delete, when it cannot decompress). A throwing custom\n * serializer never leads to a delete. Never throws: a value that cannot even be inspected (a\n * revoked Proxy) is not ours.\n */\nfunction ownEnvelope(\n ctx: EnvelopeContext,\n raw: string,\n decoded: { value: unknown } | undefined,\n): boolean {\n try {\n if (decoded !== undefined) return isDeletable(decoded.value);\n const { serializer } = ctx.options;\n if (serializer === jsonSerializer) return isDeletable(JSON.parse(raw));\n const check: unknown = (serializer as Partial<Record<typeof OWN_ENVELOPE, unknown>>)[\n OWN_ENVELOPE\n ];\n return typeof check === 'function' && (check as (raw: string) => unknown)(raw) === true;\n } catch {\n return false;\n }\n}\n\n/** Ours and not newer: a newer envelope is a miss that stays in the store (D-01). */\nfunction isDeletable(value: unknown): boolean {\n return hasOwnVersion(value) && !isNewerEnvelope(value);\n}\n\n/** `envelope` with the `tags` field of `stamp`; an absent or empty stamp adds nothing. */\nexport function stamped(envelope: CacheEnvelope, stamp: TagStamp | undefined): CacheEnvelope {\n return hasTags(stamp) ? { ...envelope, tags: stamp } : envelope;\n}\n\n/** The `unless`/`cacheNull` policy of a value; a throwing `unless` is a `set` error. */\nexport function writePlan<T>(\n ctx: EnvelopeContext,\n target: Target,\n value: T,\n options: WritePolicy<T>,\n strategy: ExpiryStrategy,\n): WritePlan {\n try {\n if (options.unless?.(value) === true) return 'skip';\n } catch (error) {\n ctx.reportError(target.name, 'set', error);\n return 'skip';\n }\n if (isEmpty(value)) {\n if (!(options.cacheNull ?? ctx.options.defaults.cacheNull)) return 'empty';\n const nullTtl = toIntegerMs(options.nullTtl ?? ctx.options.defaults.nullTtl);\n return { strategy: EMPTY_STRATEGY, ttl: nullTtl };\n }\n return { strategy, ttl: ctx.ttlFor(strategy, options.ttl ?? ctx.options.defaults.ttl) };\n}\n","import type { ResolvedCacheOptions } from '../module/cache.options.js';\nimport type { CacheStore } from '../stores/cache-store.interface.js';\nimport type { ReportError } from './events.js';\nimport { fullKey, lockKey } from './key-builder.js';\nimport type { NamespaceVersions } from './namespace-versions.js';\n\nexport interface Target {\n name: string;\n store: CacheStore;\n}\n\n/** The data key and the lock key of one entry, carrying the namespace version if any. */\nexport interface ResolvedKey {\n full: string;\n lock: string;\n}\n\n/** Key resolution: the data and lock keys of an entry, with the namespace version if any. */\nexport class EngineKeys {\n constructor(\n private readonly options: ResolvedCacheOptions,\n private readonly versions: NamespaceVersions,\n private readonly reportError: ReportError,\n ) {}\n\n /**\n * The keys of `ref` in `target`. A namespace that is not versioned resolves synchronously, so\n * callers await only a promise and the 0.3 path gains no await. A versioned namespace reads\n * its token; on a failure it reports one `version` error and falls back to the last token this\n * process knew for the namespace, or resolves `undefined` when there is none, and the caller\n * then skips the cache.\n */\n resolveKey(\n target: Target,\n ref: { namespace?: string | undefined; key: string },\n ): ResolvedKey | Promise<ResolvedKey | undefined> {\n const { namespace, key } = ref;\n if (namespace === undefined || !this.versions.isVersioned(namespace)) {\n return this.keysOf(namespace, key);\n }\n return this.versionedNamespace(target, namespace).then((resolved) =>\n resolved === undefined ? undefined : this.keysOf(resolved, key),\n );\n }\n\n /**\n * The keys of every `keys` entry in one namespace, in input order. As `resolveKey`, but one\n * version read serves the whole batch. A failed read reports one `version` error and falls back\n * as `resolveKey` does, or resolves `undefined`.\n */\n resolveKeys(\n target: Target,\n namespace: string | undefined,\n keys: readonly string[],\n ): ResolvedKey[] | Promise<ResolvedKey[] | undefined> {\n if (namespace === undefined || !this.versions.isVersioned(namespace)) {\n return keys.map((key) => this.keysOf(namespace, key));\n }\n return this.versionedNamespace(target, namespace).then((resolved) =>\n resolved === undefined ? undefined : keys.map((key) => this.keysOf(resolved, key)),\n );\n }\n\n private keysOf(namespace: string | undefined, key: string): ResolvedKey {\n const { prefix } = this.options;\n return { full: fullKey(prefix, namespace, key), lock: lockKey(prefix, namespace, key) };\n }\n\n /**\n * `<ns>@<v>`. When the version read fails it reports one `version` error. A store with\n * `getStrict` then uses the last token this process knew (even past `cacheTtl`) for this call\n * only, so the next call reads the store again; `undefined` when no token was ever known, and\n * always for a store without `getStrict`. Never rejects. Deletes do not use it.\n */\n private async versionedNamespace(target: Target, namespace: string): Promise<string | undefined> {\n try {\n return `${namespace}@${await this.versions.current(target, namespace)}`;\n } catch (error) {\n this.reportError(target.name, 'version', error);\n // Only stores with getStrict (tiered, or a breaker over one) opt into the fallback.\n if (target.store.getStrict === undefined) return undefined;\n const known = this.versions.cached(target, namespace);\n return known === undefined ? undefined : `${namespace}@${known}`;\n }\n }\n\n /**\n * The `<ns>@<v>` forms a delete removes: the token read fresh from the store, so an entry\n * another instance wrote after its clear is deleted within `cacheTtl` too, plus any other\n * token this instance had cached (its own writes may sit under it). One version read for the\n * whole call; `undefined` after reporting a `version` error.\n */\n async deleteNamespaces(target: Target, namespace: string): Promise<string[] | undefined> {\n const previous = this.versions.cached(target, namespace);\n let token: string;\n try {\n token = await this.versions.fresh(target, namespace);\n } catch (error) {\n this.reportError(target.name, 'version', error);\n return undefined;\n }\n // A bump during the read leaves its newer token cached: delete under it as well.\n const tokens = new Set([token]);\n for (const other of [previous, this.versions.cached(target, namespace)]) {\n if (other !== undefined) tokens.add(other);\n }\n return [...tokens].map((t) => `${namespace}@${t}`);\n }\n}\n","import { CacheConfigError } from '../errors.js';\nimport type { ResolvedCacheOptions } from '../module/cache.options.js';\nimport type { CacheTracing } from '../observability/cache-tracing.js';\nimport { CircuitOpenError } from '../resilience/circuit-breaker.store.js';\nimport type { CacheEventMap, CacheEvents, CacheOperation, ReportError } from './events.js';\nimport {\n decode,\n deleteInvalid,\n stamped,\n toIntegerMs,\n writePlan,\n type BatchPutOptions,\n type EnvelopeContext,\n type Lookup,\n type PutOptions,\n} from './engine-envelope.js';\nimport { EngineKeys, type ResolvedKey, type Target } from './engine-keys.js';\nimport { EngineTags, type Stamping, type TagCheck, type TagStamp } from './engine-tags.js';\nimport { fullKey, namespacePrefix } from './key-builder.js';\nimport type { NamespaceVersions } from './namespace-versions.js';\nimport type { ExpiryStrategy } from './strategies/expiry-strategy.js';\nimport type { VersionTokens } from './version-tokens.js';\n\nexport interface KeyRef {\n store?: string;\n namespace?: string;\n key: string;\n}\n\nexport type { BatchPutOptions, Lookup, PutOptions } from './engine-envelope.js';\nexport { EMPTY_STRATEGY, isEmpty, servable, toIntegerMs, uncertain } from './engine-envelope.js';\nexport type { ResolvedKey, Target } from './engine-keys.js';\n\n/** One entry of a batch: its plain key (in `ref`, for events) and its resolved keys. */\nexport interface BatchItem {\n ref: KeyRef;\n key: ResolvedKey;\n}\n\n/** A batch entry ready to write; `ttl` is an integer >= 1, already jittered if needed. */\nexport interface WriteItem extends BatchItem {\n value: unknown;\n strategy: ExpiryStrategy;\n ttl: number;\n /** The entry's tag stamp; absent (or empty) for an untagged entry. */\n tags?: TagStamp;\n}\n\n/**\n * Store reads and writes plus the events they emit, shared by the engine facade and the\n * load orchestration. Nothing here validates options; the facade does that first.\n */\nexport class EngineIO {\n private readonly resolver: EngineKeys;\n private readonly envelope: EnvelopeContext;\n /** Tag stamps for writes; their failures are reported through `reportError`. */\n readonly tags: EngineTags;\n\n constructor(\n private readonly options: ResolvedCacheOptions,\n private readonly events: CacheEvents,\n private readonly versions: NamespaceVersions,\n tokens: VersionTokens,\n private readonly tracing: CacheTracing,\n ) {\n const reportError: ReportError = (store, operation, error) => {\n this.reportError(store, operation, error);\n };\n this.resolver = new EngineKeys(options, versions, reportError);\n this.tags = new EngineTags(tokens, reportError);\n this.envelope = {\n options,\n reportError,\n ttlFor: (strategy, ttl) => this.ttlFor(strategy, ttl),\n };\n }\n\n /** The keys of `ref` in `target`; see `EngineKeys.resolveKey`. */\n resolveKey(\n target: Target,\n ref: { namespace?: string | undefined; key: string },\n ): ResolvedKey | Promise<ResolvedKey | undefined> {\n return this.resolver.resolveKey(target, ref);\n }\n\n /** The keys of every `keys` entry in one namespace; see `EngineKeys.resolveKeys`. */\n resolveKeys(\n target: Target,\n namespace: string | undefined,\n keys: readonly string[],\n ): ResolvedKey[] | Promise<ResolvedKey[] | undefined> {\n return this.resolver.resolveKeys(target, namespace, keys);\n }\n\n resolve(name: string | undefined): Target {\n const resolved = name ?? 'default';\n const store = this.options.stores.get(resolved);\n if (store === undefined) {\n throw new CacheConfigError(\n `Unknown cache store \"${resolved}\". Configured stores: ${[...this.options.stores.keys()].join(', ')}`,\n );\n }\n return { name: resolved, store };\n }\n\n reportError(store: string | undefined, operation: CacheOperation, error: unknown): void {\n // An open circuit means the store is temporarily absent, not broken: no `error` event.\n if (error instanceof CircuitOpenError) return;\n this.events.emit('error', { store: store ?? 'default', operation, error });\n // Swallowed: recorded on the current cache span, if any, with the status left unset.\n this.tracing.error(operation, error);\n }\n\n /**\n * Reads and classifies an entry without emitting `hit`/`miss`; callers decide which one\n * applies. `ttl` is the effective ttl, used as the sliding touch ttl.\n */\n read(target: Target, key: ResolvedKey, strategy: ExpiryStrategy, ttl: number): Promise<Lookup> {\n return this.readEntry(target, key, strategy, ttl, true);\n }\n\n /**\n * `read`; with `verify` a tagged entry is checked against the current tag tokens, without it\n * the stamp is left in the lookup's `tags` (a batch checks them all at once).\n */\n private async readEntry(\n target: Target,\n { full: key }: ResolvedKey,\n strategy: ExpiryStrategy,\n ttl: number,\n verify: boolean,\n ): Promise<Lookup> {\n const { name, store } = target;\n const plan = strategy.read(toIntegerMs(ttl));\n const touchTtl = plan.touch ? plan.touchTtl : undefined;\n // Without getAndTouch, a touching read is a get, then a re-set of the same string.\n const reSet = touchTtl !== undefined && store.getAndTouch === undefined;\n let raw: string | undefined;\n try {\n raw =\n touchTtl !== undefined && store.getAndTouch !== undefined\n ? await store.getAndTouch(key, touchTtl)\n : await store.get(key);\n } catch (error) {\n this.reportError(name, 'get', error);\n return { found: false };\n }\n return decode(\n this.envelope,\n target,\n key,\n raw,\n strategy,\n plan.touch,\n reSet ? touchTtl : undefined,\n verify ? (stamp) => this.verifyOne(target, stamp) : undefined,\n );\n }\n\n private async verifyOne(target: Target, stamp: TagStamp): Promise<TagCheck> {\n const [check] = await this.tags.verify(target, [stamp]);\n return check ?? 'uncertain';\n }\n\n /**\n * Reads several entries, in input order, as `read` would, without emitting `hit`/`miss`. A\n * touching strategy (sliding) reads each key on its own, so each entry's window is reset;\n * any other reads them all with one `store.getMany` (one `get` per key without it). A failing\n * batch read is one `get` error and misses. Tag stamps are not checked here: a tagged entry\n * keeps its stamp in `tags`, and the caller passes the lookups to `checkStamps`.\n */\n async readMany(\n target: Target,\n keys: readonly ResolvedKey[],\n strategy: ExpiryStrategy,\n ttl: number,\n ): Promise<Lookup[]> {\n if (strategy.read(toIntegerMs(ttl)).touch) {\n return Promise.all(keys.map((key) => this.readEntry(target, key, strategy, ttl, false)));\n }\n const raws = await this.fetchMany(\n target,\n keys.map((key) => key.full),\n );\n return Promise.all(\n keys.map((key, i) =>\n decode(this.envelope, target, key.full, raws[i], strategy, false, undefined),\n ),\n );\n }\n\n /**\n * `lookups` from `readMany` with their tag stamps checked: one `currentMany` for all their tags\n * and at most one `version` error (spec 3.2). The store-confirmed invalid entries a\n * `getAndTouch` read extended are deleted with one `store.delete` (spec 3.3, T4-C); an\n * `unconfirmed` one is a plain miss. Synchronous when no entry is tagged, so an\n * untagged batch gains no await.\n */\n checkStamps(target: Target, lookups: readonly Lookup[]): readonly Lookup[] | Promise<Lookup[]> {\n const stamps = lookups.flatMap((lookup) =>\n lookup.found && lookup.tags !== undefined ? [lookup.tags] : [],\n );\n if (stamps.length === 0) return lookups;\n return this.tags.verify(target, stamps).then((checks) => {\n let next = 0;\n const extended: string[] = [];\n const checked = lookups.map((lookup): Lookup => {\n if (!lookup.found || lookup.tags === undefined) return lookup;\n const check = checks[next++];\n if (check === 'valid') return { found: true, value: lookup.value, stale: lookup.stale };\n // Only a store-confirmed mismatch deletes (T4-C); `unconfirmed` is a plain miss.\n if (check === 'invalid' && lookup.touched !== undefined) extended.push(lookup.touched);\n return check === 'invalid' || check === 'unconfirmed'\n ? { found: false }\n : { found: false, uncertain: true };\n });\n if (extended.length === 0) return checked;\n // Not compare-and-delete: an entry rewritten since this read is removed too (one extra\n // miss, never stale data).\n return deleteInvalid(this.envelope, target, extended).then(() => checked);\n });\n }\n\n /** The raw strings of `keys`; a failure is one `get` error, its keys then read as misses. */\n private async fetchMany(\n { name, store }: Target,\n keys: readonly string[],\n ): Promise<(string | undefined)[]> {\n if (keys.length === 0) return [];\n if (store.getMany !== undefined) {\n try {\n return await store.getMany(keys);\n } catch (error) {\n this.reportError(name, 'get', error);\n return [];\n }\n }\n const settled = await Promise.allSettled(keys.map(async (key) => store.get(key)));\n const failed = settled.find((result) => result.status === 'rejected');\n if (failed !== undefined) this.reportError(name, 'get', failed.reason);\n return settled.map((result) => (result.status === 'fulfilled' ? result.value : undefined));\n }\n\n /**\n * Applies the `unless`/`cacheNull` policy, then writes with the matching strategy. `taken` is\n * the stamp of tags known before a load; without it, `options.tags` is stamped only once the\n * write is decided (a tag function gets the value). An entry without tags adds no await.\n * Resolves `true` only when the entry was written: `false` when the policy skips it or it is\n * empty without `cacheNull` (even when that deletes), its stamp is `'skip'`, or the set fails.\n */\n async store<T>(\n target: Target,\n ref: KeyRef,\n key: ResolvedKey,\n value: T,\n options: PutOptions<T>,\n strategy: ExpiryStrategy,\n deleteWhenEmpty: boolean,\n taken?: Stamping,\n ): Promise<boolean> {\n const plan = writePlan(this.envelope, target, value, options, strategy);\n if (plan === 'skip') return false;\n if (plan === 'empty') {\n // Through `delete`, so a versioned namespace reads its token fresh, as any delete does.\n if (deleteWhenEmpty) {\n await this.delete({ store: ref.store, namespace: ref.namespace }, [ref.key]);\n }\n return false;\n }\n const { tags } = options;\n const stamping =\n taken ?? (tags === undefined ? undefined : await this.tags.stampFor(target, tags, value));\n if (stamping === 'skip') return false;\n return await this.write(target, ref, key, value, plan.strategy, plan.ttl, stamping);\n }\n\n /**\n * `store` for loaded batch values, written with one `writeMany`; it never deletes. `taken` is\n * as for `store`; without it, the entries to write are stamped together (one token call).\n * Resolves the user keys written, as `writeMany` does.\n */\n async storeMany<T>(\n target: Target,\n items: readonly (BatchItem & { value: T })[],\n options: BatchPutOptions<T>,\n strategy: ExpiryStrategy,\n taken?: Stamping,\n ): Promise<ReadonlySet<string>> {\n const planned: (WriteItem & { value: T })[] = [];\n for (const item of items) {\n const plan = writePlan(this.envelope, target, item.value, options, strategy);\n if (typeof plan === 'object') planned.push({ ...item, ...plan });\n }\n let writes: readonly WriteItem[];\n if (taken === undefined) {\n writes = await this.tags.stampWrites(target, options.tags, planned);\n } else {\n writes = taken === 'skip' ? [] : planned.map((write) => ({ ...write, tags: taken }));\n }\n return await this.writeMany(target, writes);\n }\n\n /**\n * `ttl` is an integer >= 1, already jittered when the strategy asks for it. `tags` is the\n * entry's stamp, written as the envelope's `tags` unless absent or empty. Resolves whether the\n * entry was written (`false` after a `set` error).\n */\n async write(\n { name, store }: Target,\n ref: KeyRef,\n { full: key }: ResolvedKey,\n value: unknown,\n strategy: ExpiryStrategy,\n ttl: number,\n tags?: TagStamp,\n ): Promise<boolean> {\n let storeTtl: number;\n try {\n const wrapped = strategy.wrap(value, Date.now(), ttl);\n storeTtl = wrapped.storeTtl;\n const envelope = stamped(wrapped.envelope, tags);\n await store.set(key, this.options.serializer.serialize(envelope), storeTtl);\n } catch (error) {\n this.reportError(name, 'set', error);\n return false;\n }\n this.events.emit('set', { store: name, namespace: ref.namespace, key: ref.key, ttl: storeTtl });\n return true;\n }\n\n /**\n * Writes several entries with one `store.setMany` (one `set` per entry without it), each as\n * `write` would, emitting `set` per written entry. A value that cannot be serialized is a\n * `set` error and is left out; a failing batch write is one `set` error. Keys are unique.\n * Resolves the user keys (`ref.key`) written: those a `set` event was emitted for.\n */\n async writeMany(\n { name, store }: Target,\n items: readonly WriteItem[],\n ): Promise<ReadonlySet<string>> {\n // User keys (`ref.key`), not store keys: a batch is one namespace and loads by user key.\n const done = new Set<string>();\n const entries: { key: string; value: string; ttlMs: number }[] = [];\n const written: { ref: KeyRef; ttl: number }[] = [];\n for (const { ref, key, value, strategy, ttl, tags } of items) {\n try {\n const wrapped = strategy.wrap(value, Date.now(), ttl);\n const serialized = this.options.serializer.serialize(stamped(wrapped.envelope, tags));\n entries.push({ key: key.full, value: serialized, ttlMs: wrapped.storeTtl });\n written.push({ ref, ttl: wrapped.storeTtl });\n } catch (error) {\n this.reportError(name, 'set', error);\n }\n }\n if (entries.length === 0) return done;\n let stored: boolean[];\n if (store.setMany !== undefined) {\n try {\n await store.setMany(entries);\n } catch (error) {\n this.reportError(name, 'set', error);\n return done;\n }\n stored = entries.map(() => true);\n } else {\n const settled = await Promise.allSettled(\n entries.map(async (e) => store.set(e.key, e.value, e.ttlMs)),\n );\n const failed = settled.find((result) => result.status === 'rejected');\n if (failed !== undefined) this.reportError(name, 'set', failed.reason);\n stored = settled.map((result) => result.status === 'fulfilled');\n }\n written.forEach(({ ref, ttl }, i) => {\n if (stored[i] !== true) return;\n done.add(ref.key);\n this.events.emit('set', { store: name, namespace: ref.namespace, key: ref.key, ttl });\n });\n return done;\n }\n\n /** `recordKeys` sets the full keys deleted as `cache.key` (the `delete` call's own span). */\n async delete(\n scope: { store?: string | undefined; namespace?: string | undefined },\n keys: readonly string[],\n recordKeys = false,\n ): Promise<void> {\n const target = this.resolve(scope.store);\n if (keys.length === 0) return;\n const { name, store } = target;\n const { namespace } = scope;\n let namespaces: readonly (string | undefined)[] = [namespace];\n if (namespace !== undefined && this.versions.isVersioned(namespace)) {\n const versioned = await this.resolver.deleteNamespaces(target, namespace);\n if (versioned === undefined) return;\n namespaces = versioned;\n }\n const fullKeys = namespaces.flatMap((ns) =>\n keys.map((key) => fullKey(this.options.prefix, ns, key)),\n );\n if (recordKeys) this.tracing.key(fullKeys);\n try {\n await store.delete(fullKeys);\n } catch (error) {\n this.reportError(name, 'delete', error);\n return;\n }\n this.events.emit('delete', { store: name, namespace, keys });\n }\n\n /** A versioned namespace gets a new token instead of a scan; its old keys expire by TTL. */\n async clear(storeName: string | undefined, namespace: string): Promise<void> {\n const target = this.resolve(storeName);\n const { name, store } = target;\n if (this.versions.isVersioned(namespace)) {\n try {\n await this.versions.bump(target, namespace);\n } catch (error) {\n this.reportError(name, 'version', error);\n return;\n }\n } else {\n try {\n await store.clear(namespacePrefix(this.options.prefix, namespace));\n } catch (error) {\n this.reportError(name, 'clear', error);\n return;\n }\n }\n this.events.emit('clear', { store: name, namespace });\n }\n\n /** `keys` is set by a batch load only, so a single-key `load` keeps its 0.3 shape. */\n emitLoad(\n store: string,\n ref: KeyRef,\n started: number,\n success: boolean,\n keys?: readonly string[],\n ): void {\n const payload: CacheEventMap['load'] = {\n store,\n namespace: ref.namespace,\n key: ref.key,\n durationMs: Date.now() - started,\n success,\n };\n if (keys !== undefined) payload.keys = keys;\n this.events.emit('load', payload);\n }\n\n emitLock(store: string, ref: KeyRef, waitedMs: number, acquired: boolean): void {\n this.events.emit('lock', { store, namespace: ref.namespace, key: ref.key, waitedMs, acquired });\n }\n\n hit(store: string, ref: KeyRef, stale: boolean): void {\n this.events.emit('hit', { store, namespace: ref.namespace, key: ref.key, stale });\n this.tracing.hit(stale);\n }\n\n miss(store: string, ref: KeyRef): void {\n this.events.emit('miss', { store, namespace: ref.namespace, key: ref.key });\n this.tracing.miss();\n }\n\n ttlFor(strategy: ExpiryStrategy, ttl: number): number {\n return strategy.jittered ? this.jittered(ttl) : toIntegerMs(ttl);\n }\n\n private jittered(ttl: number): number {\n const { jitter } = this.options.defaults;\n return toIntegerMs(ttl * (1 + (Math.random() * 2 - 1) * jitter));\n }\n}\n","import type { ResolvedCacheOptions } from '../module/cache.options.js';\nimport type { CacheTracing } from '../observability/cache-tracing.js';\nimport {\n EMPTY_STRATEGY,\n isEmpty,\n servable,\n uncertain,\n type BatchPutOptions,\n} from './engine-envelope.js';\nimport type { BatchItem, EngineIO } from './engine-io.js';\nimport type { Target } from './engine-keys.js';\nimport type { BatchTagOption } from './engine-tags.js';\nimport type { BatchPlan, EngineLoad, LoadItem } from './engine-load.js';\nimport { keyErrorOf } from './key-builder.js';\nimport type { ExpiryStrategy } from './strategies/expiry-strategy.js';\n\n/** The store and namespace a batch call works in. */\nexport interface BatchScope {\n store?: string;\n namespace?: string;\n}\n\nexport type BatchLoader<T> = (missing: string[]) => Promise<ReadonlyMap<string, T>>;\n\n/**\n * The batch calls of the engine (`getMany`, `setMany`, `getOrSetMany`), run after the facade\n * has validated their arguments and built their strategy.\n */\nexport class EngineBatch {\n constructor(\n private readonly options: ResolvedCacheOptions,\n private readonly io: EngineIO,\n private readonly load: EngineLoad,\n private readonly tracing: CacheTracing,\n ) {}\n\n /** `CacheEngine.getMany` after validation. */\n async getMany<T>(\n target: Target,\n scope: BatchScope,\n keys: readonly string[],\n strategy: ExpiryStrategy,\n ): Promise<(T | undefined)[]> {\n const items = await this.batchItems(\n target,\n scope,\n this.uniqueKeys(target, scope.namespace, keys),\n );\n if (items === undefined) return keys.map(() => undefined);\n const read = await this.io.readMany(\n target,\n items.map((item) => item.key),\n strategy,\n this.options.defaults.ttl,\n );\n // One tag check for the batch; awaited only when an entry is tagged (no 0.6 tick added).\n const checked = this.io.checkStamps(target, read);\n const lookups = checked instanceof Promise ? await checked : checked;\n const values = new Map<string, unknown>();\n items.forEach(({ ref }, i) => {\n const lookup = lookups[i];\n if (lookup?.found !== true) {\n this.io.miss(target.name, ref);\n return;\n }\n this.io.hit(target.name, ref, lookup.stale);\n values.set(ref.key, lookup.value);\n });\n return keys.map((key) => values.get(key) as T | undefined);\n }\n\n /**\n * `CacheEngine.setMany` after validation; `ttl` is the effective ttl. With `tags`, the entries\n * are stamped together (one token call); an entry whose tags fail is not written.\n */\n async setMany<T>(\n target: Target,\n scope: BatchScope,\n entries: readonly (readonly [key: string, value: T])[],\n requested: ExpiryStrategy,\n ttl: number,\n tags?: BatchTagOption<T>,\n ): Promise<void> {\n const values = new Map<string, T>();\n for (const [key, value] of entries) values.set(key, value);\n const items = await this.batchItems(\n target,\n scope,\n this.uniqueKeys(target, scope.namespace, [...values.keys()]),\n );\n if (items === undefined) return;\n const writes = items.map((item) => {\n const value = values.get(item.ref.key) as T;\n // As `set`: an empty value keeps the 0.1 ttl, but always as `fixed`.\n const strategy = isEmpty(value) ? EMPTY_STRATEGY : requested;\n return { ...item, value, strategy, ttl: this.io.ttlFor(strategy, ttl) };\n });\n await this.io.writeMany(target, await this.io.tags.stampWrites(target, tags, writes));\n }\n\n /** `CacheEngine.getOrSetMany` after validation; `ttl` is the effective ttl. */\n async getOrSetMany<T>(\n target: Target,\n scope: BatchScope,\n keys: readonly string[],\n loader: BatchLoader<T>,\n options: BatchPutOptions<T>,\n strategy: ExpiryStrategy,\n ttl: number,\n ): Promise<(T | undefined)[]> {\n const unique = this.uniqueKeys(target, scope.namespace, keys);\n const plan: BatchPlan<T> = { target, namespace: scope.namespace, loader, options, strategy };\n const items = await this.batchItems(target, scope, unique);\n const values = new Map<string, unknown>();\n if (items === undefined) {\n // A version failure skips the cache: every key is loaded and nothing is written.\n const loaded = await this.load.runLoader(plan, unique, false);\n for (const key of unique) values.set(key, loaded.get(key));\n return keys.map((key) => values.get(key) as T | undefined);\n }\n const read = await this.io.readMany(\n target,\n items.map((item) => item.key),\n strategy,\n ttl,\n );\n const checked = this.io.checkStamps(target, read);\n const lookups = checked instanceof Promise ? await checked : checked;\n const missing: LoadItem[] = [];\n const stale: BatchItem[] = [];\n items.forEach((item, i) => {\n const lookup = lookups[i] ?? { found: false };\n if (!servable(lookup, strategy)) {\n this.io.miss(target.name, item.ref);\n // Its tag tokens could not be read: loaded, but not written (spec 3.2 step 4).\n missing.push(uncertain(lookup) ? { ...item, noWrite: true } : item);\n return;\n }\n this.io.hit(target.name, item.ref, lookup.stale);\n values.set(item.ref.key, lookup.value);\n if (lookup.stale) stale.push(item);\n });\n // Both start before anything is awaited, so their flights are registered at once.\n const loading = missing.length > 0 ? this.load.onMissMany(plan, missing) : undefined;\n const refreshing =\n stale.length > 0 ? this.load.refreshMany(plan, stale, options.softTimeout) : undefined;\n if (loading !== undefined) {\n for (const [key, value] of await loading) values.set(key, value);\n }\n // Without softTimeout the refresh runs in the background, as in 0.7. With it, the stale keys\n // share one wait window, and those refreshed in time get their new values.\n if (refreshing !== undefined && options.softTimeout !== undefined) {\n for (const [key, value] of await refreshing) values.set(key, value);\n }\n return keys.map((key) => values.get(key) as T | undefined);\n }\n\n /** `keys` deduped, first occurrence first, without invalid keys (one key error per call). */\n private uniqueKeys(\n target: Target,\n namespace: string | undefined,\n keys: readonly string[],\n ): string[] {\n const unique = new Set<string>();\n let invalid: TypeError | undefined;\n for (const key of keys) {\n const error = keyErrorOf(namespace, key);\n if (error === undefined) unique.add(key);\n else invalid ??= error;\n }\n if (invalid !== undefined) this.io.reportError(target.name, 'key', invalid);\n return [...unique];\n }\n\n /**\n * The batch items of `keys` (unique, neither empty nor reserved) in `scope`, with one version\n * read for a versioned namespace; `undefined` after a version failure (already reported). With\n * `recordKeys`, their full keys are the call's `cache.key`, set without an added tick.\n */\n private async batchItems(\n target: Target,\n scope: BatchScope,\n keys: readonly string[],\n ): Promise<BatchItem[] | undefined> {\n if (keys.length === 0) return [];\n const pending = this.io.resolveKeys(target, scope.namespace, keys);\n const resolved = pending instanceof Promise ? await pending : pending;\n if (resolved === undefined) return undefined;\n const items: BatchItem[] = [];\n keys.forEach((key, i) => {\n const resolvedKey = resolved[i];\n if (resolvedKey !== undefined) items.push({ ref: { ...scope, key }, key: resolvedKey });\n });\n if (this.tracing.recordKeys) this.tracing.key(items.map((item) => item.key.full));\n return items;\n }\n}\n","import type { LockHandle, LockProvider } from '../stores/cache-store.interface.js';\n\n/** Milliseconds. `ttl` goes to the store and must already be an integer >= 1. */\nexport interface LockSettings {\n ttl: number;\n waitTimeout: number;\n retryDelay: number;\n}\n\n/** Reads the entry again without emitting `hit`/`miss`; `found` means usable by the caller. */\nexport type Reread<T> = () => Promise<{ found: true; value: T } | { found: false }>;\n\n/** Must not throw. */\nexport interface LockHooks {\n /** Called right before `acquire` (the `cache.lock` span starts here). */\n onAcquireStart?(): void;\n /** Called once: the lock was acquired, or the wait for it ended. */\n onLock(acquired: boolean, waitedMs: number): void;\n onError(error: unknown): void;\n}\n\n/** A plain `setTimeout`, not unref'd, so fake timers drive the wait. */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** Releases in `finally`; a failed release is reported and never replaces the load outcome. */\nasync function whileHolding<T>(\n handle: LockHandle,\n load: () => Promise<T>,\n hooks: LockHooks,\n): Promise<T> {\n try {\n return await load();\n } finally {\n try {\n await handle.release();\n } catch (error) {\n hooks.onError(error);\n }\n }\n}\n\n/**\n * Miss path (spec 0.2, 4.4). With the lock: load, then release. Without it: poll `reread`\n * every `retryDelay` until a value appears or `waitTimeout` passes, then load without the lock.\n * When `acquire` throws, the error is reported and the load runs without the lock.\n */\nexport async function loadWithLock<T>(\n lock: LockProvider,\n key: string,\n settings: LockSettings,\n reread: Reread<T>,\n load: () => Promise<T>,\n hooks: LockHooks,\n): Promise<{ value: T; from: 'cache' | 'load' }> {\n const started = Date.now();\n let handle: LockHandle | undefined;\n hooks.onAcquireStart?.();\n try {\n handle = await lock.acquire(key, settings.ttl);\n } catch (error) {\n hooks.onError(error);\n return { value: await load(), from: 'load' };\n }\n if (handle !== undefined) {\n hooks.onLock(true, Date.now() - started);\n return { value: await whileHolding(handle, load, hooks), from: 'load' };\n }\n for (;;) {\n // The last sleep is shortened so the wait never runs past waitTimeout.\n const remaining = settings.waitTimeout - (Date.now() - started);\n await sleep(Math.min(settings.retryDelay, Math.max(0, remaining)));\n const cached = await reread();\n const waited = Date.now() - started;\n if (cached.found) {\n hooks.onLock(false, waited);\n return { value: cached.value, from: 'cache' };\n }\n if (waited >= settings.waitTimeout) {\n hooks.onLock(false, waited);\n return { value: await load(), from: 'load' };\n }\n }\n}\n\n/**\n * Background refresh (spec 0.2, 4.3): one attempt, no wait. A held lock skips the load; a\n * failing `acquire` is reported and the load runs without the lock.\n */\nexport async function refreshWithLock(\n lock: LockProvider,\n key: string,\n ttl: number,\n load: () => Promise<void>,\n hooks: LockHooks,\n): Promise<void> {\n const started = Date.now();\n let handle: LockHandle | undefined;\n hooks.onAcquireStart?.();\n try {\n handle = await lock.acquire(key, ttl);\n } catch (error) {\n hooks.onError(error);\n await load();\n return;\n }\n hooks.onLock(handle !== undefined, Date.now() - started);\n if (handle === undefined) return;\n await whileHolding(handle, load, hooks);\n}\n","export class SingleFlight {\n private readonly inFlight = new Map<string, Promise<unknown>>();\n\n /** True only while a flight for `key` is in progress. */\n has(key: string): boolean {\n return this.inFlight.has(key);\n }\n\n /** The flight in progress for `key`, without joining or starting one. */\n current(key: string): Promise<unknown> | undefined {\n return this.inFlight.get(key);\n }\n\n run<T>(key: string, task: () => Promise<T>): Promise<T> {\n const existing = this.inFlight.get(key);\n if (existing) return existing as Promise<T>;\n\n const promise = (async () => task())();\n this.inFlight.set(key, promise);\n // Registered before any caller can attach a continuation, so the entry is\n // gone before a waiter may start a new run for the same key.\n const forget = (): void => {\n if (this.inFlight.get(key) === promise) this.inFlight.delete(key);\n };\n promise.then(forget, forget);\n return promise;\n }\n}\n","import type { ResolvedDefaults } from '../module/cache.options.js';\nimport type { CacheTracing } from '../observability/cache-tracing.js';\nimport type { LockProvider } from '../stores/cache-store.interface.js';\nimport {\n isEmpty,\n servable,\n toIntegerMs,\n type BatchItem,\n type BatchPutOptions,\n type EngineIO,\n type KeyRef,\n type PutOptions,\n type ResolvedKey,\n type Target,\n} from './engine-io.js';\nimport { knownTags } from './engine-tags.js';\nimport { loadWithLock, refreshWithLock, type LockHooks, type LockSettings } from './lock-runner.js';\nimport { SingleFlight } from './single-flight.js';\nimport type { ExpiryStrategy } from './strategies/expiry-strategy.js';\n\n/** Everything a load needs once the facade has validated the call. */\nexport interface LoadPlan<T> {\n target: Target;\n ref: KeyRef;\n /** Resolved once by the facade, so the load, its lock and its write use one version. */\n key: ResolvedKey;\n loader: () => Promise<T>;\n options: PutOptions<T>;\n strategy: ExpiryStrategy;\n /** The effective ttl, used by the silent re-reads of a locked wait. */\n ttl: number;\n /** Set only when the lock is enabled for the call and the store has one. */\n lock: LockProvider | undefined;\n /**\n * The read could not check the entry's tags (spec 3.2 step 4): the value is loaded but not\n * written, and no tag tokens are taken for it.\n */\n noWrite?: boolean;\n}\n\n/** A batch item to load; `noWrite` as in `LoadPlan`, per item. */\nexport type LoadItem = BatchItem & { noWrite?: boolean };\n\n/** Everything a batch load needs once the facade has validated the call. Batches never lock. */\nexport interface BatchPlan<T> {\n target: Target;\n namespace: string | undefined;\n loader: (missing: string[]) => Promise<ReadonlyMap<string, T>>;\n options: BatchPutOptions<T>;\n strategy: ExpiryStrategy;\n}\n\ntype Located = Pick<LoadPlan<unknown>, 'target' | 'ref'>;\n\n/**\n * A refresh that found the lock held settles its flight without a value. `unwritten` marks an\n * empty value (`undefined`/`null`, or an omitted batch key) that was not stored, by what the\n * write actually did (`EngineIO.store`/`storeMany`): `cacheNull` off, a load that does not\n * write, an `unless` veto or throw, a `'skip'` tag stamp or a failed set.\n */\ntype Outcome<T> = Loaded<T> | { loaded: false };\n\n/** A flight that loaded a value; see `Outcome`. */\ntype Loaded<T> = { loaded: true; value: T; unwritten?: true };\n\n/** A loaded value and whether its write happened. */\ninterface Stored<T> {\n value: T;\n written: boolean;\n}\n\n/**\n * The value a refresh wrote; `undefined` when it was skipped or failed, or loaded an empty value\n * it did not write (F-2): the store then still holds the stale entry, so the caller gets that,\n * as when the refresh misses the softTimeout window. An empty value written by `cacheNull` is\n * `{ value }`.\n */\nexport type Refreshed<T> = { value: T } | undefined;\n\n/** A batch loader's result and the user keys of it that were written. */\ninterface LoadedMany<T> {\n loaded: ReadonlyMap<string, T>;\n written: ReadonlySet<string>;\n}\n\nconst NOOP = (): void => undefined;\n\n/** Node runs a longer `setTimeout` delay after 1 ms; the soft wait is capped at this instead. */\nconst MAX_TIMER_MS = 2 ** 31 - 1;\n\n/**\n * Settles with `pending`'s value, or with `undefined` once `ms` have passed. `pending` must\n * never reject. The timer is unref'd and always cleared.\n */\nexport async function settleWithin<T>(pending: Promise<T>, ms: number): Promise<T | undefined> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timedOut = new Promise<undefined>((resolve) => {\n const started = setTimeout(\n () => {\n resolve(undefined);\n },\n Math.min(ms, MAX_TIMER_MS),\n );\n started.unref();\n timer = started;\n });\n try {\n return await Promise.race([pending, timedOut]);\n } finally {\n clearTimeout(timer);\n }\n}\n\n/** A batch loader's result; throws a `TypeError` unless it is a Map. */\nfunction asMap<T>(loaded: unknown): ReadonlyMap<string, T> {\n if (!(loaded instanceof Map)) {\n const got = loaded === null ? 'null' : typeof loaded;\n throw new TypeError(`The getOrSetMany loader must resolve a Map, got ${got}.`);\n }\n return loaded as ReadonlyMap<string, T>;\n}\n\n/** A flight's outcome as a refresh result; never rejects. */\nfunction refreshed<T>(flight: Promise<unknown>): Promise<Refreshed<T>> {\n return flight.then(\n (outcome) => {\n const settled = outcome as Outcome<T>;\n return settled.loaded && settled.unwritten !== true ? { value: settled.value } : undefined;\n },\n () => undefined,\n );\n}\n\n/**\n * Miss loads and background refreshes. A miss and a refresh of the same key share one flight,\n * keyed `<store>\\u0000<fullKey>`.\n */\nexport class EngineLoad {\n private readonly singleFlight = new SingleFlight();\n private readonly lockSettings: LockSettings;\n\n constructor(\n private readonly io: EngineIO,\n defaults: Pick<ResolvedDefaults, 'lock'>,\n private readonly tracing: CacheTracing,\n ) {\n const { ttl, waitTimeout, retryDelay } = defaults.lock;\n this.lockSettings = { ttl: toIntegerMs(ttl), waitTimeout, retryDelay };\n }\n\n /**\n * Loads and stores a missing entry; concurrent misses of the key share the load. The flight\n * key ignores `noWrite`, so single-flight works in both directions: a caller that would write\n * can join a flight that does not (it gets the value, nothing is written for it), and a\n * caller that cannot write joins a flight that does (it gets the value, which is stored).\n */\n async onMiss<T>(plan: LoadPlan<T>): Promise<T> {\n const flightKey = this.flightKey(plan.target, plan.key);\n // Traced, `cache.load.joined` is set once the joined flight has loaded (or failed its load),\n // not for a refresh that skipped its load: this call then loads on its own.\n const joining = this.tracing.enabled && this.singleFlight.has(flightKey);\n let joined: Outcome<T>;\n try {\n joined = await this.singleFlight.run<Outcome<T>>(flightKey, () => this.missTask(plan));\n } catch (error) {\n if (joining) this.tracing.set('cache.load.joined', true);\n throw error;\n }\n if (joined.loaded) {\n if (joining) this.tracing.set('cache.load.joined', true);\n return joined.value;\n }\n // The flight was a refresh that skipped its load: another instance holds the lock. A miss\n // that joins another miss's flight here shares its load, with the same rule as above.\n const sharing = this.tracing.enabled && this.singleFlight.has(flightKey);\n let own: Outcome<T>;\n try {\n own = await this.singleFlight.run<Outcome<T>>(flightKey, () => this.missTask(plan));\n } catch (error) {\n if (sharing) this.tracing.set('cache.load.joined', true);\n throw error;\n }\n if (own.loaded) {\n if (sharing) this.tracing.set('cache.load.joined', true);\n return own.value;\n }\n return (await this.missTask(plan)).value;\n }\n\n /**\n * One flight per key, registered before this returns; shutdown does not wait for it. A failed\n * load keeps the stale value; the flight still rejects, so a miss that joined it gets the\n * loader error. The result is the value the flight wrote, or `undefined` when it was skipped,\n * failed or loaded an empty value it did not write (`Refreshed`); it never rejects. A key\n * already in flight (a miss, a refresh or a batch) is not loaded again: its flight is joined.\n * Callers that do not wait ignore the result.\n */\n refresh<T>(plan: LoadPlan<T>): Promise<Refreshed<T>> {\n const flightKey = this.flightKey(plan.target, plan.key);\n const current = this.singleFlight.current(flightKey);\n if (current !== undefined) return refreshed(current);\n // Traced, the refresh is a root `cache.refresh` span linked to the call that started it.\n const task = this.tracing.enabled\n ? () =>\n this.tracing.root({ store: plan.target.name, namespace: plan.ref.namespace }, () =>\n this.refreshTask(plan),\n )\n : () => this.refreshTask(plan);\n return refreshed(this.singleFlight.run<Outcome<T>>(flightKey, task));\n }\n\n /**\n * Loads the missing batch items, by plain key. An item already in flight (a single-key load\n * or refresh, or another batch) joins it; the rest share one flight per key, all settled by\n * one loader call, so a concurrent single-key `getOrSet` joins them. A joined refresh that\n * skipped its load (another instance held its lock) leaves its items to one more loader\n * call, outside single-flight. A loader error rejects every flight and the caller.\n */\n async onMissMany<T>(\n plan: BatchPlan<T>,\n items: readonly LoadItem[],\n ): Promise<Map<string, unknown>> {\n const outcomes = await Promise.all(this.flights(plan, items, false));\n const values = new Map<string, unknown>();\n const skipped: LoadItem[] = [];\n items.forEach((item, i) => {\n const outcome = outcomes[i];\n if (outcome?.loaded === true) values.set(item.ref.key, outcome.value);\n else skipped.push(item);\n });\n if (skipped.length > 0) {\n const { loaded } = await this.loadMany(plan, skipped, false);\n for (const item of skipped) values.set(item.ref.key, loaded.get(item.ref.key));\n }\n return values;\n }\n\n /**\n * One loader call for the stale items not already in flight, as `refresh`; the items in\n * flight join theirs. A failure is one `refresh` error; the stale values stay. Never rejects:\n * the result holds, by plain key, each refreshed value that counts (`Refreshed`): a non-empty\n * one, and an empty one (an omitted key as `undefined`) only when it was actually written;\n * any other key keeps its stale value.\n * With `softTimeout`, it settles once every item is done or that many ms have passed,\n * whichever is first, with the keys done by then; the refreshes run on.\n */\n refreshMany<T>(\n plan: BatchPlan<T>,\n items: readonly BatchItem[],\n softTimeout?: number,\n ): Promise<ReadonlyMap<string, T>> {\n const done = new Map<string, T>();\n // `flights` joins the items in flight and loads the others with one loader call.\n const flights = this.flights(plan, items, true).map((flight, i) =>\n refreshed<T>(flight).then((result) => {\n const item = items[i];\n if (result !== undefined && item !== undefined) done.set(item.ref.key, result.value);\n }),\n );\n const all = Promise.all(flights).then(() => done);\n if (softTimeout === undefined) return all;\n return settleWithin(all, softTimeout).then(() => new Map(done));\n }\n\n /**\n * One flight per item: an item in flight joins it; the others run one shared `loadMany`,\n * started by the first of them, so every flight is registered before anything is awaited.\n */\n private flights<T>(\n plan: BatchPlan<T>,\n items: readonly LoadItem[],\n refreshing: boolean,\n ): Promise<Outcome<unknown>>[] {\n const own = items.filter(\n (item) => !this.singleFlight.has(this.flightKey(plan.target, item.key)),\n );\n let batch: Promise<LoadedMany<T>> | undefined;\n return items.map((item) =>\n this.singleFlight.run<Outcome<unknown>>(this.flightKey(plan.target, item.key), async () => {\n // Traced, a refresh is one root `cache.refresh` span for the batch's own items.\n batch ??=\n refreshing && this.tracing.enabled\n ? this.tracing.root({ store: plan.target.name, namespace: plan.namespace }, () =>\n this.loadMany(plan, own, true),\n )\n : this.loadMany(plan, own, refreshing);\n const { loaded, written } = await batch;\n const { key } = item.ref;\n return this.outcome({ value: loaded.get(key), written: written.has(key) });\n }),\n );\n }\n\n /**\n * Runs the loader for `items` and stores what it returned for them, except `noWrite` items;\n * other keys are ignored. Tags known up front have their tokens taken before the loader runs,\n * as in `loadAndStore`, when any item is to be written. `written` holds the user keys stored.\n */\n private async loadMany<T>(\n plan: BatchPlan<T>,\n items: readonly LoadItem[],\n refreshing: boolean,\n ): Promise<LoadedMany<T>> {\n const { tags } = plan.options;\n const writable = items.filter((item) => item.noWrite !== true);\n const taken =\n knownTags(tags) && writable.length > 0\n ? await this.io.tags.stamp(plan.target, () => tags)\n : undefined;\n const loaded = await this.runLoader(\n plan,\n items.map((item) => item.ref.key),\n refreshing,\n );\n // An omitted key is stored as if the loader had returned `undefined` for it.\n const values = writable.map(({ ref, key }) => ({ ref, key, value: loaded.get(ref.key) as T }));\n const written = await this.io.storeMany(\n plan.target,\n values,\n plan.options,\n plan.strategy,\n taken,\n );\n return { loaded, written };\n }\n\n /**\n * One batch loader call and its `load` event (`key` the first key, `keys` all of them). A\n * rejection, a synchronous throw or a result that is not a Map reaches the caller;\n * `refreshing` also reports it as `refresh`.\n */\n async runLoader<T>(\n plan: BatchPlan<T>,\n keys: readonly string[],\n refreshing: boolean,\n ): Promise<ReadonlyMap<string, T>> {\n const { target, namespace, loader } = plan;\n const ref = { namespace, key: keys[0] ?? '' };\n const started = Date.now();\n let loaded: ReadonlyMap<string, T>;\n try {\n // Traced, `cache.load` covers the Map check too, so a non-Map marks it `ERROR`. The async\n // wrapper costs one microtask after the loader settles, on the traced path only.\n loaded = this.tracing.enabled\n ? await this.tracing.child('cache.load', async () => asMap<T>(await loader([...keys])))\n : asMap<T>(await loader([...keys]));\n } catch (error) {\n this.io.emitLoad(target.name, ref, started, false, keys);\n if (refreshing) this.io.reportError(target.name, 'refresh', error);\n throw error;\n }\n this.io.emitLoad(target.name, ref, started, true, keys);\n return loaded;\n }\n\n private flightKey(target: Target, key: ResolvedKey): string {\n return `${target.name}\\u0000${key.full}`;\n }\n\n /** A miss's flight outcome; `unwritten` as in `Outcome`, for a refresh that joins it. */\n private async missTask<T>(plan: LoadPlan<T>): Promise<Loaded<T>> {\n const stored =\n plan.lock === undefined\n ? await this.loadAndStore(plan, false)\n : await this.loadLocked(plan, plan.lock);\n return this.outcome(stored);\n }\n\n /**\n * A loaded value as a flight outcome: marked `unwritten` when it is empty and its write did\n * not happen. A non-empty value is fresh data whether or not it was written (F-6).\n */\n private outcome<T>({ value, written }: Stored<T>): Loaded<T> {\n if (isEmpty(value) && !written) return { loaded: true, value, unwritten: true };\n return { loaded: true, value };\n }\n\n /**\n * A value found while waiting for another holder is served with a single `hit`; it is in the\n * store, so it counts as written.\n */\n private async loadLocked<T>(plan: LoadPlan<T>, lock: LockProvider): Promise<Stored<T>> {\n const { target, ref, key, strategy, ttl } = plan;\n const result = await loadWithLock<Stored<T> & { stale: boolean }>(\n lock,\n key.lock,\n this.lockSettings,\n async () => {\n const cached = await this.io.read(target, key, strategy, ttl);\n return servable(cached, strategy)\n ? {\n found: true,\n value: { value: cached.value as T, written: true, stale: cached.stale },\n }\n : { found: false };\n },\n async () => ({ ...(await this.loadAndStore(plan, false)), stale: false }),\n this.hooks(plan),\n );\n // A stale swr value is served as is; the holder's own write is the refresh.\n if (result.from === 'cache') this.io.hit(target.name, ref, result.value.stale);\n return result.value;\n }\n\n private async refreshTask<T>(plan: LoadPlan<T>): Promise<Outcome<T>> {\n if (plan.lock === undefined) {\n return this.outcome(await this.loadAndStore(plan, true));\n }\n let outcome: Outcome<T> = { loaded: false };\n await refreshWithLock(\n plan.lock,\n plan.key.lock,\n this.lockSettings.ttl,\n async () => {\n outcome = this.outcome(await this.loadAndStore(plan, true));\n },\n this.hooks(plan),\n );\n return outcome;\n }\n\n /**\n * Traced, `cache.lock` runs from `onAcquireStart` to the first `onLock` or acquire error; its\n * `end` is idempotent, so a later release error lands on the current cache span instead.\n */\n private hooks({ target, ref }: Located): LockHooks {\n let lockSpan: { end(acquired: boolean | undefined): void } | undefined;\n return {\n onAcquireStart: this.tracing.enabled\n ? () => {\n lockSpan = this.tracing.lockSpan();\n }\n : NOOP,\n onLock: (acquired, waitedMs) => {\n lockSpan?.end(acquired);\n this.io.emitLock(target.name, ref, waitedMs, acquired);\n },\n onError: (error) => {\n lockSpan?.end(undefined);\n this.io.reportError(target.name, 'lock', error);\n },\n };\n }\n\n /**\n * A synchronous loader throw is a failed load too; `refreshing` reports it as `refresh`. Tags\n * known up front (an array) have their tokens taken before the loader runs, and the write uses\n * exactly those, so an invalidation during the load is not lost (spec 3.3). A `noWrite` plan\n * only loads. `written` is what `EngineIO.store` reports.\n */\n private async loadAndStore<T>(plan: LoadPlan<T>, refreshing: boolean): Promise<Stored<T>> {\n const { target, ref, key, loader, options, strategy } = plan;\n const writes = plan.noWrite !== true;\n // Awaited only with tags known up front: an untagged load keeps the 0.6 ticks.\n const { tags } = options;\n const taken =\n writes && knownTags(tags) ? await this.io.tags.stamp(target, () => tags) : undefined;\n const started = Date.now();\n let value: T;\n try {\n value = await this.tracing.child('cache.load', loader);\n } catch (error) {\n this.io.emitLoad(target.name, ref, started, false);\n if (refreshing) this.io.reportError(target.name, 'refresh', error);\n throw error;\n }\n this.io.emitLoad(target.name, ref, started, true);\n const written =\n writes && (await this.io.store(target, ref, key, value, options, strategy, false, taken));\n return { value, written };\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport type { CacheStore } from '../stores/cache-store.interface.js';\nimport type { Target } from './engine-keys.js';\nimport { fullKey } from './key-builder.js';\n\n/** What a token versions: a versioned namespace or a cache tag. */\nexport type TokenKind = 'ns' | 'tag';\n\n/** 30 days; a token key outlives any data written under its token. */\nexport const VERSION_KEY_TTL = 2_592_000_000;\n\n/**\n * Internal: the most tag tokens one instance keeps cached. Tags are user-controlled and can be\n * high-cardinality (`user:<id>`), so the least recently refreshed are evicted beyond it.\n * Namespace tokens are not capped.\n */\nexport const MAX_TAG_TOKENS = 10_000;\n\nconst KIND_NAMESPACE: Readonly<Record<TokenKind, string>> = { ns: '__version__', tag: '__tag__' };\n\n/**\n * `<prefix>:__version__:<name>` for a namespace (unchanged since 0.4), `<prefix>:__tag__:<name>`\n * for a tag. The name is used as is, without escaping.\n */\nexport function tokenKey(prefix: string | undefined, kind: TokenKind, name: string): string {\n return fullKey(prefix, KIND_NAMESPACE[kind], name);\n}\n\n/** The key prefixes of the tokens under `prefix`: `<prefix>:__version__:`, `<prefix>:__tag__:`. */\nexport function tokenKeyPrefixes(prefix: string | undefined): string[] {\n return [tokenKey(prefix, 'ns', ''), tokenKey(prefix, 'tag', '')].map((k) => `${k}:`);\n}\n\n/** 8 base36 characters derived from a random UUID. */\nexport function newVersionToken(): string {\n const n = BigInt(`0x${randomUUID().replaceAll('-', '').slice(0, 12)}`);\n return n.toString(36).padStart(8, '0').slice(-8);\n}\n\ninterface Cached {\n token: string;\n until: number;\n}\n\n/** The tokens of one kind, each map keyed by `<store>\\0<name>`. */\ninterface KindState {\n readonly kind: TokenKind;\n /**\n * Cached tokens, least recently refreshed first. Expired entries stay (a strict store falls\n * back to them when a read fails); for tags only the cap evicts them.\n */\n readonly cache: Map<string, Cached>;\n /** The most entries `cache` keeps. */\n readonly limit: number;\n /**\n * In-flight read-or-create calls (`current`). `fresh` does not register, but it and `bump`\n * drop the slot's entry so an older read cannot replace the newer token.\n */\n readonly inflight: Map<string, Promise<string>>;\n /**\n * In-flight plain reads (`currentMany`), which never create. A read caches its token only\n * while it is still registered here; a bump or a fresh read unregisters it.\n */\n readonly reads: Map<string, Promise<string | undefined>>;\n /**\n * Per slot, the bumps that completed while a `fresh` read of it was in flight (a `fresh` that\n * sees the count change caches nothing). Counted and kept only while `freshes` has the slot.\n */\n readonly bumps: Map<string, number>;\n /** `fresh` reads in flight per slot. */\n readonly freshes: Map<string, number>;\n /**\n * When each slot was last allowed a re-read (`mayRecheck`), oldest first; capped at `limit`.\n */\n readonly rechecked: Map<string, number>;\n /** In-flight re-reads (`recheck`), one per slot; a bump unregisters the slot's. */\n readonly rechecks: Map<string, Promise<string | undefined>>;\n}\n\nfunction newState(kind: TokenKind, limit: number): KindState {\n return {\n kind,\n cache: new Map(),\n limit,\n inflight: new Map(),\n reads: new Map(),\n bumps: new Map(),\n freshes: new Map(),\n rechecked: new Map(),\n rechecks: new Map(),\n };\n}\n\nfunction slot(target: Target, name: string): string {\n return `${target.name}\\u0000${name}`;\n}\n\n/**\n * Version tokens per (store, kind, name), for versioned namespaces (`'ns'`) and cache tags\n * (`'tag'`). Emits nothing; store failures reject. A token key is read with `getStrict` and\n * written with `setStrict` when the store has them (a tiered store), so a token is never created\n * or changed in L1 alone while L2 is down. An empty token key counts as missing.\n */\nexport class VersionTokens {\n private readonly kinds: Readonly<Record<TokenKind, KindState>>;\n\n /** `maxTagTokens` is `MAX_TAG_TOKENS` outside tests. */\n constructor(\n private readonly prefix: string | undefined,\n private readonly cacheTtl: number,\n maxTagTokens = MAX_TAG_TOKENS,\n ) {\n this.kinds = { ns: newState('ns', Infinity), tag: newState('tag', maxTagTokens) };\n }\n\n /** The bump counts `fresh` reads in flight compare, keyed by `<store>\\0<name>`. */\n bumpCounts(kind: TokenKind): ReadonlyMap<string, number> {\n return this.kinds[kind].bumps;\n }\n\n /**\n * The token of `name`: cached for `cacheTtl`, else read from the store, and created when the\n * key is missing. Concurrent reads of one name share one store read.\n */\n current(target: Target, kind: TokenKind, name: string): Promise<string> {\n const state = this.kinds[kind];\n const k = slot(target, name);\n const cached = state.cache.get(k);\n if (cached !== undefined && Date.now() < cached.until) return Promise.resolve(cached.token);\n const running = state.inflight.get(k);\n if (running !== undefined) return running;\n const promise = this.read(target, kind, name).then(\n (token) => {\n // A bump while this read was in flight removed the entry; keep the newer token.\n if (state.inflight.get(k) === promise) {\n state.inflight.delete(k);\n // An older plain read may have seen the key missing; it must not drop this token.\n state.reads.delete(k);\n this.remember(state, k, token);\n }\n return token;\n },\n (error: unknown) => {\n if (state.inflight.get(k) === promise) state.inflight.delete(k);\n throw error;\n },\n );\n state.inflight.set(k, promise);\n return promise;\n }\n\n /** The token this instance has cached, even past `cacheTtl`; never reads the store. */\n cached(target: Target, kind: TokenKind, name: string): string | undefined {\n return this.kinds[kind].cache.get(slot(target, name))?.token;\n }\n\n /**\n * Reads the token from the store (creating it when missing), bypassing the cache, then caches\n * it for `cacheTtl`. A bump that completes during the read keeps its token in the cache.\n */\n async fresh(target: Target, kind: TokenKind, name: string): Promise<string> {\n return (await this.readFresh(target, kind, name, true)) as string;\n }\n\n /**\n * Whether `name` may be re-read now (spec 3.3 step 3): true at most once per `cacheTtl` per\n * (store, name), and the time is recorded. The record keeps at most as many slots as the\n * token cache (`MAX_TAG_TOKENS` for tags), evicting the oldest first.\n */\n mayRecheck(target: Target, kind: TokenKind, name: string): boolean {\n const state = this.kinds[kind];\n const k = slot(target, name);\n const now = Date.now();\n const last = state.rechecked.get(k);\n if (last !== undefined && now < last + this.cacheTtl) return false;\n state.rechecked.delete(k);\n state.rechecked.set(k, now);\n for (const oldest of state.rechecked.keys()) {\n if (state.rechecked.size <= state.limit) break;\n state.rechecked.delete(oldest);\n }\n return true;\n }\n\n /**\n * Re-reads the token of `name` from the store, bypassing the cache, for a stamp that differs\n * from the cached token (spec 3.3). Joins the slot's re-read in flight; otherwise starts one\n * when `mayRecheck` allows it, and returns `undefined` (no read) when it does not. Never\n * creates the token: a missing or empty key resolves `undefined` and drops a cached tag\n * token. As with `fresh`, the result is cached unless a bump completed meanwhile; a bump also\n * unregisters the re-read, so no later call joins a read older than the bump. A rejection\n * reaches every waiter and caches nothing.\n */\n recheck(target: Target, kind: TokenKind, name: string): Promise<string | undefined> | undefined {\n const state = this.kinds[kind];\n const k = slot(target, name);\n const running = state.rechecks.get(k);\n if (running !== undefined) return running;\n if (!this.mayRecheck(target, kind, name)) return undefined;\n const read = this.readFresh(target, kind, name, false).finally(() => {\n if (state.rechecks.get(k) === read) state.rechecks.delete(k);\n });\n state.rechecks.set(k, read);\n return read;\n }\n\n /**\n * The store's token of `name`, bypassing the cache; `create` writes one when the key is\n * missing, else a missing (or empty) key is `undefined`. What it read is cached unless a bump\n * completed during the read; a missing tag key then drops the cached token instead.\n */\n private async readFresh(\n target: Target,\n kind: TokenKind,\n name: string,\n create: boolean,\n ): Promise<string | undefined> {\n const state = this.kinds[kind];\n const k = slot(target, name);\n state.freshes.set(k, (state.freshes.get(k) ?? 0) + 1);\n const bumps = state.bumps.get(k) ?? 0;\n try {\n const token = create\n ? await this.read(target, kind, name)\n : await readToken(target.store, tokenKey(this.prefix, kind, name));\n const found = token !== undefined && token !== '';\n if ((state.bumps.get(k) ?? 0) === bumps) {\n // In-flight reads started earlier; they must not replace this newer token (or, for a\n // missing key, cache the token it replaced). A create in flight is newer: it stays.\n state.reads.delete(k);\n if (found) {\n state.inflight.delete(k);\n this.remember(state, k, token);\n } else if (kind === 'tag') {\n // As in `currentMany`: the tag key is gone, so its token is no fallback any more.\n state.cache.delete(k);\n }\n }\n return found ? token : undefined;\n } finally {\n // The last fresh read of the slot ends: nothing compares its bump count any more.\n const left = (state.freshes.get(k) ?? 0) - 1;\n if (left > 0) {\n state.freshes.set(k, left);\n } else {\n state.freshes.delete(k);\n state.bumps.delete(k);\n }\n }\n }\n\n /** Writes a new token and caches it; on a failed write the cached token is unchanged. */\n async bump(target: Target, kind: TokenKind, name: string): Promise<void> {\n const token = newVersionToken();\n await writeToken(target.store, tokenKey(this.prefix, kind, name), token);\n const state = this.kinds[kind];\n const k = slot(target, name);\n if (state.freshes.has(k)) state.bumps.set(k, (state.bumps.get(k) ?? 0) + 1);\n state.inflight.delete(k);\n state.reads.delete(k);\n state.rechecks.delete(k);\n this.remember(state, k, token);\n }\n\n /**\n * The tokens of `names` (deduplicated, in first-occurrence order), `undefined` for a missing\n * or empty key; never creates one. Cached tokens are served without a store call. A name with\n * a plain read already in flight (from another `currentMany`) joins it; the others are read\n * with one `getStrict` each, in parallel, when the store has it, else with one `getMany` (one\n * `get` each without it). A token read is cached unless a bump or a fresh read completed\n * meanwhile, and an older read-or-create still in flight then no longer updates the cache; a\n * missing key is not cached, and for a tag it also drops the cached token. A `current` that\n * caches a token also unregisters a plain read still in flight, so that read cannot undo it.\n * Rejects when any store read rejects, for every waiter on it. The names served from the\n * process cache (not read by this call nor joined to a read) are added to `fromCache`.\n */\n async currentMany(\n target: Target,\n kind: TokenKind,\n names: readonly string[],\n fromCache?: Set<string>,\n ): Promise<Map<string, string | undefined>> {\n const state = this.kinds[kind];\n const result = new Map<string, string | undefined>();\n const pending: (readonly [string, Promise<string | undefined>])[] = [];\n const unread: string[] = [];\n const now = Date.now();\n for (const name of names) {\n if (result.has(name)) continue;\n const k = slot(target, name);\n const cached = state.cache.get(k);\n if (cached !== undefined && now < cached.until) {\n result.set(name, cached.token);\n fromCache?.add(name);\n continue;\n }\n result.set(name, undefined);\n const running = state.reads.get(k);\n if (running === undefined) unread.push(name);\n else pending.push([name, running]);\n }\n const reads = readTokens(\n target.store,\n unread.map((name) => [name, tokenKey(this.prefix, kind, name)] as const),\n );\n for (const [name, raw] of reads) {\n pending.push([name, this.shareRead(state, slot(target, name), raw)]);\n }\n for (const [name, token] of await Promise.all(\n pending.map(async ([name, read]) => [name, await read] as const),\n )) {\n result.set(name, token);\n }\n return result;\n }\n\n /**\n * `current` for each of `names` (deduplicated), in parallel: missing tokens are created, and\n * reads already in flight are shared. Rejects when any read or create rejects.\n */\n async ensureMany(\n target: Target,\n kind: TokenKind,\n names: readonly string[],\n ): Promise<Map<string, string>> {\n const entries = await Promise.all(\n [...new Set(names)].map(\n async (name) => [name, await this.current(target, kind, name)] as const,\n ),\n );\n return new Map(entries);\n }\n\n /**\n * `bump` for each of `names` (deduplicated), in parallel. Every name is tried; then the call\n * rejects with the first failing name's error. Successful bumps are cached either way.\n */\n async bumpMany(target: Target, kind: TokenKind, names: readonly string[]): Promise<void> {\n const settled = await Promise.allSettled(\n [...new Set(names)].map((name) => this.bump(target, kind, name)),\n );\n const failed = settled.find((result) => result.status === 'rejected');\n if (failed !== undefined) throw failed.reason;\n }\n\n /**\n * Registers the plain read of `k` so concurrent `currentMany` calls join it. On success a token\n * is cached while the read is still registered; `''` becomes `undefined`. A rejection is\n * passed to every waiter and caches nothing.\n */\n private shareRead(\n state: KindState,\n k: string,\n raw: Promise<string | undefined>,\n ): Promise<string | undefined> {\n const read: Promise<string | undefined> = raw.then(\n (value) => {\n const registered = state.reads.get(k) === read;\n if (registered) state.reads.delete(k);\n if (value === undefined || value === '') {\n // The tag key is gone: its token is no fallback any more.\n if (registered && state.kind === 'tag') state.cache.delete(k);\n return undefined;\n }\n if (registered) {\n // As in `fresh`: an older read-or-create in flight must not replace this token.\n state.inflight.delete(k);\n this.remember(state, k, value);\n }\n return value;\n },\n (error: unknown) => {\n if (state.reads.get(k) === read) state.reads.delete(k);\n throw error;\n },\n );\n state.reads.set(k, read);\n return read;\n }\n\n /** Caches `token` as the most recently refreshed entry, evicting the oldest beyond the cap. */\n private remember(state: KindState, k: string, token: string): void {\n state.cache.delete(k);\n state.cache.set(k, { token, until: Date.now() + this.cacheTtl });\n for (const oldest of state.cache.keys()) {\n if (state.cache.size <= state.limit) break;\n state.cache.delete(oldest);\n }\n }\n\n /** Reads the token key, creating it when missing; a concurrent creator's token wins. */\n private async read(target: Target, kind: TokenKind, name: string): Promise<string> {\n const key = tokenKey(this.prefix, kind, name);\n const existing = await readToken(target.store, key);\n if (existing !== undefined && existing !== '') return existing;\n // A bump that lands between the read above and this write is overwritten by `created`: the\n // entries stamped with the bumped token are orphaned (they read as misses), never read wrongly.\n const created = newVersionToken();\n await writeToken(target.store, key, created);\n const stored = await readToken(target.store, key);\n return stored === undefined || stored === '' ? created : stored;\n }\n}\n\nfunction readToken(store: CacheStore, key: string): Promise<string | undefined> {\n return store.getStrict === undefined ? store.get(key) : store.getStrict(key);\n}\n\n/**\n * The read of each `[name, key]` pair: `getStrict` each when the store has it, else one shared\n * `getMany` (one `get` each without it). No call for an empty list.\n */\nfunction readTokens(\n store: CacheStore,\n entries: readonly (readonly [name: string, key: string])[],\n): [string, Promise<string | undefined>][] {\n if (entries.length === 0) return [];\n if (store.getStrict === undefined && store.getMany !== undefined) {\n const getMany = store.getMany.bind(store);\n const all = attempt(() => getMany(entries.map(([, key]) => key)));\n return entries.map(([name], i) => [name, all.then((values) => values[i])]);\n }\n // A synchronous throw becomes this entry's rejection, so the reads already started stay handled.\n return entries.map(([name, key]) => [name, attempt(() => readToken(store, key))]);\n}\n\n/** `run()`, with a synchronous throw turned into a rejection (by the Promise executor). */\nfunction attempt<T>(run: () => Promise<T>): Promise<T> {\n return new Promise<T>((resolve) => {\n resolve(run());\n });\n}\n\nfunction writeToken(store: CacheStore, key: string, token: string): Promise<void> {\n return store.setStrict === undefined\n ? store.set(key, token, VERSION_KEY_TTL)\n : store.setStrict(key, token, VERSION_KEY_TTL);\n}\n","import type { Target } from './engine-keys.js';\nimport { tokenKey, VersionTokens } from './version-tokens.js';\n\nexport { newVersionToken, VERSION_KEY_TTL } from './version-tokens.js';\n\nexport function versionKey(prefix: string | undefined, namespace: string): string {\n return tokenKey(prefix, 'ns', namespace);\n}\n\n/**\n * Version tokens for opt-in versioned namespaces: the 0.6 API over `VersionTokens` with kind\n * `'ns'`. Emits nothing; store failures reject (see `VersionTokens`).\n */\nexport class NamespaceVersions {\n /** Completed bumps per (store, namespace): the `'ns'` counters of `tokens`. */\n private readonly bumps: ReadonlyMap<string, number>;\n\n /**\n * `tokens` lets the engine share one `VersionTokens` with tags; it must be built with the\n * same `prefix` and `cacheTtl`.\n */\n constructor(\n prefix: string | undefined,\n private readonly versioned: ReadonlySet<string>,\n cacheTtl: number,\n private readonly tokens: VersionTokens = new VersionTokens(prefix, cacheTtl),\n ) {\n this.bumps = tokens.bumpCounts('ns');\n }\n\n isVersioned(namespace: string | undefined): boolean {\n return namespace !== undefined && this.versioned.has(namespace);\n }\n\n /** See `VersionTokens.current`. */\n current(target: Target, namespace: string): Promise<string> {\n return this.tokens.current(target, 'ns', namespace);\n }\n\n /** The token this instance has cached, even past `cacheTtl`; never reads the store. */\n cached(target: Target, namespace: string): string | undefined {\n return this.tokens.cached(target, 'ns', namespace);\n }\n\n /**\n * Reads the token from the store, bypassing the cache, then caches it for `cacheTtl`.\n * Deletes use it, so they never miss an entry written under another instance's newer token.\n * A bump that completes during the read keeps its token in the cache. Store failures reject.\n */\n fresh(target: Target, namespace: string): Promise<string> {\n return this.tokens.fresh(target, 'ns', namespace);\n }\n\n bump(target: Target, namespace: string): Promise<void> {\n return this.tokens.bump(target, 'ns', namespace);\n }\n}\n","import type { LoadStrategyOptions } from '../decorators/options.js';\nimport { CacheConfigError } from '../errors.js';\nimport type { ResolvedCacheOptions } from '../module/cache.options.js';\nimport { CacheTracing } from '../observability/cache-tracing.js';\nimport { MemoryStore } from '../stores/memory.store.js';\nimport {\n EMPTY_STRATEGY,\n EngineIO,\n isEmpty,\n servable,\n uncertain,\n type BatchPutOptions,\n type KeyRef,\n type PutOptions,\n type Target,\n} from './engine-io.js';\nimport { EngineBatch, type BatchLoader, type BatchScope } from './engine-batch.js';\nimport { EngineLoad, settleWithin } from './engine-load.js';\nimport {\n normalizeTags,\n type BatchTagOption,\n type Stamping,\n type TagOption,\n} from './engine-tags.js';\nimport { isReservedNamespace, keyErrorOf } from './key-builder.js';\nimport type { CacheEvents, CacheLogLevel, CacheOperation } from './events.js';\nimport { NamespaceVersions } from './namespace-versions.js';\nimport { createStrategy, type ExpiryStrategy } from './strategies/expiry-strategy.js';\nimport { tokenKeyPrefixes, VersionTokens } from './version-tokens.js';\n\nexport type { BatchPutOptions, KeyRef, PutOptions } from './engine-io.js';\nexport type { BatchLoader, BatchScope } from './engine-batch.js';\n\n/** `lock` overrides `defaults.lock.enabled`; it has no effect on a store without `lock`. */\nexport type LoadOptions<T> = PutOptions<T> & { lock?: boolean };\n\n/** `getOrSetMany` options: batch tags (D2); `lock: true` is rejected. */\nexport type BatchLoadOptions<T> = BatchPutOptions<T> & { lock?: boolean };\n\nexport type SetOptions<T = unknown> = { ttl?: number; tags?: TagOption<T> } & LoadStrategyOptions;\n\n/** `setMany` options: a tag function also gets each entry's key (D2). */\nexport type BatchSetOptions<T = unknown> = {\n ttl?: number;\n tags?: BatchTagOption<T>;\n} & LoadStrategyOptions;\n\nfunction checkDuration(option: string, value: number | undefined): void {\n if (value === undefined) return;\n if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {\n throw new CacheConfigError(\n `Invalid ${option}: ${String(value)}. Durations are milliseconds, finite numbers greater than 0.`,\n );\n }\n}\n\nfunction checkKeys(keys: unknown): void {\n if (Array.isArray(keys)) return;\n throw new CacheConfigError(`Invalid keys: ${String(keys)}. It must be an array of strings.`);\n}\n\nfunction checkEntries(entries: unknown): void {\n if (Array.isArray(entries)) return;\n throw new CacheConfigError(\n `Invalid entries: ${String(entries)}. It must be an array of [key, value] pairs.`,\n );\n}\n\n/** The tags of an `invalidateTags` call (spec 4): a non-empty list of valid tags. */\nfunction tagsToInvalidate(tags: unknown): string[] {\n let names: string[];\n try {\n names = normalizeTags(tags);\n } catch (error) {\n throw new CacheConfigError(error instanceof Error ? error.message : String(error));\n }\n if (names.length === 0) {\n throw new CacheConfigError('Invalid tags: []. invalidateTags requires at least one tag.');\n }\n return names;\n}\n\n/**\n * The store and namespace of a traced call's span. Read without a throw, so a `ref` or `scope`\n * that is not an object makes the call reject inside its span, as it rejects untraced.\n */\nfunction traceBase(ref: { store?: string; namespace?: string }): {\n store: string;\n namespace?: string;\n} {\n const given = ref as { store?: string; namespace?: string } | null | undefined;\n if (typeof given !== 'object' || given === null) return { store: 'default' };\n return { store: given.store ?? 'default', namespace: given.namespace };\n}\n\nfunction checkBoolean(option: string, value: boolean | undefined): void {\n if (value === undefined || typeof value === 'boolean') return;\n throw new CacheConfigError(`Invalid ${option}: ${String(value)}. It must be a boolean.`);\n}\n\n/**\n * Validates the strategy options and builds the strategy. `ttl` is the effective ttl the\n * entry is written with; it is omitted by `get`, which writes nothing. `preset` is a strategy\n * already built from these same options; every check still runs, in the same order.\n * `noSoftTimeout` names a call that does not load (`get`, `set`, ...): any defined\n * `softTimeout` is then rejected. On a load call, `softTimeout` needs the `swr` strategy: only a\n * stale `swr` hit waits for its refresh.\n */\nfunction strategyOf(\n options: LoadStrategyOptions,\n ttl: number | undefined,\n preset?: ExpiryStrategy,\n noSoftTimeout?: string,\n): ExpiryStrategy {\n const { staleTtl, maxTtl } = options;\n if (noSoftTimeout !== undefined && options.softTimeout !== undefined) {\n throw new CacheConfigError(\n `Invalid softTimeout: ${String(options.softTimeout)}. ${noSoftTimeout} does not support softTimeout; only getOrSet and getOrSetMany do.`,\n );\n }\n checkDuration('staleTtl', staleTtl);\n checkDuration('maxTtl', maxTtl);\n checkDuration('softTimeout', options.softTimeout);\n const strategy = preset ?? createStrategy(options);\n if (options.softTimeout !== undefined && strategy.kind !== 'swr') {\n throw new CacheConfigError(\n `Invalid softTimeout: ${String(options.softTimeout)}. softTimeout needs the 'swr' strategy, but the strategy is '${strategy.kind}'.`,\n );\n }\n if (strategy.kind === 'swr' && staleTtl === undefined) {\n throw new CacheConfigError(\n \"Invalid staleTtl: undefined. The 'swr' strategy requires staleTtl.\",\n );\n }\n if (ttl !== undefined && maxTtl !== undefined && maxTtl < ttl) {\n throw new CacheConfigError(\n `Invalid maxTtl: ${String(maxTtl)}. It must be >= ttl (${String(ttl)}).`,\n );\n }\n return strategy;\n}\n\n/** Public facade: validates each call, then delegates to the store I/O and load orchestration. */\nexport class CacheEngine {\n private readonly io: EngineIO;\n private readonly load: EngineLoad;\n private readonly batch: EngineBatch;\n\n /** The module's `logging.level`. */\n readonly logLevel: CacheLogLevel;\n\n /** The module's `escapeKeyArgs`; decorators pass it to template key rendering at call time. */\n readonly escapeKeyArgs: boolean;\n\n /** Internal: the version tokens of namespaces and tags, one set per engine. */\n readonly tokens: VersionTokens;\n\n /**\n * @param tracing Internal: the module's tracing; until a tracer is registered with it, every\n * call runs untraced, as before 0.10.\n */\n constructor(\n private readonly options: ResolvedCacheOptions,\n events: CacheEvents,\n private readonly tracing: CacheTracing = new CacheTracing(),\n ) {\n this.logLevel = options.logging.level;\n this.escapeKeyArgs = options.escapeKeyArgs;\n // One token store for namespaces and tags; the facade serves the namespace calls.\n const tokens = new VersionTokens(options.prefix, options.versionCacheTtl);\n this.tokens = tokens;\n const versions = new NamespaceVersions(\n options.prefix,\n options.versionedNamespaces,\n options.versionCacheTtl,\n tokens,\n );\n // A memory store keeps the tokens apart from its data LRU, so data writes never evict them\n // (an evicted token is re-created and empties its namespace or tag). A tiered L1 is not\n // told: a token it drops is read again from L2.\n const reserved = tokenKeyPrefixes(options.prefix);\n for (const store of options.stores.values()) {\n if (store instanceof MemoryStore) store.reserveKeyPrefixes(reserved);\n }\n this.io = new EngineIO(options, events, versions, tokens, tracing);\n this.load = new EngineLoad(this.io, options.defaults, tracing);\n this.batch = new EngineBatch(options, this.io, this.load, tracing);\n }\n\n hasStore(name: string): boolean {\n return this.options.stores.has(name);\n }\n\n /** True when the store is configured and can lock; never throws for an unknown name. */\n hasLock(name: string): boolean {\n return this.options.stores.get(name)?.lock !== undefined;\n }\n\n storeNames(): string[] {\n return [...this.options.stores.keys()];\n }\n\n /** Never refreshes; `options` selects the read command and the classification only. */\n get<T>(ref: KeyRef, options?: LoadStrategyOptions): Promise<T | undefined> {\n if (!this.tracing.enabled) return this.getImpl<T>(ref, options);\n return this.tracing.span('cache.get', traceBase(ref), () => this.getImpl<T>(ref, options));\n }\n\n private async getImpl<T>(ref: KeyRef, options: LoadStrategyOptions = {}): Promise<T | undefined> {\n const target = this.io.resolve(ref.store);\n this.checkNamespace(ref.namespace);\n const strategy = strategyOf(options, undefined, undefined, 'get');\n if (this.invalidKey(target, ref.namespace, ref.key)) {\n this.tracing.result('bypass');\n return undefined;\n }\n const pending = this.io.resolveKey(target, ref);\n const key = pending instanceof Promise ? await pending : pending;\n // A version failure is already reported; like a key error, it is no miss.\n if (key === undefined) {\n this.tracing.result('bypass');\n return undefined;\n }\n this.tracing.key(key.full);\n const result = await this.io.read(target, key, strategy, this.options.defaults.ttl);\n if (!result.found) {\n this.io.miss(target.name, ref);\n return undefined;\n }\n this.io.hit(target.name, ref, result.stale);\n return result.value as T | undefined;\n }\n\n /**\n * @param preset Internal: the strategy built from `options` at decoration time, so a\n * decorated call does not rebuild it. It must come from `createStrategy(options)`.\n */\n getOrSet<T>(\n ref: KeyRef,\n loader: () => Promise<T>,\n options?: LoadOptions<T>,\n preset?: ExpiryStrategy,\n ): Promise<T> {\n if (!this.tracing.enabled) return this.getOrSetImpl(ref, loader, options, preset);\n return this.tracing.span('cache.getOrSet', traceBase(ref), () =>\n this.getOrSetImpl(ref, loader, options, preset),\n );\n }\n\n private async getOrSetImpl<T>(\n ref: KeyRef,\n loader: () => Promise<T>,\n options: LoadOptions<T> = {},\n preset?: ExpiryStrategy,\n ): Promise<T> {\n const target = this.io.resolve(ref.store);\n this.checkNamespace(ref.namespace);\n checkDuration('ttl', options.ttl);\n checkDuration('nullTtl', options.nullTtl);\n checkBoolean('cacheNull', options.cacheNull);\n checkBoolean('lock', options.lock);\n const ttl = options.ttl ?? this.options.defaults.ttl;\n const strategy = strategyOf(options, ttl, preset);\n if (this.invalidKey(target, ref.namespace, ref.key)) return this.bypass(loader);\n // Awaited only for a versioned namespace: the swr refresh below must register its flight\n // without an added tick, as in 0.3.\n const pending = this.io.resolveKey(target, ref);\n const key = pending instanceof Promise ? await pending : pending;\n if (key === undefined) return this.bypass(loader);\n this.tracing.key(key.full);\n const cached = await this.io.read(target, key, strategy, ttl);\n // An entry whose tags could not be checked is loaded without a write (spec 3.2 step 4), and\n // without the lock: nothing would be written for other instances to wait for.\n const noWrite = uncertain(cached);\n const locking = !noWrite && (options.lock ?? this.options.defaults.lock.enabled);\n const lock = locking ? target.store.lock : undefined;\n const plan = { target, ref, key, loader, options, strategy, ttl, lock, noWrite };\n if (servable(cached, strategy)) {\n this.io.hit(target.name, ref, cached.stale);\n if (!cached.stale) return cached.value as T;\n // A refresh already in flight is joined, even one that started before this stale entry\n // was written: its result is what the store will hold, so it is the value to wait for.\n const refreshing = this.load.refresh(plan);\n // Without softTimeout nothing is awaited here, as in 0.7.\n const { softTimeout } = options;\n if (softTimeout === undefined) return cached.value as T;\n const refreshed = await settleWithin(refreshing, softTimeout);\n return refreshed === undefined ? (cached.value as T) : refreshed.value;\n }\n this.io.miss(target.name, ref);\n return this.load.onMiss(plan);\n }\n\n /** With `tags`, the entry is stamped with their tokens; an invalid list skips the write. */\n set<T>(ref: KeyRef, value: T, options?: SetOptions<T>): Promise<void> {\n if (!this.tracing.enabled) return this.setImpl(ref, value, options);\n return this.tracing.span('cache.set', traceBase(ref), () => this.setImpl(ref, value, options));\n }\n\n private async setImpl<T>(ref: KeyRef, value: T, options: SetOptions<T> = {}): Promise<void> {\n const target = this.io.resolve(ref.store);\n this.checkNamespace(ref.namespace);\n checkDuration('ttl', options.ttl);\n const ttl = options.ttl ?? this.options.defaults.ttl;\n const requested = strategyOf(options, ttl, undefined, 'set');\n if (this.invalidKey(target, ref.namespace, ref.key)) {\n this.tracing.set('cache.written', false);\n return;\n }\n const pending = this.io.resolveKey(target, ref);\n const key = pending instanceof Promise ? await pending : pending;\n // A version failure is already reported; nothing is written.\n if (key === undefined) {\n this.tracing.set('cache.written', false);\n return;\n }\n this.tracing.key(key.full);\n // `set` has no cacheNull/nullTtl: an empty value keeps the 0.1 ttl, but always as `fixed`.\n const strategy = isEmpty(value) ? EMPTY_STRATEGY : requested;\n const { tags } = options;\n const stamping =\n tags === undefined ? undefined : await this.io.tags.stampFor(target, tags, value);\n if (stamping === 'skip') {\n this.tracing.set('cache.written', false);\n return;\n }\n const written = await this.io.write(\n target,\n ref,\n key,\n value,\n strategy,\n this.io.ttlFor(strategy, ttl),\n stamping,\n );\n this.tracing.set('cache.written', written);\n }\n\n /**\n * @param preset Internal: as for `getOrSet`.\n * @param taken Internal: the stamp `takeTags` gave before the value was produced (T4-B); the\n * write uses exactly those tokens and `options.tags` is not stamped again.\n */\n put<T>(\n ref: KeyRef,\n value: T,\n options?: PutOptions<T>,\n preset?: ExpiryStrategy,\n taken?: Stamping,\n ): Promise<void> {\n if (!this.tracing.enabled) return this.putImpl(ref, value, options, preset, taken);\n return this.tracing.span('cache.put', traceBase(ref), () =>\n this.putImpl(ref, value, options, preset, taken),\n );\n }\n\n private async putImpl<T>(\n ref: KeyRef,\n value: T,\n options: PutOptions<T> = {},\n preset?: ExpiryStrategy,\n taken?: Stamping,\n ): Promise<void> {\n const target = this.io.resolve(ref.store);\n this.checkNamespace(ref.namespace);\n checkDuration('ttl', options.ttl);\n checkDuration('nullTtl', options.nullTtl);\n checkBoolean('cacheNull', options.cacheNull);\n const strategy = strategyOf(options, options.ttl ?? this.options.defaults.ttl, preset);\n if (this.invalidKey(target, ref.namespace, ref.key)) {\n this.tracing.set('cache.written', false);\n return;\n }\n const pending = this.io.resolveKey(target, ref);\n const key = pending instanceof Promise ? await pending : pending;\n // A version failure is already reported; nothing is written.\n if (key === undefined) {\n this.tracing.set('cache.written', false);\n return;\n }\n this.tracing.key(key.full);\n const written = await this.io.store(target, ref, key, value, options, strategy, true, taken);\n this.tracing.set('cache.written', written);\n }\n\n /**\n * Internal: takes the tokens of tags known before a value is produced (spec 3.3), for a later\n * `put`, so an invalidation in between leaves that write stale. An invalid list is one `tag`\n * error, a failed token write one `version` error; either gives `'skip'` and never rejects.\n */\n takeTags(storeName: string | undefined, tags: readonly string[]): Promise<Stamping> {\n const target = this.io.resolve(storeName);\n return this.io.tags.stamp(target, () => tags);\n }\n\n /**\n * `get` for several keys of one namespace: one store read for the batch (per key under\n * `sliding`), results in input order. A duplicate is read once; an empty or reserved key is\n * `undefined`.\n */\n getMany<T>(\n scope: BatchScope,\n keys: readonly string[],\n options?: LoadStrategyOptions,\n ): Promise<(T | undefined)[]> {\n if (!this.tracing.enabled) return this.getManyImpl<T>(scope, keys, options);\n return this.tracing.span(\n 'cache.getMany',\n traceBase(scope),\n () => this.getManyImpl<T>(scope, keys, options),\n 'batch',\n );\n }\n\n private async getManyImpl<T>(\n scope: BatchScope,\n keys: readonly string[],\n options: LoadStrategyOptions = {},\n ): Promise<(T | undefined)[]> {\n const target = this.io.resolve(scope.store);\n this.checkNamespace(scope.namespace);\n const strategy = strategyOf(options, undefined, undefined, 'getMany');\n checkKeys(keys);\n this.tracing.set('cache.keys', keys.length);\n return this.batch.getMany(target, scope, keys, strategy);\n }\n\n /**\n * `set` for several entries, written with one store call. A repeated key is written once,\n * with its last value; empty or reserved keys are dropped and reported once as a key error.\n */\n setMany<T>(\n scope: BatchScope,\n entries: readonly (readonly [key: string, value: NoInfer<T>])[],\n options?: BatchSetOptions<T>,\n ): Promise<void> {\n if (!this.tracing.enabled) return this.setManyImpl<T>(scope, entries, options);\n // Not a `'batch'` scope: a write has no hits or misses to count.\n return this.tracing.span('cache.setMany', traceBase(scope), () =>\n this.setManyImpl<T>(scope, entries, options),\n );\n }\n\n private async setManyImpl<T>(\n scope: BatchScope,\n entries: readonly (readonly [key: string, value: T])[],\n options: BatchSetOptions<T> = {},\n ): Promise<void> {\n const target = this.io.resolve(scope.store);\n this.checkNamespace(scope.namespace);\n checkDuration('ttl', options.ttl);\n const ttl = options.ttl ?? this.options.defaults.ttl;\n const requested = strategyOf(options, ttl, undefined, 'setMany');\n checkEntries(entries);\n this.tracing.set('cache.keys', entries.length);\n await this.batch.setMany(target, scope, entries, requested, ttl, options.tags);\n }\n\n /**\n * `getOrSet` for several keys of one namespace. Hits (stale `swr` ones too) are served; the\n * misses go to one `loader(missing)` call, except those another call is loading, which are\n * awaited. A key the loader omits counts as `undefined`; keys it was not asked for are\n * ignored. Stale `swr` keys are refreshed in the background with one more loader call.\n * Results are in input order, duplicates included; an empty or reserved key is\n * `undefined`. Never locks.\n */\n getOrSetMany<T>(\n scope: BatchScope,\n keys: readonly string[],\n loader: BatchLoader<T>,\n options?: BatchLoadOptions<T>,\n ): Promise<(T | undefined)[]> {\n if (!this.tracing.enabled) return this.getOrSetManyImpl(scope, keys, loader, options);\n return this.tracing.span(\n 'cache.getOrSetMany',\n traceBase(scope),\n () => this.getOrSetManyImpl(scope, keys, loader, options),\n 'batch',\n );\n }\n\n private async getOrSetManyImpl<T>(\n scope: BatchScope,\n keys: readonly string[],\n loader: BatchLoader<T>,\n options: BatchLoadOptions<T> = {},\n ): Promise<(T | undefined)[]> {\n const target = this.io.resolve(scope.store);\n this.checkNamespace(scope.namespace);\n if (options.lock === true) {\n throw new CacheConfigError('Invalid lock: true. getOrSetMany does not support lock.');\n }\n checkDuration('ttl', options.ttl);\n checkDuration('nullTtl', options.nullTtl);\n checkBoolean('cacheNull', options.cacheNull);\n const ttl = options.ttl ?? this.options.defaults.ttl;\n const strategy = strategyOf(options, ttl);\n checkKeys(keys);\n this.tracing.set('cache.keys', keys.length);\n return this.batch.getOrSetMany(target, scope, keys, loader, options, strategy, ttl);\n }\n\n /** Empty keys are dropped and reported once as a key error; every other key is deleted. */\n delete(scope: { store?: string; namespace?: string }, keys: readonly string[]): Promise<void> {\n if (!this.tracing.enabled) return this.deleteImpl(scope, keys);\n return this.tracing.span('cache.delete', traceBase(scope), () => this.deleteImpl(scope, keys));\n }\n\n private async deleteImpl(\n scope: { store?: string; namespace?: string },\n keys: readonly string[],\n ): Promise<void> {\n const target = this.io.resolve(scope.store);\n this.checkNamespace(scope.namespace);\n let invalid: TypeError | undefined;\n const valid = keys.filter((key) => {\n const error = keyErrorOf(scope.namespace, key);\n if (error === undefined) return true;\n invalid ??= error;\n return false;\n });\n this.tracing.set('cache.keys', valid.length);\n if (invalid !== undefined) this.io.reportError(target.name, 'key', invalid);\n await this.io.delete(scope, valid, true);\n }\n\n clear(namespace: string, storeName?: string): Promise<void> {\n if (!this.tracing.enabled) return this.clearImpl(namespace, storeName);\n const base = {\n store: storeName ?? 'default',\n namespace: typeof namespace === 'string' && namespace !== '' ? namespace : undefined,\n };\n return this.tracing.span('cache.clear', base, () => this.clearImpl(namespace, storeName));\n }\n\n private async clearImpl(namespace: string, storeName?: string): Promise<void> {\n // With a prefix, '' would wipe every namespace; without one it would clear nothing.\n if (typeof namespace !== 'string' || namespace === '') {\n throw new CacheConfigError('clear requires a non-empty namespace');\n }\n this.io.resolve(storeName);\n this.checkNamespace(namespace);\n await this.io.clear(storeName, namespace);\n }\n\n /**\n * Gives each tag a new version in the store (spec 3.4), so every entry stamped with one of them\n * becomes a miss; this instance sees it at once, others once their cached token expires. Rejects\n * `CacheConfigError` for an invalid list (empty, an empty or non-string tag, more than 32 after\n * de-duplication) or an unknown store. A failed token write is one `version` error, and the\n * call rejects with the first failing tag's error once every tag was tried.\n */\n invalidateTags(tags: readonly string[], storeName?: string): Promise<void> {\n if (!this.tracing.enabled) return this.invalidateTagsImpl(tags, storeName);\n return this.tracing.span('cache.invalidateTags', { store: storeName ?? 'default' }, () =>\n this.invalidateTagsImpl(tags, storeName),\n );\n }\n\n private async invalidateTagsImpl(tags: readonly string[], storeName?: string): Promise<void> {\n const names = tagsToInvalidate(tags);\n this.tracing.set('cache.tags', names.length);\n this.tracing.key(names);\n const target = this.io.resolve(storeName);\n await this.io.tags.invalidate(target, names);\n }\n\n reportError(store: string | undefined, operation: CacheOperation, error: unknown): void {\n this.io.reportError(store, operation, error);\n }\n\n /** Names starting with `__` are reserved for internal keys (the lock keys). */\n private checkNamespace(namespace: string | undefined): void {\n if (namespace !== undefined && isReservedNamespace(namespace)) {\n throw new CacheConfigError(\n `Invalid namespace: ${namespace}. Names starting with \"__\" are reserved.`,\n );\n }\n }\n\n /** A `getOrSet` that skips the cache: `cache.result = 'bypass'`, the loader in `cache.load`. */\n private bypass<T>(loader: () => Promise<T>): Promise<T> {\n this.tracing.result('bypass');\n return this.tracing.child('cache.load', loader);\n }\n\n /** Reports an empty or reserved key as a key error; the caller then skips the cache. */\n private invalidKey(target: Target, namespace: string | undefined, key: string): boolean {\n const error = keyErrorOf(namespace, key);\n if (error === undefined) return false;\n this.io.reportError(target.name, 'key', error);\n return true;\n }\n}\n","import type { LoadStrategyOptions, StrategyOptions } from '../decorators/options.js';\nimport type {\n BatchLoadOptions,\n BatchScope,\n BatchSetOptions,\n CacheEngine,\n LoadOptions,\n SetOptions,\n} from './cache-engine.js';\nimport { strategyOptionsOf } from './strategies/expiry-strategy.js';\n\n/** Where a key lives: its `namespace` (default none) and `store` name (default `'default'`). */\nexport interface KeyOptions {\n namespace?: string;\n store?: string;\n}\n\n/**\n * `tags`: fixed tag strings (not templates), or a function of the value. The entry is stamped\n * with each tag's version, so `invalidateTags` turns it into a miss. On `getOrSet` an array's\n * versions are taken before the loader runs; a function runs after it, and only when the entry\n * is written, so an invalidation during that load can be missed until the entry expires. An\n * invalid list (an empty tag, more than 32 tags, a throwing function) is an `error` event with\n * operation `'tag'`: the entry is not written and the call still resolves.\n */\nexport type WriteOptions<T = unknown> = KeyOptions & Writes<T> & StrategyOptions;\n\n/** The options of the batch writes: a tag function also gets each entry's key. */\nexport type WriteManyOptions<T = unknown> = KeyOptions & WritesMany<T> & StrategyOptions;\n\n/** `ttl` and `tags` of a single-key write; see `WriteOptions`. */\ninterface Writes<T> {\n ttl?: number;\n tags?: readonly string[] | ((value: T) => readonly string[]);\n}\n\n/** `ttl` and `tags` of a batch write; see `WriteManyOptions`. */\ninterface WritesMany<T> {\n ttl?: number;\n tags?: readonly string[] | ((value: T, key: string) => readonly string[]);\n}\n\n/** The load options; `L` narrows `lock` (`false` for `getOrSetMany`, which never locks). */\ninterface LoadPolicy<T, L extends boolean = boolean> {\n cacheNull?: boolean;\n nullTtl?: number;\n unless?: (result: T) => boolean;\n lock?: L;\n}\n\n/**\n * `getOrSet` options: the `WriteOptions` fields with `LoadStrategyOptions` (so `softTimeout` is\n * accepted), plus the load policy. It is not built on `WriteOptions`, whose\n * `softTimeout?: never` would make the intersection reject `softTimeout`.\n */\nexport type GetOrSetOptions<T> = KeyOptions & Writes<T> & LoadStrategyOptions & LoadPolicy<T>;\n\n/**\n * `getOrSetMany` options. `lock` accepts only `false`: a batch never locks, and `lock: true`\n * from JavaScript rejects with `CacheConfigError`.\n */\nexport type GetOrSetManyOptions<T> = KeyOptions &\n WritesMany<T> &\n LoadStrategyOptions &\n LoadPolicy<T, false>;\n\nfunction refOf(\n key: string,\n options: KeyOptions,\n): { store?: string; namespace?: string; key: string } {\n const ref: { store?: string; namespace?: string; key: string } = { key };\n if (options.store !== undefined) ref.store = options.store;\n if (options.namespace !== undefined) ref.namespace = options.namespace;\n return ref;\n}\n\nfunction scopeOf(options: KeyOptions): BatchScope {\n const scope: BatchScope = {};\n if (options.store !== undefined) scope.store = options.store;\n if (options.namespace !== undefined) scope.namespace = options.namespace;\n return scope;\n}\n\n/** Only the defined options are forwarded. */\nfunction writeOptionsOf<T>(options: Writes<T> & LoadStrategyOptions): SetOptions<T> {\n const write: SetOptions<T> = strategyOptionsOf(options);\n if (options.ttl !== undefined) write.ttl = options.ttl;\n if (options.tags !== undefined) write.tags = options.tags;\n return write;\n}\n\nfunction writeManyOptionsOf<T>(options: WritesMany<T> & LoadStrategyOptions): BatchSetOptions<T> {\n const write: BatchSetOptions<T> = strategyOptionsOf(options);\n if (options.ttl !== undefined) write.ttl = options.ttl;\n if (options.tags !== undefined) write.tags = options.tags;\n return write;\n}\n\n/** Copies the defined `LoadPolicy` options of `options` onto `load`. */\nfunction withLoadPolicy<O extends LoadPolicy<T>, T>(load: O, options: LoadPolicy<T>): O {\n const { cacheNull, nullTtl, unless, lock } = options;\n if (cacheNull !== undefined) load.cacheNull = cacheNull;\n if (nullTtl !== undefined) load.nullTtl = nullTtl;\n if (unless !== undefined) load.unless = unless;\n if (lock !== undefined) load.lock = lock;\n return load;\n}\n\nfunction loadOptionsOf<T>(options: GetOrSetOptions<T>): LoadOptions<T> {\n return withLoadPolicy<LoadOptions<T>, T>(writeOptionsOf(options), options);\n}\n\nfunction loadManyOptionsOf<T>(options: GetOrSetManyOptions<T>): BatchLoadOptions<T> {\n return withLoadPolicy<BatchLoadOptions<T>, T>(writeManyOptionsOf(options), options);\n}\n\n/**\n * The programmatic cache API, injected from `CacheModule`. Cache failures (store, serializer,\n * key, lock) are reported as `error` events and do not reject a call, with one exception:\n * `invalidateTags` rejects with the store's error when a tag version write fails, so the caller\n * knows the invalidation did not happen. Invalid arguments reject with `CacheConfigError`.\n */\nexport class CacheService {\n /** Created by `CacheModule`; do not construct it, inject it. */\n constructor(private readonly engine: CacheEngine) {}\n\n /**\n * Reads a value; returns `undefined` on a miss.\n *\n * Strategy options pick the read command (`sliding` touches the entry) and how the entry is\n * classified; a stale `swr` entry is returned as a hit with `stale: true`. `get` never refreshes.\n *\n * With `strategy: 'sliding'` the entry's window is reset to `defaults.ttl`, not to the `ttl` it\n * was written with, because `getAndTouch` needs the TTL before the entry is read.\n */\n get<T>(key: string, options: KeyOptions & StrategyOptions = {}): Promise<T | undefined> {\n return this.engine.get<T>(refOf(key, options), strategyOptionsOf(options));\n }\n\n /**\n * Writes a value with `options.ttl` (else `defaults.ttl`). An empty value (`null` or\n * `undefined`) is written as is, under the `fixed` strategy.\n */\n set<T>(key: string, value: T, options: WriteOptions<T> = {}): Promise<void> {\n return this.engine.set(refOf(key, options), value, writeOptionsOf(options));\n }\n\n /** Deletes one key or several keys of one namespace and store, with one store call. */\n delete(key: string | readonly string[], options: KeyOptions = {}): Promise<void> {\n return this.engine.delete(scopeOf(options), typeof key === 'string' ? [key] : key);\n }\n\n /**\n * Deletes every entry of `namespace` in the store (`options.store`, else `default`): the\n * store's `clear` of its key prefix, or one version token change for a versioned namespace.\n * Rejects `CacheConfigError` for `''`.\n */\n clear(namespace: string, options: { store?: string } = {}): Promise<void> {\n return this.engine.clear(namespace, options.store);\n }\n\n /**\n * Returns the cached value, or runs `loader` once per key across concurrent callers (and, with\n * `lock`, across instances), stores its result and returns it. A loader error rejects the\n * call; nothing is stored. Under `swr` a stale value is served while one refresh runs.\n */\n getOrSet<T>(key: string, loader: () => Promise<T>, options: GetOrSetOptions<T> = {}): Promise<T> {\n return this.engine.getOrSet(refOf(key, options), loader, loadOptionsOf(options));\n }\n\n /**\n * Invalidates every entry stamped with one of `tags` in the store (`options.store`, else\n * `default`), across namespaces: each tag gets a new version, so those entries read as misses.\n * This instance sees it at once; other instances once their cached version expires\n * (`versioning.cacheTtl`). Tags are plain strings, used as is.\n *\n * Rejects with `CacheConfigError` when `tags` is not a non-empty array of non-empty strings,\n * has more than 32 tags after de-duplication, or the store is unknown. When a version write\n * fails, every tag is still tried; an `error` event with operation `'version'` is emitted and\n * the call rejects with the first failure.\n */\n invalidateTags(tags: readonly string[], options: { store?: string } = {}): Promise<void> {\n // A JavaScript caller may pass null: it means the default store, never a synchronous throw.\n const { store } = (options as { store?: string } | null) ?? {};\n return this.engine.invalidateTags(tags, store);\n }\n\n /**\n * Reads several keys of one namespace and store; results follow `keys`, `undefined` for a\n * miss. One store read for the batch (MGET on Redis), except with `strategy: 'sliding'`,\n * which touches each entry with its own `getAndTouch`.\n */\n getMany<T>(\n keys: readonly string[],\n options: KeyOptions & StrategyOptions = {},\n ): Promise<(T | undefined)[]> {\n return this.engine.getMany<T>(scopeOf(options), keys, strategyOptionsOf(options));\n }\n\n /** Writes several entries, each as `set` would, with one store call when the store allows. */\n setMany<T>(\n entries: readonly (readonly [key: string, value: T])[],\n options: WriteManyOptions<T> = {},\n ): Promise<void> {\n return this.engine.setMany(scopeOf(options), entries, writeManyOptionsOf(options));\n }\n\n /**\n * `getOrSet` for several keys: hits are served, and the misses are loaded with one\n * `loader(missing)` call that resolves a Map. A key the loader omits is treated as\n * `undefined`; keys it was not asked for are ignored. `lock: true` is not supported.\n */\n getOrSetMany<T>(\n keys: readonly string[],\n loader: (missing: string[]) => Promise<ReadonlyMap<string, T>>,\n options: GetOrSetManyOptions<T> = {},\n ): Promise<(T | undefined)[]> {\n return this.engine.getOrSetMany(scopeOf(options), keys, loader, loadManyOptionsOf(options));\n }\n}\n","import { Logger, type OnModuleInit } from '@nestjs/common';\nimport type { DiscoveryService } from '@nestjs/core';\nimport type { CacheEngine } from '../core/cache-engine.js';\nimport { getCacheMetadata, memberName, type CacheMetadataEntry } from '../decorators/metadata.js';\nimport { CacheConfigError } from '../errors.js';\n\n/**\n * `<method>\\u0000<store>` pairs already warned about, per class constructor, so repeated\n * modules and explorers warn once per method and store.\n */\nconst warnedLocks = new WeakMap<object, Set<string>>();\n\nconst KIND_LABELS: Record<CacheMetadataEntry['kind'], string> = {\n cacheable: '@Cacheable',\n put: '@CachePut',\n evict: '@CacheEvict',\n http: '@HttpCache',\n};\n\n/**\n * Validates, at app startup, that every store named by a cache decorator is configured.\n * Reads metadata from `wrapper.metatype`, so request-scoped providers without an instance are covered.\n *\n * Known limitation: with several `CacheModule.forRoot` calls in one app, each explorer checks\n * every provider and controller in the app against its own stores.\n */\nexport class CacheExplorer implements OnModuleInit {\n private readonly logger = new Logger('CacheModule');\n\n constructor(\n private readonly discovery: DiscoveryService,\n private readonly engine: CacheEngine,\n ) {}\n\n onModuleInit(): void {\n const wrappers = [...this.discovery.getProviders(), ...this.discovery.getControllers()];\n for (const wrapper of wrappers) {\n const { metatype } = wrapper;\n if (typeof metatype !== 'function' || wrapper.isFactory) continue;\n for (const entry of getCacheMetadata(metatype)) {\n if (this.engine.hasStore(entry.store)) {\n // At 'off' nothing is logged, and nothing is marked as warned for another module.\n if (this.engine.logLevel === 'off') continue;\n const warned = warnedLocks.get(metatype) ?? new Set<string>();\n warnedLocks.set(metatype, warned);\n const warnKey = `${String(entry.method)}\\u0000${entry.store}`;\n if (entry.lock === true && !this.engine.hasLock(entry.store) && !warned.has(warnKey)) {\n warned.add(warnKey);\n this.logger.warn(\n `${memberName(metatype.name, entry.method)} sets lock: true but cache store \"${entry.store}\" ` +\n 'has no distributed lock; falling back to in-process coalescing',\n );\n }\n continue;\n }\n throw new CacheConfigError(\n `Unknown cache store \"${entry.store}\" in ${memberName(metatype.name, entry.method)} ` +\n `(${KIND_LABELS[entry.kind]}). Configured stores: ${this.engine.storeNames().join(', ')}`,\n );\n }\n }\n }\n}\n","import type { OnApplicationShutdown, OnModuleInit } from '@nestjs/common';\nimport type { CacheEvents } from '../core/events.js';\nimport type { CacheLogger } from './cache.logger.js';\nimport type { ResolvedCacheOptions } from './cache.options.js';\n\nfunction messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/** `namespace:key`, or the bare key when there is no namespace. */\nfunction fullKey(namespace: string | undefined, key: string): string {\n return namespace === undefined ? key : `${namespace}:${key}`;\n}\n\nexport class CacheLifecycle implements OnModuleInit, OnApplicationShutdown {\n constructor(\n private readonly options: ResolvedCacheOptions,\n private readonly events: CacheEvents,\n private readonly logger: CacheLogger,\n ) {}\n\n onModuleInit(): void {\n const { level } = this.logger;\n // Logging listeners go first, so errors emitted while binding stores are logged.\n if (level !== 'off') this.logErrorsAndBreakers();\n if (level === 'debug') this.logEventsAtDebug();\n if (this.options.defaults.lock.enabled) {\n for (const [name, store] of this.options.stores) {\n if (store.lock !== undefined) continue;\n this.logger.warn(\n `Cache store \"${name}\" has no distributed lock; defaults.lock.enabled falls back to in-process coalescing`,\n );\n }\n }\n for (const [name, store] of this.options.stores) {\n store.bind?.(this.events.sinkFor(name, level));\n }\n }\n\n async onApplicationShutdown(): Promise<void> {\n for (const [name, store] of this.options.stores) {\n try {\n await store.close?.();\n } catch (error) {\n this.logger.error(`Failed to close cache store \"${name}\": ${messageOf(error)}`);\n }\n }\n }\n\n private logErrorsAndBreakers(): void {\n const { events, logger } = this;\n events.on('error', ({ store, operation, error }) => {\n logger.storeError(store, operation, error);\n });\n events.on('breaker', ({ store, state }) => {\n if (state === 'open') logger.warn(`Circuit breaker for cache store \"${store}\" opened`);\n else if (state === 'closed') logger.log(`Circuit breaker for cache store \"${store}\" closed`);\n });\n }\n\n private logEventsAtDebug(): void {\n const { events, logger } = this;\n events.on('hit', ({ store, namespace, key, stale }) => {\n logger.debug(`Cache hit ${store} ${fullKey(namespace, key)}${stale ? ' stale' : ''}`);\n });\n events.on('miss', ({ store, namespace, key }) => {\n logger.debug(`Cache miss ${store} ${fullKey(namespace, key)}`);\n });\n events.on('set', ({ store, namespace, key, ttl }) => {\n logger.debug(`Cache set ${store} ${fullKey(namespace, key)} ttl=${String(ttl)}ms`);\n });\n events.on('delete', ({ store, namespace, keys }) => {\n const joined = keys.map((key) => fullKey(namespace, key)).join(',');\n logger.debug(`Cache delete ${store} ${joined}`);\n });\n events.on('clear', ({ store, namespace }) => {\n logger.debug(`Cache clear ${store} ${namespace}`);\n });\n events.on('load', ({ store, namespace, key, durationMs, success }) => {\n const outcome = success ? 'ok' : 'failed';\n logger.debug(\n `Cache load ${store} ${fullKey(namespace, key)} ${String(durationMs)}ms ${outcome}`,\n );\n });\n events.on('lock', ({ store, namespace, key, waitedMs, acquired }) => {\n const outcome = acquired ? 'acquired' : 'not acquired';\n logger.debug(\n `Cache lock ${store} ${fullKey(namespace, key)} waited ${String(waitedMs)}ms ${outcome}`,\n );\n });\n }\n}\n","import { Logger } from '@nestjs/common';\nimport type { CacheLogLevel, LogOperation } from '../core/events.js';\n\nfunction messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nconst WINDOW_MS = 30_000;\n\n/**\n * @internal The module's logger, provided under `CACHE_LOGGER`. Every library log line that\n * depends on `logging.level` goes through it; nothing is written at `'off'`.\n */\nexport class CacheLogger {\n private readonly logger = new Logger('CacheModule');\n\n private readonly throttle = new Map<string, { windowStart: number; suppressed: number }>();\n\n constructor(readonly level: CacheLogLevel) {}\n\n /**\n * Logs at most one line per (store, operation) every 30 000 ms; the next line reports how\n * many were suppressed. `error` for delete, clear and tracing, `warn` for every other\n * operation.\n */\n storeError(store: string, operation: LogOperation, error: unknown): void {\n if (this.level === 'off') return;\n const key = `${store}\\u0000${operation}`;\n const now = Date.now();\n const entry = this.throttle.get(key);\n if (entry && now - entry.windowStart < WINDOW_MS) {\n entry.suppressed += 1;\n return;\n }\n const suffix =\n entry && entry.suppressed > 0\n ? ` (+${String(entry.suppressed)} similar errors suppressed)`\n : '';\n this.throttle.set(key, { windowStart: now, suppressed: 0 });\n const text = `Cache ${operation} failed on store \"${store}\": ${messageOf(error)}${suffix}`;\n if (operation === 'delete' || operation === 'clear' || operation === 'tracing') {\n this.logger.error(text);\n } else {\n this.logger.warn(text);\n }\n }\n\n error(message: string): void {\n if (this.level !== 'off') this.logger.error(message);\n }\n\n warn(message: string): void {\n if (this.level !== 'off') this.logger.warn(message);\n }\n\n log(message: string): void {\n if (this.level !== 'off') this.logger.log(message);\n }\n\n debug(message: string): void {\n if (this.level === 'debug') this.logger.debug(message);\n }\n}\n","import type { FactoryProvider, ModuleMetadata } from '@nestjs/common';\nimport type { CacheLogLevel } from '../core/events.js';\nimport { isReservedNamespace } from '../core/key-builder.js';\nimport { CacheConfigError } from '../errors.js';\nimport { jsonSerializer, type Serializer } from '../serializers/json.serializer.js';\nimport type { CacheStore } from '../stores/cache-store.interface.js';\nimport { memoryStore } from '../stores/memory.store.js';\n\n/** `defaults.lock`: the distributed lock taken on a miss, for stores that have one. */\nexport interface CacheLockDefaults {\n /**\n * Whether `getOrSet`, `@Cacheable` and `@HttpCache` lock by default; a call's `lock` overrides\n * it. Default `false`.\n */\n enabled?: boolean;\n /** How long a lock is held at most, in ms. Default 10 000. */\n ttl?: number;\n /**\n * How long a caller that did not get the lock waits for the holder's value, in ms; then it\n * loads without the lock. Default 3 000.\n */\n waitTimeout?: number;\n /** Delay between two re-reads of the entry while waiting, in ms. Default 50. */\n retryDelay?: number;\n}\n\n/** `defaults`: what a call or decorator that does not set an option uses. */\nexport interface CacheDefaults {\n /** Entry TTL in ms. Default 60 000. */\n ttl?: number;\n /** Random TTL spread: `ttl x (1 + r)`, `r` in `[-jitter, +jitter]`; in `[0, 1)`. Default 0. */\n jitter?: number;\n /** Whether `null` and `undefined` results are stored. Default `false`. */\n cacheNull?: boolean;\n /** TTL of a stored empty value, in ms. Default 30 000. */\n nullTtl?: number;\n lock?: CacheLockDefaults;\n}\n\n/** Options of `CacheModule.forRoot`, and the value `forRootAsync`'s `useFactory` resolves. */\nexport interface CacheModuleOptions {\n /** Prepended to every key as `<prefix>:`. Default none. */\n prefix?: string;\n /**\n * Named stores; `default` is required when `stores` is set. Default\n * `{ default: memoryStore() }`.\n */\n stores?: { default: CacheStore; [name: string]: CacheStore };\n defaults?: CacheDefaults;\n /** Turns entry envelopes into the strings stores hold. Default `jsonSerializer`. */\n serializer?: Serializer;\n /** `level` defaults to `'error'`. */\n logging?: { level?: CacheLogLevel };\n /**\n * Percent-encodes `%` and `:` in string and number arguments rendered into template keys.\n * Defaults to `false`; key callbacks are never escaped.\n */\n escapeKeyArgs?: boolean;\n /**\n * Namespaces with `versioned: true` get O(1) `clear` through a version token in their keys.\n * Matching is exact: a sub-namespace such as `users:admin` does not follow a versioned `users`.\n */\n namespaces?: { [namespace: string]: { versioned?: boolean } };\n /** `cacheTtl` (ms, default 1000) is how long a version token is cached in this process. */\n versioning?: { cacheTtl?: number };\n}\n\n/** Options of `CacheModule.forRootAsync`: `useFactory` resolves the `CacheModuleOptions`. */\nexport interface CacheModuleAsyncOptions {\n /** Registers the module globally. Default `false`. */\n isGlobal?: boolean;\n imports?: ModuleMetadata['imports'];\n inject?: FactoryProvider['inject'];\n useFactory: (...args: never[]) => CacheModuleOptions | Promise<CacheModuleOptions>;\n}\n\nexport interface ResolvedDefaults {\n ttl: number;\n jitter: number;\n cacheNull: boolean;\n nullTtl: number;\n lock: { enabled: boolean; ttl: number; waitTimeout: number; retryDelay: number };\n}\n\nexport interface ResolvedCacheOptions {\n prefix: string | undefined;\n stores: ReadonlyMap<string, CacheStore>;\n defaults: ResolvedDefaults;\n serializer: Serializer;\n logging: { level: CacheLogLevel };\n escapeKeyArgs: boolean;\n versionedNamespaces: ReadonlySet<string>;\n versionCacheTtl: number;\n}\n\nconst DEFAULT_TTL = 60_000;\nconst DEFAULT_NULL_TTL = 30_000;\n\nfunction invalid(path: string, value: unknown, rule: string): CacheConfigError {\n return new CacheConfigError(`Invalid cache option ${path}: ${String(value)} (${rule})`);\n}\n\nfunction positiveDuration(path: string, value: number | undefined, fallback: number): number {\n if (value === undefined) return fallback;\n if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {\n throw invalid(path, value, 'must be a finite number > 0');\n }\n return value;\n}\n\nfunction cacheNullOf(value: boolean | undefined): boolean {\n if (value === undefined) return false;\n if (typeof value !== 'boolean') throw invalid('defaults.cacheNull', value, 'must be a boolean');\n return value;\n}\n\nfunction lockEnabled(value: boolean | undefined): boolean {\n if (value === undefined) return false;\n if (typeof value !== 'boolean')\n throw invalid('defaults.lock.enabled', value, 'must be a boolean');\n return value;\n}\n\n/** `undefined` means the defaults; anything else that is not a plain object is rejected. */\nfunction lockDefaults(value: unknown): CacheLockDefaults {\n if (value === undefined) return {};\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw invalid('defaults.lock', value, 'must be an object');\n }\n return value;\n}\n\nconst LOG_LEVELS: readonly unknown[] = ['off', 'error', 'debug'] satisfies CacheLogLevel[];\n\nfunction isLogLevel(value: unknown): value is CacheLogLevel {\n return LOG_LEVELS.includes(value);\n}\n\n/** `undefined` means the default level; anything else that is not a plain object is rejected. */\nfunction loggingOf(value: unknown): { level: CacheLogLevel } {\n if (value === undefined) return { level: 'error' };\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw invalid('logging', value, 'must be an object');\n }\n const { level } = value as { level?: unknown };\n if (level === undefined) return { level: 'error' };\n if (!isLogLevel(level)) {\n throw invalid('logging.level', level, \"must be 'off', 'error' or 'debug'\");\n }\n return { level };\n}\n\nfunction jitterOf(value: number | undefined): number {\n if (value === undefined) return 0;\n if (typeof value !== 'number' || !Number.isFinite(value) || value < 0 || value >= 1) {\n throw invalid('defaults.jitter', value, 'must be a number >= 0 and < 1');\n }\n return value;\n}\n\nfunction isCacheStore(value: unknown): value is CacheStore {\n if (typeof value !== 'object' || value === null) return false;\n const candidate = value as Record<string, unknown>;\n return ['get', 'set', 'delete', 'clear'].every((m) => typeof candidate[m] === 'function');\n}\n\nfunction resolveStores(stores: CacheModuleOptions['stores']): ReadonlyMap<string, CacheStore> {\n if (stores === undefined) return new Map([['default', memoryStore()]]);\n if (!('default' in stores)) {\n throw new CacheConfigError('Invalid cache option stores: missing required store \"default\"');\n }\n const map = new Map<string, CacheStore>();\n for (const [name, store] of Object.entries(stores)) {\n if (!isCacheStore(store)) {\n throw new CacheConfigError(`Cache store \"${name}\" does not implement CacheStore`);\n }\n map.set(name, store);\n }\n return map;\n}\n\nfunction escapeKeyArgsOf(value: unknown): boolean {\n if (value === undefined) return false;\n if (typeof value !== 'boolean') throw invalid('escapeKeyArgs', value, 'must be a boolean');\n return value;\n}\n\nfunction versionedNamespacesOf(value: unknown): ReadonlySet<string> {\n const set = new Set<string>();\n if (value === undefined) return set;\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw invalid('namespaces', value, 'must be an object');\n }\n for (const [ns, entry] of Object.entries(value)) {\n if (isReservedNamespace(ns)) {\n throw new CacheConfigError(\n `Invalid cache option namespaces: ${ns} (names starting with \"__\" are reserved)`,\n );\n }\n if (typeof entry !== 'object' || entry === null || Array.isArray(entry)) {\n throw invalid(`namespaces.${ns}`, entry, 'must be an object');\n }\n const { versioned } = entry as { versioned?: unknown };\n if (versioned === undefined) continue;\n if (typeof versioned !== 'boolean') {\n throw invalid(`namespaces.${ns}.versioned`, versioned, 'must be a boolean');\n }\n if (versioned) set.add(ns);\n }\n return set;\n}\n\nfunction versionCacheTtlOf(value: unknown): number {\n if (value === undefined) return 1_000;\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw invalid('versioning', value, 'must be an object');\n }\n const { cacheTtl } = value as { cacheTtl?: unknown };\n if (cacheTtl === undefined) return 1_000;\n if (\n typeof cacheTtl !== 'number' ||\n !Number.isFinite(cacheTtl) ||\n cacheTtl < 1 ||\n cacheTtl > 2_147_483_647\n ) {\n throw invalid(\n 'versioning.cacheTtl',\n cacheTtl,\n 'must be a finite number between 1 and 2147483647',\n );\n }\n return cacheTtl;\n}\n\nexport function resolveOptions(options: CacheModuleOptions = {}): ResolvedCacheOptions {\n const defaults = options.defaults ?? {};\n const lock = lockDefaults(defaults.lock);\n return {\n prefix: options.prefix === undefined || options.prefix === '' ? undefined : options.prefix,\n stores: resolveStores(options.stores),\n defaults: {\n ttl: positiveDuration('defaults.ttl', defaults.ttl, DEFAULT_TTL),\n jitter: jitterOf(defaults.jitter),\n cacheNull: cacheNullOf(defaults.cacheNull),\n nullTtl: positiveDuration('defaults.nullTtl', defaults.nullTtl, DEFAULT_NULL_TTL),\n lock: {\n enabled: lockEnabled(lock.enabled),\n ttl: positiveDuration('defaults.lock.ttl', lock.ttl, 10_000),\n waitTimeout: positiveDuration('defaults.lock.waitTimeout', lock.waitTimeout, 3_000),\n retryDelay: positiveDuration('defaults.lock.retryDelay', lock.retryDelay, 50),\n },\n },\n serializer: options.serializer ?? jsonSerializer,\n logging: loggingOf(options.logging),\n escapeKeyArgs: escapeKeyArgsOf(options.escapeKeyArgs),\n versionedNamespaces: versionedNamespacesOf(options.namespaces),\n versionCacheTtl: versionCacheTtlOf(options.versioning),\n };\n}\n","import { randomUUID } from 'node:crypto';\nimport type { LockHandle, LockProvider } from './cache-store.interface.js';\nimport type { RedisClientAdapter } from './redis-client.adapter.js';\n\n/** Lock over Redis `SET NX PX` with a token-checked release. */\nexport class RedisLock implements LockProvider {\n constructor(\n private readonly adapter: Required<Pick<RedisClientAdapter, 'setIfAbsent' | 'deleteIfEquals'>>,\n ) {}\n\n /** `key` is the complete lock key, used verbatim. `ttlMs` is rounded up to an integer >= 1, as `ioredisAdapter` rounds its TTLs. */\n async acquire(key: string, ttlMs: number): Promise<LockHandle | undefined> {\n const token = randomUUID();\n const acquired = await this.adapter.setIfAbsent(key, token, Math.max(1, Math.ceil(ttlMs)));\n if (!acquired) return undefined;\n let released = false;\n return {\n release: async () => {\n if (released) return;\n released = true;\n await this.adapter.deleteIfEquals(key, token);\n },\n };\n }\n}\n","const SLOTS = 16384;\n\nconst TABLE: readonly number[] = (() => {\n const table: number[] = [];\n for (let byte = 0; byte < 256; byte += 1) {\n let crc = byte << 8;\n for (let bit = 0; bit < 8; bit += 1) {\n crc = crc & 0x8000 ? ((crc << 1) ^ 0x1021) & 0xffff : (crc << 1) & 0xffff;\n }\n table.push(crc);\n }\n return table;\n})();\n\nfunction crc16(bytes: Uint8Array): number {\n let crc = 0;\n for (const byte of bytes) {\n crc = ((crc << 8) & 0xffff) ^ (TABLE[((crc >> 8) ^ byte) & 0xff] ?? 0);\n }\n return crc;\n}\n\n/**\n * Redis Cluster hash slot of `key`: CRC16-XMODEM of its UTF-8 bytes (or of the first non-empty\n * `{...}` hash tag) mod 16384.\n */\nexport function keySlot(key: string): number {\n const bytes = Buffer.from(key, 'utf8');\n const open = bytes.indexOf(0x7b);\n if (open !== -1) {\n const close = bytes.indexOf(0x7d, open + 1);\n if (close > open + 1) return crc16(bytes.subarray(open + 1, close)) % SLOTS;\n }\n return crc16(bytes) % SLOTS;\n}\n","import { keySlot } from './key-slot.js';\n\nfunction groupBySlot(keys: readonly string[]): Map<number, string[]> {\n const groups = new Map<number, string[]>();\n for (const key of keys) {\n const slot = keySlot(key);\n const group = groups.get(slot);\n if (group === undefined) groups.set(slot, [key]);\n else group.push(key);\n }\n return groups;\n}\n\n/** One `mget` per slot, in parallel; resolves the values in input order. Any rejection rejects. */\nexport async function mgetBySlot(\n keys: readonly string[],\n mget: (slotKeys: string[]) => Promise<(string | undefined)[]>,\n): Promise<(string | undefined)[]> {\n if (keys.length === 0) return [];\n const byKey = new Map<string, string | undefined>();\n await Promise.all(\n [...groupBySlot(keys).values()].map(async (slotKeys) => {\n const values = await mget(slotKeys);\n slotKeys.forEach((key, i) => byKey.set(key, values[i]));\n }),\n );\n return keys.map((key) => byKey.get(key));\n}\n\n/** One `unlink` per slot via `allSettled`, then rethrows the first rejection. */\nexport async function unlinkBySlot(\n keys: readonly string[],\n unlink: (slotKeys: string[]) => Promise<void>,\n): Promise<void> {\n if (keys.length === 0) return;\n const results = await Promise.allSettled([...groupBySlot(keys).values()].map((g) => unlink(g)));\n for (const result of results) {\n if (result.status === 'rejected') throw result.reason;\n }\n}\n\n/**\n * Scans each node to cursor '0' in order and yields the non-empty pages. With `emptyMessage`,\n * zero nodes reject with it on the first iteration: a cluster `clear` that scanned no master\n * would succeed without deleting anything.\n */\nexport async function* scanNodes<N>(\n nodes: readonly N[],\n scan: (node: N, cursor: string) => Promise<{ cursor: string; keys: string[] }>,\n emptyMessage?: string,\n): AsyncIterable<string[]> {\n if (nodes.length === 0 && emptyMessage !== undefined) throw new Error(emptyMessage);\n for (const node of nodes) {\n let cursor = '0';\n do {\n const page = await scan(node, cursor);\n cursor = page.cursor;\n if (page.keys.length > 0) yield page.keys;\n } while (cursor !== '0');\n }\n}\n","/**\n * Deletes the key only when it still holds the caller's token (the `RedisLock` release). Shared by\n * the ioredis and node-redis adapters.\n */\nexport const RELEASE_SCRIPT =\n \"if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end\";\n\n/**\n * Minimal Redis surface the cache needs; implemented over ioredis by `ioredisAdapter` and over\n * node-redis by `nodeRedisAdapter`.\n *\n * Implemented by you. In 1.x, members are only added as optional, and the library checks that\n * they exist before calling them.\n *\n * `redisStore` tells an adapter from an ioredis client by checking that `createSubscriber` is a\n * function.\n */\nexport interface RedisClientAdapter {\n get(key: string): Promise<string | undefined>;\n /** SET key value PX ttlMs */\n set(key: string, value: string, ttlMs: number): Promise<void>;\n /** GETEX key PX ttlMs */\n getex(key: string, ttlMs: number): Promise<string | undefined>;\n /**\n * An empty list sends no command. The keys may belong to several hash slots; a Cluster adapter\n * must split the command per slot.\n */\n unlink(keys: readonly string[]): Promise<void>;\n scan(cursor: string, match: string, count: number): Promise<{ cursor: string; keys: string[] }>;\n /**\n * Optional. SET key value PX ttlMs NX. Resolves `true` when the key was set, `false` when it\n * already existed.\n */\n setIfAbsent?(key: string, value: string, ttlMs: number): Promise<boolean>;\n /**\n * Optional. Deletes `key` only if it holds `value`, atomically. Resolves `true` when it\n * deleted the key.\n */\n deleteIfEquals?(key: string, value: string): Promise<boolean>;\n /** Optional. Sends a PING; resolves when Redis answers, rejects otherwise. */\n ping?(): Promise<void>;\n /**\n * Optional. MGET; resolves the values in key order, `undefined` for a missing key. An empty\n * list sends no command and resolves `[]`. The keys may belong to several hash slots; a\n * Cluster adapter must split the command per slot.\n */\n mget?(keys: readonly string[]): Promise<(string | undefined)[]>;\n /**\n * Optional. Every key matching `match`, in pages, across every node that holds data (each master\n * of a cluster). When present, `RedisStore.clear` uses it instead of the `scan` cursor loop.\n */\n scanIterator?(match: string, count: number): AsyncIterable<string[]>;\n publish(channel: string, message: string): Promise<void>;\n createSubscriber(): RedisSubscriberAdapter;\n}\n\n/**\n * The subscriber connection of a `RedisClientAdapter`, used by the invalidation bus.\n *\n * Implemented by you. In 1.x, members are only added as optional, and the library checks that\n * they exist before calling them.\n */\nexport interface RedisSubscriberAdapter {\n /**\n * Subscribes to `channel`. If it rejects (for example Redis was unreachable), the adapter\n * should subscribe again once the connection is ready, and a later call retries too.\n */\n subscribe(channel: string, onMessage: (message: string) => void): Promise<void>;\n /**\n * Fires on every 'ready' after the first (the first is the initial connect), and when a\n * subscription that had failed is established later: messages may have been missed meanwhile.\n */\n onReconnect(handler: () => void): void;\n /**\n * Optional. Registers a handler for errors of the dedicated connection (connection errors,\n * failed re-subscribes). Handlers must not throw.\n */\n onError?(handler: (error: unknown) => void): void;\n /** Quits the dedicated connection; calling it again is a no-op. Never rejects. */\n close(): Promise<void>;\n}\n","import type { RedisSubscriberAdapter } from './redis-client.adapter.js';\n\n/** How long a subscriber's `close` waits for a graceful close before it drops the connection. */\nexport const CLOSE_TIMEOUT_MS = 1_000;\n\n/** Calls every handler; a throwing handler never reaches the others or the client's emitter. */\nexport function notifyAll<A extends unknown[]>(\n handlers: readonly ((...args: A) => void)[],\n ...args: A\n): void {\n for (const handler of handlers) {\n try {\n handler(...args);\n } catch {\n // swallowed: this runs inside the client's event listeners\n }\n }\n}\n\n/**\n * Runs `close`, or `destroy` when `close` rejects, throws or has not settled after\n * `CLOSE_TIMEOUT_MS`. Never rejects; the timer is unref'd and always cleared.\n */\nexport async function closeWithTimeout(close: () => unknown, destroy: () => void): Promise<void> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timedOut = new Promise<boolean>((resolve) => {\n timer = setTimeout(() => {\n resolve(true);\n }, CLOSE_TIMEOUT_MS);\n timer.unref();\n });\n // The executor turns a synchronous throw into a rejection.\n const closed = new Promise((resolve) => {\n resolve(close());\n }).then(\n () => false,\n () => true,\n );\n const force = await Promise.race([closed, timedOut]);\n clearTimeout(timer);\n if (!force) return;\n try {\n destroy();\n } catch {\n // close never rejects\n }\n}\n\n/** What a client library supplies to `createSubscriptionTracker`. */\nexport interface SubscriberTransport {\n /** Sends one SUBSCRIBE (or SSUBSCRIBE) for `channel`. May throw synchronously. */\n subscribe(channel: string): Promise<unknown>;\n /** Closes the dedicated connection; called at most once. Must never reject. */\n close(): Promise<void>;\n}\n\n/** The shared subscriber state; the adapter wires its connection's events to it. */\nexport interface SubscriptionTracker {\n readonly subscriber: RedisSubscriberAdapter;\n /** Hands a message to the channel's handler. A throwing handler is swallowed, so client listeners never throw. */\n deliver(channel: string, message: string): void;\n /** For each 'ready' event of the connection. */\n ready(): void;\n /** For each 'error' event of the connection. */\n error(error: unknown): void;\n}\n\ninterface Subscription {\n status: 'pending' | 'ok' | 'failed';\n done: Promise<void>;\n}\n\n/**\n * The `RedisSubscriberAdapter` retry contract, shared by the client adapters. Clients restore a\n * channel on reconnect only once its SUBSCRIBE was confirmed, so channels whose SUBSCRIBE failed are\n * sent again on 'ready', and a later `subscribe` call retries too. `onReconnect` fires from the\n * second 'ready' onward, and when a failed channel recovers.\n */\nexport function createSubscriptionTracker(transport: SubscriberTransport): SubscriptionTracker {\n const handlers = new Map<string, (message: string) => void>();\n /** The latest SUBSCRIBE per channel. */\n const subscriptions = new Map<string, Subscription>();\n const reconnectHandlers: Array<() => void> = [];\n const errorHandlers: Array<(error: unknown) => void> = [];\n let readyCount = 0;\n let closing: Promise<void> | undefined;\n\n const send = (channel: string): Promise<void> => {\n const subscription: Subscription = { status: 'pending', done: Promise.resolve() };\n // The executor turns a synchronous throw into a rejection, so nothing throws into the client.\n const sent = new Promise((resolve) => {\n resolve(transport.subscribe(channel));\n });\n subscription.done = sent.then(\n () => {\n subscription.status = 'ok';\n },\n (error: unknown) => {\n subscription.status = 'failed';\n throw error;\n },\n );\n subscriptions.set(channel, subscription);\n return subscription.done;\n };\n\n return {\n subscriber: {\n subscribe(channel, onMessage) {\n handlers.set(channel, onMessage);\n const current = subscriptions.get(channel);\n if (current !== undefined && current.status !== 'failed') return current.done;\n return send(channel);\n },\n onReconnect(handler) {\n reconnectHandlers.push(handler);\n },\n onError(handler) {\n errorHandlers.push(handler);\n },\n close() {\n closing ??= transport.close();\n return closing;\n },\n },\n deliver(channel, message) {\n try {\n handlers.get(channel)?.(message);\n } catch {\n // swallowed: a throwing handler must not reach the client's listener\n }\n },\n ready() {\n readyCount += 1;\n if (readyCount > 1) notifyAll(reconnectHandlers);\n if (closing !== undefined) return;\n for (const [channel, subscription] of subscriptions) {\n if (subscription.status !== 'failed') continue;\n // Messages published while the channel was not subscribed are lost: treat it as a reconnect.\n send(channel).then(\n () => {\n notifyAll(reconnectHandlers);\n },\n (error: unknown) => {\n notifyAll(errorHandlers, error);\n },\n );\n }\n },\n error(error) {\n notifyAll(errorHandlers, error);\n },\n };\n}\n","import { CacheConfigError } from '../errors.js';\nimport { mgetBySlot, scanNodes, unlinkBySlot } from './cluster-ops.js';\nimport { RELEASE_SCRIPT } from './redis-client.adapter.js';\nimport type { RedisClientAdapter, RedisSubscriberAdapter } from './redis-client.adapter.js';\nimport { closeWithTimeout, createSubscriptionTracker } from './subscriber-support.js';\n\n/** Re-exported for existing imports; the script lives in `redis-client.adapter.ts`. */\nexport { RELEASE_SCRIPT };\n\n/**\n * Structural subset of an ioredis client (v5 and v6). Declared by hand so the\n * library never imports ioredis.\n *\n * Satisfied by the client you pass in. In 1.x, members are only added as optional, and the\n * library checks that they exist before calling them.\n */\nexport interface IoredisLike {\n get(key: string): Promise<string | null>;\n set(key: string, value: string, mode: 'PX', ttlMs: number): Promise<unknown>;\n set(key: string, value: string, mode: 'PX', ttlMs: number, nx: 'NX'): Promise<'OK' | null>;\n eval(script: string, numKeys: number, ...args: string[]): Promise<unknown>;\n getex(key: string, mode: 'PX', ttlMs: number): Promise<string | null>;\n unlink(...keys: string[]): Promise<unknown>;\n scan(\n cursor: string,\n matchToken: 'MATCH',\n pattern: string,\n countToken: 'COUNT',\n count: number,\n ): Promise<[cursor: string, keys: string[]]>;\n publish(channel: string, message: string): Promise<unknown>;\n /** Optional. Used by health checks; the adapter exposes `ping` only when it exists. */\n ping?(): Promise<unknown>;\n /** Optional. Used by batch reads; the adapter exposes `mget` only when it exists. */\n mget?(...keys: string[]): Promise<(string | null)[]>;\n duplicate(): IoredisLike;\n subscribe(...channels: string[]): Promise<unknown>;\n on(event: string, listener: (...args: never[]) => void): unknown;\n quit(): Promise<unknown>;\n /** Optional. Closes the connection at once; used when `quit` does not settle in time. */\n disconnect?(): void;\n}\n\n/** The data commands a Cluster shares with a single-node client. */\ntype IoredisCommands = Omit<IoredisLike, 'duplicate' | 'on'>;\n\n/**\n * Structural subset of an ioredis `Cluster` (ioredis 5.6.0 or later, for sharded pub/sub).\n * Declared by hand so the library never imports ioredis. `ioredisAdapter` runs in Cluster mode\n * when `isCluster` is `true`.\n *\n * Satisfied by the client you pass in. In 1.x, members are only added as optional, and the\n * library checks that they exist before calling them.\n */\nexport interface IoredisClusterLike extends IoredisCommands {\n readonly isCluster: boolean;\n /** The master nodes; `scanIterator` scans each of them. */\n nodes(role: 'master'): IoredisLike[];\n spublish(channel: string, message: string): Promise<unknown>;\n ssubscribe(...channels: string[]): Promise<unknown>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Cluster's EventEmitter `on` takes `(...args: any[]) => void`, which `never[]` does not accept\n on(event: string, listener: (...args: any[]) => void): unknown;\n /** The adapter's subscriber is `duplicate([], { shardedSubscribers: true })`. */\n duplicate(\n startupNodes?: unknown[],\n options?: { shardedSubscribers?: boolean },\n ): IoredisClusterLike;\n}\n\nfunction isClusterClient(client: IoredisLike | IoredisClusterLike): client is IoredisClusterLike {\n return (client as Partial<IoredisClusterLike>).isCluster === true;\n}\n\n/**\n * Adapts an ioredis client or Cluster to `RedisClientAdapter`. `redisStore` does this itself;\n * call it to wrap or decorate the adapter.\n */\nexport function ioredisAdapter(client: IoredisLike | IoredisClusterLike): RedisClientAdapter {\n const adapter: RedisClientAdapter = {\n async get(key) {\n return (await client.get(key)) ?? undefined;\n },\n async set(key, value, ttlMs) {\n await client.set(key, value, 'PX', Math.ceil(ttlMs));\n },\n async getex(key, ttlMs) {\n return (await client.getex(key, 'PX', Math.ceil(ttlMs))) ?? undefined;\n },\n async setIfAbsent(key, value, ttlMs) {\n return (await client.set(key, value, 'PX', ttlMs, 'NX')) === 'OK';\n },\n async deleteIfEquals(key, value) {\n return (await client.eval(RELEASE_SCRIPT, 1, key, value)) === 1;\n },\n ...(isClusterClient(client) ? clusterCommands(client) : singleNodeCommands(client)),\n };\n // Optional members exist only when the client has them, so `'ping' in adapter` is truthful.\n if (typeof client.ping === 'function') {\n adapter.ping = async () => {\n await client.ping?.();\n };\n }\n if (typeof client.mget === 'function') {\n const mget = async (keys: readonly string[]): Promise<(string | undefined)[]> => {\n if (keys.length === 0) return [];\n const values = (await client.mget?.(...keys)) ?? [];\n return keys.map((_, index) => values[index] ?? undefined);\n };\n // A Cluster rejects a multi-key command across slots (CROSSSLOT): one MGET per slot.\n adapter.mget = isClusterClient(client) ? (keys) => mgetBySlot(keys, mget) : mget;\n }\n return adapter;\n}\n\ntype KeyspaceCommands = Pick<\n RedisClientAdapter,\n 'unlink' | 'scan' | 'publish' | 'createSubscriber' | 'scanIterator'\n>;\n\nfunction singleNodeCommands(client: IoredisLike): KeyspaceCommands {\n return {\n async unlink(keys) {\n if (keys.length === 0) return;\n await client.unlink(...keys);\n },\n async scan(cursor, match, count) {\n const [next, keys] = await client.scan(cursor, 'MATCH', match, 'COUNT', count);\n return { cursor: next, keys };\n },\n async publish(channel, message) {\n await client.publish(channel, message);\n },\n createSubscriber() {\n return createSubscriber(client.duplicate(), false);\n },\n };\n}\n\n/** Spec 3.3: multi-key commands per slot, SCAN on every master, sharded pub/sub. */\nfunction clusterCommands(client: IoredisClusterLike): KeyspaceCommands {\n return {\n unlink(keys) {\n return unlinkBySlot(keys, async (slotKeys) => {\n await client.unlink(...slotKeys);\n });\n },\n scan() {\n return Promise.reject(\n new CacheConfigError(\n 'ioredisAdapter: scan is not supported on a Redis Cluster client, because one cursor covers one node; use scanIterator, which scans every master',\n ),\n );\n },\n scanIterator(match, count) {\n return scanMasters(client, match, count);\n },\n async publish(channel, message) {\n await client.spublish(channel, message);\n },\n createSubscriber() {\n // Without shardedSubscribers, ioredis sends SSUBSCRIBE to a random node and gets MOVED.\n return createSubscriber(client.duplicate([], { shardedSubscribers: true }), true);\n },\n };\n}\n\n/**\n * Reads the masters when iteration starts, so a topology change before `clear` is seen. Rejects\n * when none is known (a `lazyConnect` Cluster before its first command): scanning zero masters\n * would let `clear` succeed without deleting anything.\n */\nasync function* scanMasters(\n client: IoredisClusterLike,\n match: string,\n count: number,\n): AsyncIterable<string[]> {\n yield* scanNodes(\n client.nodes('master'),\n async (node, cursor) => {\n const [next, keys] = await node.scan(cursor, 'MATCH', match, 'COUNT', count);\n return { cursor: next, keys };\n },\n 'ioredisAdapter: no cluster master is known yet, so the keyspace cannot be scanned',\n );\n}\n\n/**\n * The subscriber over a dedicated connection. With `sharded` and a Cluster connection, it sends\n * SSUBSCRIBE and listens to 'smessage'; otherwise SUBSCRIBE and 'message'. One flag decides both,\n * so the command and the listened event always match. Retries, reconnects and close follow the\n * shared `createSubscriptionTracker`.\n */\nfunction createSubscriber(\n connection: IoredisLike | IoredisClusterLike,\n sharded: boolean,\n): RedisSubscriberAdapter {\n const shardedConnection = sharded && isClusterClient(connection) ? connection : undefined;\n const tracker = createSubscriptionTracker({\n subscribe: (channel) =>\n shardedConnection === undefined\n ? connection.subscribe(channel)\n : shardedConnection.ssubscribe(channel),\n close: () => closeConnection(connection),\n });\n // Without an 'error' listener ioredis prints \"Unhandled error event\" on every failed reconnect.\n connection.on('error', (error: unknown) => {\n tracker.error(error);\n });\n connection.on(\n shardedConnection === undefined ? 'message' : 'smessage',\n (channel: string, message: string) => {\n tracker.deliver(channel, message);\n },\n );\n connection.on('ready', () => {\n tracker.ready();\n });\n return tracker.subscriber;\n}\n\n/** QUIT, or drop the connection if QUIT has not settled in time. Never rejects. */\nfunction closeConnection(connection: IoredisLike | IoredisClusterLike): Promise<void> {\n return closeWithTimeout(\n () => connection.quit(),\n () => {\n connection.disconnect?.();\n },\n );\n}\n\nexport function isRedisClientAdapter(\n value: IoredisLike | IoredisClusterLike | RedisClientAdapter,\n): value is RedisClientAdapter {\n return typeof (value as Partial<RedisClientAdapter>).createSubscriber === 'function';\n}\n","import type { InvalidationBus, InvalidationMessage } from './cache-store.interface.js';\nimport { ioredisAdapter, isRedisClientAdapter } from './ioredis.adapter.js';\nimport type { IoredisClusterLike, IoredisLike } from './ioredis.adapter.js';\nimport type { RedisClientAdapter, RedisSubscriberAdapter } from './redis-client.adapter.js';\n\n/** Options of `redisInvalidationBus`. */\nexport interface RedisInvalidationBusOptions {\n /** An ioredis client or Cluster, or a `RedisClientAdapter` (e.g. `nodeRedisAdapter(client)`). */\n client: IoredisLike | IoredisClusterLike | RedisClientAdapter;\n /** The pub/sub channel of invalidation messages. Defaults to 'nestjs-cache:invalidate'. */\n channel?: string;\n}\n\n/** Internal: the channel used when none is configured. */\nexport const DEFAULT_CHANNEL = 'nestjs-cache:invalidate';\n\nexport function toRedisAdapter(\n client: IoredisLike | IoredisClusterLike | RedisClientAdapter,\n): RedisClientAdapter {\n return isRedisClientAdapter(client) ? client : ioredisAdapter(client);\n}\n\n/** Longest message, in characters, that is parsed; a longer one is never `JSON.parse`d. */\nconst MAX_MESSAGE_LENGTH = 1_048_576;\n\nfunction parseMessage(raw: string): InvalidationMessage | undefined {\n // A forged multi-megabyte message would cost a parse on every instance. It becomes a clear of\n // every key instead; the empty origin never equals an instance's randomUUID() origin, so no\n // store ignores it as its own.\n if (raw.length > MAX_MESSAGE_LENGTH) return { origin: '', prefix: '' };\n let value: unknown;\n try {\n value = JSON.parse(raw);\n } catch {\n return undefined;\n }\n if (typeof value !== 'object' || value === null) return undefined;\n const record = value as Record<string, unknown>;\n const origin = record['origin'];\n if (typeof origin !== 'string') return undefined;\n const keys = record['keys'];\n const prefix = record['prefix'];\n if (keys !== undefined && prefix === undefined) {\n if (Array.isArray(keys) && keys.every((k): k is string => typeof k === 'string')) {\n return { origin, keys };\n }\n }\n if (typeof prefix === 'string' && keys === undefined) return { origin, prefix };\n // A string origin with an unknown body (a newer wire format, or a malformed one) clears L1.\n return { origin, prefix: '' };\n}\n\n/** Internal: builds the bus over an adapter that the caller owns. */\nexport function createRedisBus(adapter: RedisClientAdapter, channel: string): InvalidationBus {\n const handlers: Array<(message: InvalidationMessage) => void> = [];\n const reconnectHandlers: Array<() => void> = [];\n const errorHandlers: Array<(error: unknown) => void> = [];\n let subscriber: RedisSubscriberAdapter | undefined;\n let subscribed: Promise<void> | undefined;\n\n const dispatch = (raw: string): void => {\n const message = parseMessage(raw);\n if (message === undefined) return;\n for (const h of handlers) {\n try {\n h(message);\n } catch {\n // one failing handler must not stop the others or reach the ioredis listener\n }\n }\n };\n\n return {\n async publish(message) {\n await adapter.publish(channel, JSON.stringify(message));\n },\n subscribe(handler) {\n if (!handlers.includes(handler)) handlers.push(handler);\n if (subscriber === undefined) {\n subscriber = adapter.createSubscriber();\n for (const onReconnect of reconnectHandlers) subscriber.onReconnect(onReconnect);\n for (const onError of errorHandlers) subscriber.onError?.(onError);\n }\n // A rejected attempt is forgotten, so a later call subscribes again.\n subscribed ??= subscriber.subscribe(channel, dispatch).catch((error: unknown) => {\n subscribed = undefined;\n throw error;\n });\n return subscribed;\n },\n onReconnect(handler) {\n reconnectHandlers.push(handler);\n subscriber?.onReconnect(handler);\n },\n onError(handler) {\n errorHandlers.push(handler);\n subscriber?.onError?.(handler);\n },\n async close() {\n await subscriber?.close();\n },\n };\n}\n\n/**\n * The Redis pub/sub `InvalidationBus` a `RedisStore` uses, on its own: for a custom store, or a\n * `tieredStore` whose L2 is not Redis. Its subscriber is created on the first `subscribe`.\n */\nexport function redisInvalidationBus(options: RedisInvalidationBusOptions): InvalidationBus {\n return createRedisBus(toRedisAdapter(options.client), options.channel ?? DEFAULT_CHANNEL);\n}\n","import type { CacheStore, InvalidationBus, LockProvider } from './cache-store.interface.js';\nimport { RedisLock } from './redis-lock.js';\nimport type { RedisClientAdapter } from './redis-client.adapter.js';\nimport { createRedisBus, DEFAULT_CHANNEL, toRedisAdapter } from './redis-invalidation-bus.js';\nimport type { RedisInvalidationBusOptions } from './redis-invalidation-bus.js';\n\n/**\n * Options of `redisStore`: the client and the invalidation channel, the same fields as\n * `RedisInvalidationBusOptions`.\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type -- its own name, same fields as the bus options\nexport interface RedisStoreOptions extends RedisInvalidationBusOptions {}\n\nconst SCAN_COUNT = 100;\n\n/** Backslash-escapes `\\ * ? [ ]` so a literal can be used inside a Redis MATCH pattern. */\nexport function escapeGlob(literal: string): string {\n return literal.replace(/[\\\\*?[\\]]/g, '\\\\$&');\n}\n\ntype LockCapable = Required<Pick<RedisClientAdapter, 'setIfAbsent' | 'deleteIfEquals'>>;\n\nfunction supportsLock(adapter: RedisClientAdapter): adapter is RedisClientAdapter & LockCapable {\n return typeof adapter.setIfAbsent === 'function' && typeof adapter.deleteIfEquals === 'function';\n}\n\n/**\n * A Redis store over an ioredis client or Cluster, or any `RedisClientAdapter` (node-redis via\n * `nodeRedisAdapter`). It brings a pub/sub invalidation bus on `channel`, and a lock when the\n * adapter can `setIfAbsent` and `deleteIfEquals`. The caller's client is never closed.\n */\nexport class RedisStore implements CacheStore {\n readonly invalidation: InvalidationBus;\n /** Present only when the adapter implements `setIfAbsent` and `deleteIfEquals`. */\n declare readonly lock?: LockProvider;\n /** Present only when the adapter implements `ping`. */\n declare readonly ping?: () => Promise<void>;\n private readonly adapter: RedisClientAdapter;\n\n constructor(options: RedisStoreOptions) {\n this.adapter = toRedisAdapter(options.client);\n this.invalidation = createRedisBus(this.adapter, options.channel ?? DEFAULT_CHANNEL);\n if (supportsLock(this.adapter)) this.lock = new RedisLock(this.adapter);\n if (this.adapter.ping !== undefined) {\n const adapter = this.adapter;\n this.ping = () => adapter.ping?.() ?? Promise.resolve();\n }\n }\n\n get(key: string): Promise<string | undefined> {\n return this.adapter.get(key);\n }\n\n set(key: string, value: string, ttlMs: number): Promise<void> {\n return this.adapter.set(key, value, ttlMs);\n }\n\n getMany(keys: readonly string[]): Promise<(string | undefined)[]> {\n if (keys.length === 0) return Promise.resolve([]);\n if (this.adapter.mget !== undefined) return this.adapter.mget(keys);\n return Promise.all(keys.map((key) => this.adapter.get(key)));\n }\n\n async setMany(entries: readonly { key: string; value: string; ttlMs: number }[]): Promise<void> {\n await Promise.all(entries.map((e) => this.adapter.set(e.key, e.value, e.ttlMs)));\n }\n\n delete(keys: readonly string[]): Promise<void> {\n return this.adapter.unlink(keys);\n }\n\n async clear(prefix: string): Promise<void> {\n const match = `${escapeGlob(prefix)}*`;\n if (this.adapter.scanIterator !== undefined) {\n for await (const keys of this.adapter.scanIterator(match, SCAN_COUNT)) {\n if (keys.length > 0) await this.adapter.unlink(keys);\n }\n return;\n }\n let cursor = '0';\n do {\n const page = await this.adapter.scan(cursor, match, SCAN_COUNT);\n cursor = page.cursor;\n if (page.keys.length > 0) await this.adapter.unlink(page.keys);\n } while (cursor !== '0');\n }\n\n getAndTouch(key: string, ttlMs: number): Promise<string | undefined> {\n return this.adapter.getex(key, ttlMs);\n }\n\n /** Closes the bus's subscriber connection; the caller's client is left open. */\n close(): Promise<void> {\n return this.invalidation.close();\n }\n}\n\n/** Builds a `RedisStore`; requires Redis 6.2 or later (`GETEX`). */\nexport function redisStore(options: RedisStoreOptions): RedisStore {\n return new RedisStore(options);\n}\n","import { CacheConfigError } from '../errors.js';\nimport { mgetBySlot, scanNodes, unlinkBySlot } from './cluster-ops.js';\nimport { RELEASE_SCRIPT } from './redis-client.adapter.js';\nimport type { RedisClientAdapter, RedisSubscriberAdapter } from './redis-client.adapter.js';\nimport { closeWithTimeout, createSubscriptionTracker } from './subscriber-support.js';\n\n/** node-redis's pub/sub listener: it receives the message first, then the channel. */\ntype PubSubListener = (message: string, channel: string) => void;\n\n/**\n * Structural subset of a node-redis v5 or v6 client (`createClient()` from `redis`). Declared\n * by hand so the library never imports `redis`. The client must be connected before it is\n * passed to `nodeRedisAdapter`; the library never connects it.\n *\n * Satisfied by the client you pass in. In 1.x, members are only added as optional, and the\n * library checks that they exist before calling them.\n */\nexport interface NodeRedisLike {\n get(key: string): Promise<string | null>;\n set(\n key: string,\n value: string,\n options: { expiration: { type: 'PX'; value: number }; condition?: 'NX' },\n ): Promise<string | null>;\n getEx(key: string, options: { type: 'PX'; value: number }): Promise<string | null>;\n eval(script: string, options: { keys: string[]; arguments: string[] }): Promise<unknown>;\n unlink(keys: string[]): Promise<unknown>;\n mGet(keys: string[]): Promise<(string | null)[]>;\n /** Optional. Used by health checks; the adapter exposes `ping` only when it exists. */\n ping?(): Promise<unknown>;\n scan(\n cursor: string,\n options: { MATCH: string; COUNT: number },\n ): Promise<{ cursor: string; keys: string[] }>;\n publish(channel: string, message: string): Promise<unknown>;\n /** The subscriber's dedicated connection: a new, unconnected client. */\n duplicate(): NodeRedisLike;\n connect(): Promise<unknown>;\n subscribe(channel: string, listener: PubSubListener): Promise<unknown>;\n close(): Promise<unknown>;\n destroy(): void;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- node-redis's EventEmitter `on` takes `(...args: any[]) => void`, which `never[]` does not accept\n on(event: string, listener: (...args: any[]) => void): unknown;\n}\n\n/**\n * Structural subset of a node-redis v5 or v6 cluster (`createCluster()` from `redis`). Declared\n * by hand so the library never imports `redis`. `nodeRedisAdapter` runs in cluster mode when the\n * client has `masters`. Like a single client, it must be connected before it is passed in.\n *\n * Satisfied by the client you pass in. In 1.x, members are only added as optional, and the\n * library checks that they exist before calling them.\n */\nexport interface NodeRedisClusterLike extends Omit<NodeRedisLike, 'scan' | 'duplicate'> {\n /** The master nodes, passed back to `nodeClient`; `scanIterator` scans each of them. */\n readonly masters: readonly unknown[];\n /** The client of one master node. */\n nodeClient(master: unknown): Promise<Pick<NodeRedisLike, 'scan'>>;\n sPublish(channel: string, message: string): Promise<unknown>;\n sSubscribe(channel: string, listener: PubSubListener): Promise<unknown>;\n /** The subscriber's dedicated connection: a new, unconnected cluster. */\n duplicate(): NodeRedisClusterLike;\n}\n\n/**\n * Structural subset of a node-redis v5 or v6 Sentinel client (`createSentinel()` from `redis`).\n * Declared by hand so the library never imports `redis`. `nodeRedisAdapter` runs in Sentinel\n * mode when `getSentinelNode` is a function. Data commands go to the sentinel, which sends them\n * to the current master. It has no `duplicate`: the subscriber subscribes on the sentinel\n * itself, whose pub/sub connection follows the master, and closing the subscriber only\n * unsubscribes its own channels; the sentinel is never closed. Like a single client, it must be\n * connected before it is passed in.\n *\n * Satisfied by the client you pass in. In 1.x, members are only added as optional, and the\n * library checks that they exist before calling them.\n */\nexport interface NodeRedisSentinelLike extends Omit<NodeRedisLike, 'duplicate'> {\n /** Marks a Sentinel client; never called. */\n getSentinelNode(): unknown;\n /**\n * Removes one listener of `channel`; the channel's other listeners keep it subscribed. node-redis\n * types the listener for string and buffer mode alike.\n */\n unsubscribe(channel: string, listener: AnyModePubSubListener): Promise<unknown>;\n off(event: string, listener: (arg: unknown) => void): unknown;\n}\n\n/** A pub/sub listener as node-redis types it for either mode: string or buffer messages. */\ntype AnyModePubSubListener = (message: string | Uint8Array, channel: string | Uint8Array) => void;\n\n/**\n * The connection the subscriber drives: a single client, or a cluster (sharded mode), which also\n * has `sSubscribe`.\n */\ntype SubscriberConnection = Pick<\n NodeRedisLike,\n 'connect' | 'subscribe' | 'close' | 'destroy' | 'on'\n> & {\n sSubscribe?(channel: string, listener: PubSubListener): Promise<unknown>;\n};\n\n/**\n * Adapts a connected node-redis v5 or v6 client, cluster or Sentinel to the cache's\n * `RedisClientAdapter`. A cluster (spec 3.4) splits `mget`/`unlink` per slot, scans every master\n * through `scanIterator`, and publishes and subscribes with sharded pub/sub. A Sentinel subscribes\n * on itself (see `NodeRedisSentinelLike`).\n */\nexport function nodeRedisAdapter(\n client: NodeRedisLike | NodeRedisClusterLike | NodeRedisSentinelLike,\n): RedisClientAdapter {\n const adapter: RedisClientAdapter = {\n async get(key) {\n return (await client.get(key)) ?? undefined;\n },\n async set(key, value, ttlMs) {\n await client.set(key, value, { expiration: { type: 'PX', value: Math.ceil(ttlMs) } });\n },\n async getex(key, ttlMs) {\n return (await client.getEx(key, { type: 'PX', value: Math.ceil(ttlMs) })) ?? undefined;\n },\n async setIfAbsent(key, value, ttlMs) {\n const reply = await client.set(key, value, {\n expiration: { type: 'PX', value: Math.ceil(ttlMs) },\n condition: 'NX',\n });\n return reply === 'OK';\n },\n async deleteIfEquals(key, value) {\n return (await client.eval(RELEASE_SCRIPT, { keys: [key], arguments: [value] })) === 1;\n },\n ...keyspaceCommands(client),\n };\n // Optional members exist only when the client has them, so `'ping' in adapter` is truthful.\n if (typeof client.ping === 'function') {\n adapter.ping = async () => {\n await client.ping?.();\n };\n }\n return adapter;\n}\n\ntype KeyspaceCommands = Pick<\n RedisClientAdapter,\n 'unlink' | 'mget' | 'scan' | 'publish' | 'createSubscriber' | 'scanIterator'\n>;\n\n/** MGET; `null` becomes `undefined` and the values keep the key order. */\nasync function mgetValues(\n client: Pick<NodeRedisLike, 'mGet'>,\n keys: readonly string[],\n): Promise<(string | undefined)[]> {\n if (keys.length === 0) return [];\n const values = await client.mGet([...keys]);\n return keys.map((_, index) => values[index] ?? undefined);\n}\n\nfunction isSentinel(\n client: NodeRedisLike | NodeRedisClusterLike | NodeRedisSentinelLike,\n): client is NodeRedisSentinelLike {\n return typeof (client as Partial<NodeRedisSentinelLike>).getSentinelNode === 'function';\n}\n\nfunction keyspaceCommands(\n client: NodeRedisLike | NodeRedisClusterLike | NodeRedisSentinelLike,\n): KeyspaceCommands {\n if (isSentinel(client)) {\n return singleNodeCommands(client, () => createNodeRedisSentinelSubscriber(client));\n }\n if ('masters' in client) return clusterCommands(client);\n return singleNodeCommands(client, () => createNodeRedisSubscriber(client.duplicate(), false));\n}\n\n/** A single client's or a Sentinel's commands; they differ only in their subscriber. */\nfunction singleNodeCommands(\n client: Omit<NodeRedisLike, 'duplicate'>,\n createSubscriber: () => RedisSubscriberAdapter,\n): KeyspaceCommands {\n return {\n async unlink(keys) {\n if (keys.length === 0) return;\n await client.unlink([...keys]);\n },\n mget(keys) {\n return mgetValues(client, keys);\n },\n async scan(cursor, match, count) {\n const reply = await client.scan(cursor, { MATCH: match, COUNT: count });\n return { cursor: reply.cursor, keys: reply.keys };\n },\n async publish(channel, message) {\n await client.publish(channel, message);\n },\n createSubscriber,\n };\n}\n\n/** Spec 3.4: multi-key commands per slot, SCAN on every master, sharded pub/sub. */\nfunction clusterCommands(client: NodeRedisClusterLike): KeyspaceCommands {\n return {\n unlink(keys) {\n return unlinkBySlot(keys, async (slotKeys) => {\n await client.unlink(slotKeys);\n });\n },\n // A cluster rejects a multi-key command across slots (CROSSSLOT): one MGET per slot.\n mget(keys) {\n return mgetBySlot(keys, (slotKeys) => mgetValues(client, slotKeys));\n },\n scan() {\n return Promise.reject(\n new CacheConfigError(\n 'nodeRedisAdapter: scan is not supported on a Redis cluster client, because one cursor covers one node; use scanIterator, which scans every master',\n ),\n );\n },\n scanIterator(match, count) {\n return scanMasters(client, match, count);\n },\n async publish(channel, message) {\n await client.sPublish(channel, message);\n },\n createSubscriber() {\n return createNodeRedisSubscriber(client.duplicate(), true);\n },\n };\n}\n\n/**\n * Reads the masters when iteration starts, so a topology change before `clear` is seen. Rejects\n * when none is known: scanning zero masters would let `clear` succeed without deleting anything.\n */\nasync function* scanMasters(\n client: NodeRedisClusterLike,\n match: string,\n count: number,\n): AsyncIterable<string[]> {\n yield* scanNodes(\n [...client.masters],\n async (master, cursor) => {\n const node = await client.nodeClient(master);\n const reply = await node.scan(cursor, { MATCH: match, COUNT: count });\n return { cursor: reply.cursor, keys: reply.keys };\n },\n 'nodeRedisAdapter: no cluster master is known yet, so the keyspace cannot be scanned',\n );\n}\n\n/** The rejection of a subscribe after close, whether close came before or during connect. */\nconst SUBSCRIBER_CLOSED = 'nodeRedisAdapter: the subscriber is closed';\n\n/**\n * The subscriber over a dedicated, not yet connected node-redis connection. The first `subscribe`\n * connects it; a rejected connect is forgotten, so a later `subscribe` connects again. With\n * `sharded` (a cluster) it sends SSUBSCRIBE, otherwise SUBSCRIBE. Retries, reconnects and close\n * follow the shared `createSubscriptionTracker`: node-redis restores confirmed subscriptions after\n * a reconnect, and a SUBSCRIBE that rejected is sent again on the next 'ready'.\n */\nexport function createNodeRedisSubscriber(\n connection: SubscriberConnection,\n sharded: boolean,\n): RedisSubscriberAdapter {\n let connecting: Promise<unknown> | undefined;\n let closed = false;\n\n const connect = (): Promise<unknown> => {\n if (closed) return Promise.reject(new Error(SUBSCRIBER_CLOSED));\n // The executor turns a synchronous throw into a rejection.\n connecting ??= new Promise((resolve) => {\n resolve(connection.connect());\n }).catch((error: unknown) => {\n connecting = undefined;\n throw error;\n });\n return connecting;\n };\n\n // One listener for every channel; the tracker swallows a throwing handler.\n const deliver: PubSubListener = (message, channel) => {\n tracker.deliver(channel, message);\n };\n\n const subscribeCommand = (channel: string): Promise<unknown> => {\n if (closed) return Promise.reject(new Error(SUBSCRIBER_CLOSED));\n if (!sharded) return connection.subscribe(channel, deliver);\n if (connection.sSubscribe === undefined) {\n return Promise.reject(\n new Error('nodeRedisAdapter: sharded pub/sub needs a client with sSubscribe'),\n );\n }\n return connection.sSubscribe(channel, deliver);\n };\n\n const tracker = createSubscriptionTracker({\n subscribe: (channel) => connect().then(() => subscribeCommand(channel)),\n close: () => {\n closed = true;\n return closeWithTimeout(\n () => connection.close(),\n () => {\n connection.destroy();\n },\n );\n },\n });\n\n // Without an 'error' listener, an error emitted while node-redis reconnects would crash.\n connection.on('error', (error: unknown) => {\n tracker.error(error);\n });\n if (sharded) {\n // A cluster re-emits each node client's errors as 'node-error' (error, clientInfo).\n connection.on('node-error', (error: unknown) => {\n tracker.error(error);\n });\n }\n // A cluster never emits 'ready', so the cluster (sharded) subscriber never fires onReconnect:\n // 'node-ready' is registered once per node client and 'node-reconnecting' fires before the\n // reconnect completes. After a cluster reconnect, L1 staleness is bounded by l1Ttl.\n connection.on('ready', () => {\n tracker.ready();\n });\n return tracker.subscriber;\n}\n\n/**\n * The subscriber over a connected node-redis Sentinel (ruling T1-A). It subscribes on the sentinel\n * itself, never connects it, and `close` only unsubscribes its own listener from its channels and\n * removes its event listeners: the sentinel stays open for the user and for other subscribers.\n * A SUBSCRIBE that completes after close is unsubscribed at once, and nothing is delivered after\n * close.\n * The sentinel never emits 'ready'; a MASTER_CHANGE topology event, after which its pub/sub\n * connection moves to the new master, counts as a reconnect, so `onReconnect` fires and failed\n * SUBSCRIBEs are sent again.\n */\nfunction createNodeRedisSentinelSubscriber(\n sentinel: NodeRedisSentinelLike,\n): RedisSubscriberAdapter {\n let closed = false;\n /**\n * Every channel a SUBSCRIBE was sent for and has not rejected, so close removes the listener\n * from each.\n */\n const channels = new Set<string>();\n\n // One listener for every channel; the tracker swallows a throwing handler. It subscribes in\n // string mode, so both arguments are strings; the wider type is what `unsubscribe` takes.\n const deliver: AnyModePubSubListener = (message, channel) => {\n if (closed) return;\n tracker.deliver(String(channel), String(message));\n };\n const onError = (error: unknown): void => {\n tracker.error(error);\n };\n // node-redis emits MASTER_CHANGE before its pub/sub proxy has finished moving to the new\n // master, so an L1 backfill in that gap can still miss an invalidation (bounded by l1Ttl).\n const onTopologyChange = (event: unknown): void => {\n if ((event as { type?: unknown } | undefined)?.type === 'MASTER_CHANGE') tracker.ready();\n };\n\n const tracker = createSubscriptionTracker({\n subscribe: (channel) => {\n if (closed) return Promise.reject(new Error(SUBSCRIBER_CLOSED));\n channels.add(channel);\n return sentinel.subscribe(channel, deliver).then(\n (reply) => {\n if (!closed) return reply;\n // T5-B: it completed after close, whose UNSUBSCRIBE came too early: remove it now.\n void Promise.resolve()\n .then(() => sentinel.unsubscribe(channel, deliver))\n .catch(() => undefined);\n throw new Error(SUBSCRIBER_CLOSED);\n },\n (error: unknown) => {\n // Not subscribed, so close must not UNSUBSCRIBE it: on a sentinel that is shutting\n // down, that could make node-redis open a new pub/sub client. A retry re-adds it.\n channels.delete(channel);\n throw error;\n },\n );\n },\n close: () => {\n closed = true;\n sentinel.off('error', onError);\n sentinel.off('topology-change', onTopologyChange);\n // Nothing to destroy: the sentinel is the user's, so a hanging UNSUBSCRIBE is abandoned.\n return closeWithTimeout(\n () =>\n // Each channel on its own: one that fails or throws does not keep the others subscribed.\n Promise.allSettled(\n [...channels].map(\n (channel) =>\n new Promise((resolve) => {\n resolve(sentinel.unsubscribe(channel, deliver));\n }),\n ),\n ),\n () => undefined,\n );\n },\n });\n\n // The sentinel re-emits its pub/sub and node clients' errors as 'error'.\n sentinel.on('error', onError);\n sentinel.on('topology-change', onTopologyChange);\n // The sentinel is connected already: this is the first 'ready', so the next one is a reconnect.\n tracker.ready();\n return tracker.subscriber;\n}\n","import { randomUUID } from 'node:crypto';\nimport { Logger } from '@nestjs/common';\nimport type { CacheEventSink, CacheOperation } from '../core/events.js';\nimport { CacheConfigError } from '../errors.js';\nimport { CircuitOpenError } from '../resilience/circuit-breaker.store.js';\nimport type {\n CacheStore,\n InvalidationBus,\n InvalidationMessage,\n LockProvider,\n} from './cache-store.interface.js';\n\n/** Options of `tieredStore`. */\nexport interface TieredStoreOptions {\n /** The local tier, usually `memoryStore()`. */\n l1: CacheStore;\n /** The shared tier, usually `redisStore(...)`; its bus is used unless `invalidation` is set. */\n l2: CacheStore;\n /** Upper bound on how long a value lives in L1. Defaults to 10_000 ms. */\n l1Ttl?: number;\n /** Overrides `l2.invalidation`. */\n invalidation?: InvalidationBus;\n}\n\nconst DEFAULT_L1_TTL = 10_000;\n\n/**\n * Two-tier store: a fast local L1 in front of a shared L2. Every write, delete and clear is\n * published on the invalidation bus so other instances drop their L1 copies. Failures are reported\n * through the sink given to `bind`; no method rejects except `getStrict` and `setStrict`, which\n * reject when L2 cannot be read or written.\n */\nexport class TieredStore implements CacheStore {\n /** The L2's lock, when it has one. */\n declare readonly lock?: LockProvider;\n /** Present only when the L2 has `ping`; probes the L2. */\n declare readonly ping?: () => Promise<void>;\n private readonly l1: CacheStore;\n private readonly l2: CacheStore;\n private readonly l1Ttl: number;\n private readonly bus: InvalidationBus | undefined;\n private readonly ownedBus: InvalidationBus | undefined;\n private readonly origin = randomUUID();\n private readonly logger = new Logger('CacheModule');\n private sink: CacheEventSink | undefined;\n private subscribed = false;\n private warned = false;\n private closing: Promise<void> | undefined;\n /**\n * One token per key with an L2 read in flight. Invalidating a key drops its token, so a read\n * that straddles an invalidation does not backfill L1 with the value it read before it.\n */\n private readonly pending = new Map<string, symbol>();\n\n constructor(options: TieredStoreOptions) {\n const l1Ttl = options.l1Ttl ?? DEFAULT_L1_TTL;\n if (typeof l1Ttl !== 'number' || !Number.isFinite(l1Ttl) || l1Ttl <= 0) {\n throw new CacheConfigError(\n `Invalid tieredStore option l1Ttl: ${String(l1Ttl)} (must be a finite number > 0)`,\n );\n }\n this.l1 = options.l1;\n this.l2 = options.l2;\n if (options.l2.lock !== undefined) this.lock = options.l2.lock;\n if (options.l2.ping !== undefined) {\n const ping = options.l2.ping.bind(options.l2);\n this.ping = () => ping();\n }\n this.l1Ttl = l1Ttl;\n this.ownedBus = options.invalidation;\n this.bus = options.invalidation ?? options.l2.invalidation;\n }\n\n bind(sink: CacheEventSink): void {\n this.sink = sink;\n this.l1.bind?.(sink);\n this.l2.bind?.(sink);\n if (this.bus === undefined) {\n // A hand-built sink may omit `logLevel`; a missing one means the default level.\n const level = sink.logLevel ?? 'error';\n if (level !== 'off' && !this.warned) {\n this.warned = true;\n this.logger.warn(\n 'TieredStore has no invalidation bus: other instances keep stale L1 entries for up to l1Ttl after a write or delete',\n );\n }\n return;\n }\n if (this.subscribed) return;\n this.subscribed = true;\n const bus = this.bus;\n const registrations = [\n () => {\n bus.onReconnect(this.onReconnect);\n },\n () => {\n bus.onError?.(this.onBusError);\n },\n ];\n for (const register of registrations) {\n try {\n register();\n } catch (error) {\n this.report('subscribe', error);\n }\n }\n // Startup must not wait on the bus: subscribe runs in the background.\n void this.attempt('subscribe', () => bus.subscribe(this.onMessage));\n }\n\n async get(key: string): Promise<string | undefined> {\n const local = await this.readL1(key);\n if (local !== undefined) return local;\n return this.readL2(key, () => this.l2.get(key), this.l1Ttl);\n }\n\n /**\n * Like `get`, but an L2 failure (including `CircuitOpenError`) is reported as `get` and then\n * rejects with that error instead of counting as a miss. An L1 failure still counts as a miss.\n */\n async getStrict(key: string): Promise<string | undefined> {\n const local = await this.readL1(key);\n if (local !== undefined) return local;\n return this.readL2(key, () => this.l2.get(key), this.l1Ttl, true);\n }\n\n /**\n * Reads several keys: L1 first, then one L2 read for the misses, backfilling L1 (with `l1Ttl`)\n * only the keys not invalidated meanwhile. A failing tier counts as misses; an L2 failure is\n * reported once for the batch.\n */\n async getMany(keys: readonly string[]): Promise<(string | undefined)[]> {\n if (keys.length === 0) return [];\n let local: (string | undefined)[] = [];\n try {\n local = await readMany(this.l1, keys);\n } catch (error) {\n this.report('get', error);\n }\n const result = keys.map((_, i) => local[i]);\n const missed = keys.filter((_, i) => result[i] === undefined);\n if (missed.length === 0) return result;\n\n const tokens = new Map<string, symbol>();\n for (const key of missed) {\n const token = Symbol(key);\n tokens.set(key, token);\n this.pending.set(key, token);\n }\n let remote: (string | undefined)[] = [];\n try {\n remote = await readMany(this.l2, missed);\n } catch (error) {\n this.report('get', error);\n }\n const backfill: { key: string; value: string; ttlMs: number }[] = [];\n missed.forEach((key, i) => {\n const current = this.pending.get(key) === tokens.get(key);\n if (current) this.pending.delete(key);\n const value = remote[i];\n if (value === undefined) return;\n if (current) backfill.push({ key, value, ttlMs: this.l1Ttl });\n });\n if (backfill.length > 0) await this.attempt('set', () => writeMany(this.l1, backfill));\n let next = 0;\n return keys.map((_, i) => result[i] ?? remote[next++]);\n }\n\n /**\n * Writes L2 first, then L1 (each TTL capped at `l1Ttl`), then publishes one message with every\n * key, unless the L2 refused the write because its circuit is open.\n */\n async setMany(entries: readonly { key: string; value: string; ttlMs: number }[]): Promise<void> {\n if (entries.length === 0) return;\n const refused = await this.attempt('set', () => writeMany(this.l2, entries));\n this.forgetKeys(entries.map((e) => e.key));\n const capped = entries.map((e) => ({ ...e, ttlMs: Math.min(e.ttlMs, this.l1Ttl) }));\n await this.attempt('set', () => writeMany(this.l1, capped));\n if (refused instanceof CircuitOpenError) return;\n await this.publish({ origin: this.origin, keys: entries.map((e) => e.key) });\n }\n\n /**\n * Reads the value and resets its TTL to `ttlMs` on L2 (through `l2.getAndTouch` when it has\n * one, otherwise `l2.get`). L1 is read but never extended; a backfill lives `min(ttlMs, l1Ttl)`.\n */\n async getAndTouch(key: string, ttlMs: number): Promise<string | undefined> {\n const local = await this.readL1(key);\n if (local !== undefined) return local;\n\n const l2 = this.l2;\n return this.readL2(\n key,\n () => (l2.getAndTouch === undefined ? l2.get(key) : l2.getAndTouch(key, ttlMs)),\n Math.min(ttlMs, this.l1Ttl),\n );\n }\n\n /** L1 read; a failure is reported as `get` and counts as a miss. */\n private async readL1(key: string): Promise<string | undefined> {\n try {\n return await this.l1.get(key);\n } catch (error) {\n this.report('get', error);\n return undefined;\n }\n }\n\n /**\n * L2 read after an L1 miss, backfilling L1 unless the key was invalidated meanwhile. A failure\n * is reported as `get` and counts as a miss, or, when `strict`, rejects with the same error.\n */\n private async readL2(\n key: string,\n read: () => Promise<string | undefined>,\n backfillTtl: number,\n strict = false,\n ): Promise<string | undefined> {\n const token = Symbol(key);\n this.pending.set(key, token);\n let remote: string | undefined;\n try {\n remote = await read();\n } catch (error) {\n this.report('get', error);\n if (strict) {\n this.release(key, token);\n throw error;\n }\n }\n // Still ours: no invalidation of this key (and no newer read of it) happened meanwhile.\n const current = this.release(key, token);\n if (remote !== undefined && current) {\n const value = remote;\n await this.attempt('set', () => this.l1.set(key, value, backfillTtl));\n }\n return remote;\n }\n\n async set(key: string, value: string, ttlMs: number): Promise<void> {\n const refused = await this.attempt('set', () => this.l2.set(key, value, ttlMs));\n await this.afterL2Set(key, value, ttlMs, !(refused instanceof CircuitOpenError));\n }\n\n /**\n * Like `set`, but an L2 failure (including `CircuitOpenError`) is reported as `set` and then\n * rejects with that error; L1 is not written and nothing is published. Once L2 stored the\n * value, it continues as `set` does.\n */\n async setStrict(key: string, value: string, ttlMs: number): Promise<void> {\n try {\n await this.l2.set(key, value, ttlMs);\n } catch (error) {\n this.report('set', error);\n throw error;\n }\n await this.afterL2Set(key, value, ttlMs, true);\n }\n\n /** The rest of a set once L2 was tried: L1 with `min(ttlMs, l1Ttl)`, then the publish. */\n private async afterL2Set(\n key: string,\n value: string,\n ttlMs: number,\n publish: boolean,\n ): Promise<void> {\n this.pending.delete(key);\n await this.attempt('set', () => this.l1.set(key, value, Math.min(ttlMs, this.l1Ttl)));\n if (publish) await this.publish({ origin: this.origin, keys: [key] });\n }\n\n async delete(keys: readonly string[]): Promise<void> {\n const refused = await this.attempt('delete', () => this.l2.delete(keys));\n this.forgetKeys(keys);\n await this.attempt('delete', () => this.l1.delete(keys));\n if (refused instanceof CircuitOpenError) return;\n if (keys.length > 0) await this.publish({ origin: this.origin, keys: [...keys] });\n }\n\n async clear(prefix: string): Promise<void> {\n const refused = await this.attempt('clear', () => this.l2.clear(prefix));\n this.forgetPrefix(prefix);\n await this.attempt('clear', () => this.l1.clear(prefix));\n if (refused instanceof CircuitOpenError) return;\n await this.publish({ origin: this.origin, prefix });\n }\n\n /** Idempotent. Closes both tiers and a bus passed in options; `l2.invalidation` belongs to `l2`. */\n close(): Promise<void> {\n this.closing ??= this.closeAll();\n return this.closing;\n }\n\n private async closeAll(): Promise<void> {\n await quietly(() => this.l1.close?.());\n await quietly(() => this.l2.close?.());\n await quietly(() => this.ownedBus?.close());\n }\n\n private readonly onMessage = (message: InvalidationMessage): void => {\n if (message.origin === this.origin) return;\n if (\n 'keys' in message &&\n !('prefix' in message) &&\n Array.isArray(message.keys) &&\n message.keys.every((k): k is string => typeof k === 'string')\n ) {\n this.forgetKeys(message.keys);\n void this.attempt('delete', () => this.l1.delete(message.keys));\n } else {\n // A custom bus may deliver a body of a newer format: clear L1 rather than keep stale data.\n // Like parseMessage: a prefix counts only when `keys` is absent; keys and prefix together\n // (or any unknown body) clear everything.\n const given = 'keys' in message ? undefined : (message as { prefix?: unknown }).prefix;\n const prefix = typeof given === 'string' ? given : '';\n this.forgetPrefix(prefix);\n void this.attempt('clear', () => this.l1.clear(prefix));\n }\n };\n\n private readonly onReconnect = (): void => {\n // Messages may have been missed while disconnected.\n this.pending.clear();\n void this.attempt('clear', () => this.l1.clear(''));\n };\n\n /** Errors the bus handles internally, such as a lost subscriber connection. */\n private readonly onBusError = (error: unknown): void => {\n this.report('subscribe', error);\n };\n\n /** Drops the pending read token of `key` if it is still `token`; true when it was. */\n private release(key: string, token: symbol): boolean {\n const current = this.pending.get(key) === token;\n if (current) this.pending.delete(key);\n return current;\n }\n\n private forgetKeys(keys: readonly string[]): void {\n for (const key of keys) this.pending.delete(key);\n }\n\n private forgetPrefix(prefix: string): void {\n for (const key of this.pending.keys()) {\n if (key.startsWith(prefix)) this.pending.delete(key);\n }\n }\n\n private async publish(message: InvalidationMessage): Promise<void> {\n const bus = this.bus;\n if (bus === undefined) return;\n await this.attempt('publish', () => bus.publish(message));\n }\n\n /**\n * Runs `fn`, reporting a rejection or a synchronous throw. Never rejects. Returns the caught\n * error, or `undefined` on success.\n */\n private async attempt(operation: CacheOperation, fn: () => Promise<unknown>): Promise<unknown> {\n try {\n await fn();\n return undefined;\n } catch (error) {\n this.report(operation, error);\n return error;\n }\n }\n\n private report(operation: CacheOperation, error: unknown): void {\n // An open circuit means the store is temporarily absent, not broken.\n if (error instanceof CircuitOpenError) return;\n try {\n this.sink?.emit('error', { operation, error });\n } catch {\n // a failing sink must never reach the caller\n }\n }\n}\n\nfunction readMany(store: CacheStore, keys: readonly string[]): Promise<(string | undefined)[]> {\n return store.getMany === undefined\n ? Promise.all(keys.map((key) => store.get(key)))\n : store.getMany(keys);\n}\n\nfunction writeMany(\n store: CacheStore,\n entries: readonly { key: string; value: string; ttlMs: number }[],\n): Promise<unknown> {\n return store.setMany === undefined\n ? Promise.all(entries.map((e) => store.set(e.key, e.value, e.ttlMs)))\n : store.setMany(entries);\n}\n\nasync function quietly(fn: () => Promise<unknown> | undefined): Promise<void> {\n try {\n await fn();\n } catch {\n // close failures are swallowed; close itself never rejects\n }\n}\n\n/** Builds a two-tier store (see `TieredStore`). */\nexport function tieredStore(options: TieredStoreOptions): TieredStore {\n return new TieredStore(options);\n}\n","import type { DynamicModule, Provider } from '@nestjs/common';\nimport { Module } from '@nestjs/common';\nimport { CacheEvents } from '../core/events.js';\nimport type { CacheLogger } from '../module/cache.logger.js';\nimport { CACHE_LOGGER, CACHE_PROMETHEUS_OPTIONS } from '../module/tokens.js';\nimport {\n CacheMetricsCollector,\n resolvePrometheusOptions,\n type ResolvedPrometheusOptions,\n} from './metrics.collector.js';\nimport type { CachePrometheusAsyncOptions, CachePrometheusOptions } from './prometheus.types.js';\n\nfunction collectorProvider(): Provider {\n return {\n provide: CacheMetricsCollector,\n useFactory: (events: CacheEvents, options: ResolvedPrometheusOptions, logger: CacheLogger) =>\n new CacheMetricsCollector(events, options, logger),\n inject: [CacheEvents, CACHE_PROMETHEUS_OPTIONS, CACHE_LOGGER],\n };\n}\n\n/**\n * Records cache metrics through a Prometheus client you pass in (`prom-client` or\n * `@prometheus-io/client`). Needs a global `CacheModule`. Opens no endpoint.\n */\n@Module({})\nexport class CachePrometheusModule {\n static forRoot(options: CachePrometheusOptions): DynamicModule {\n const resolved = resolvePrometheusOptions(options);\n return {\n module: CachePrometheusModule,\n providers: [{ provide: CACHE_PROMETHEUS_OPTIONS, useValue: resolved }, collectorProvider()],\n };\n }\n\n static forRootAsync(options: CachePrometheusAsyncOptions): DynamicModule {\n return {\n module: CachePrometheusModule,\n imports: options.imports ?? [],\n providers: [\n {\n provide: CACHE_PROMETHEUS_OPTIONS,\n useFactory: async (...args: never[]) =>\n resolvePrometheusOptions(await options.useFactory(...args)),\n inject: options.inject ?? [],\n },\n collectorProvider(),\n ],\n };\n }\n}\n","import type { FactoryProvider, ModuleMetadata } from '@nestjs/common';\n\n/**\n * Structural subset of a Prometheus registry; satisfied by prom-client and @prometheus-io/client.\n *\n * Satisfied by the client you pass in. In 1.x, members are only added as optional, and the\n * library checks that they exist before calling them.\n */\nexport interface RegistryLike {\n getSingleMetric(name: string): unknown;\n removeSingleMetric(name: string): void;\n /** Real clients call this on every entry of `registers` while constructing a metric. */\n registerMetric(metric: unknown): void;\n}\n\nexport interface PrometheusMetricConfig {\n name: string;\n help: string;\n labelNames: readonly string[];\n registers: readonly RegistryLike[];\n}\n\n/*\n * The real clients declare `new <T extends string>(config: CounterConfiguration<T>)`, where\n * `registers` is a mutable array of their concrete `Registry` class. Construct signatures are\n * compared contravariantly, so no config type built on `RegistryLike` is accepted: the\n * parameter must be a subtype of what the real constructors take. `never` is that subtype, which\n * makes both client modules assignable without a cast. The price is that the constructors are not\n * directly callable through this type; use `construct()` below (one internal cast, not exported\n * from the package index).\n */\nexport type PrometheusConstructor<TInstance> = new (config: never) => TInstance;\n\n/** Calls a client constructor with a typed config. Internal helper for the metrics collector. */\nexport function construct<TInstance>(\n ctor: PrometheusConstructor<TInstance>,\n config: PrometheusMetricConfig & { buckets?: readonly number[] },\n): TInstance {\n return new (\n ctor as unknown as new (\n config: PrometheusMetricConfig & { buckets?: readonly number[] },\n ) => TInstance\n )(config);\n}\n\n/**\n * Structural subset of a prom-client-compatible client module; pass\n * `import * as client from '...'`.\n *\n * Satisfied by the client you pass in. In 1.x, members are only added as optional, and the\n * library checks that they exist before calling them.\n *\n * A minimal hand-written fake, for tests:\n *\n * ```ts\n * const registry: RegistryLike = {\n * getSingleMetric: () => undefined,\n * removeSingleMetric: () => undefined,\n * registerMetric: () => undefined,\n * };\n * class FakeMetric {\n * inc(): void {}\n * observe(): void {}\n * set(): void {}\n * }\n * const client: PrometheusClientLike = {\n * Counter: FakeMetric,\n * Histogram: FakeMetric,\n * Gauge: FakeMetric,\n * register: registry,\n * };\n * ```\n */\nexport interface PrometheusClientLike {\n Counter: PrometheusConstructor<{ inc(labels: Record<string, string>): void }>;\n Histogram: PrometheusConstructor<{\n observe(labels: Record<string, string>, value: number): void;\n }>;\n Gauge: PrometheusConstructor<{ set(labels: Record<string, string>, value: number): void }>;\n register: RegistryLike;\n}\n\n/** Options of `CachePrometheusModule.forRoot`. */\nexport interface CachePrometheusOptions {\n /** The client module: `import * as client from 'prom-client'` or `'@prometheus-io/client'`. */\n client: PrometheusClientLike;\n /** Where the metrics are registered. Default `client.register`. */\n registry?: RegistryLike;\n /** Metric name prefix (not the cache key prefix). Default `'cache_'`. */\n prefix?: string;\n /** Histogram buckets in seconds, strictly increasing. Default: the client's default buckets. */\n buckets?: readonly number[];\n}\n\n/** Options of `CachePrometheusModule.forRootAsync`: `useFactory` resolves the module options. */\nexport interface CachePrometheusAsyncOptions {\n imports?: ModuleMetadata['imports'];\n inject?: FactoryProvider['inject'];\n useFactory: (...args: never[]) => CachePrometheusOptions | Promise<CachePrometheusOptions>;\n}\n","import type { OnModuleDestroy, OnModuleInit } from '@nestjs/common';\nimport type { BreakerState, CacheEvents } from '../core/events.js';\nimport { CacheConfigError } from '../errors.js';\nimport type { CacheLogger } from '../module/cache.logger.js';\nimport {\n construct,\n type CachePrometheusOptions,\n type PrometheusClientLike,\n type RegistryLike,\n} from './prometheus.types.js';\n\nexport interface ResolvedPrometheusOptions {\n client: PrometheusClientLike;\n registry: RegistryLike;\n prefix: string;\n buckets: readonly number[] | undefined;\n}\n\nconst PREFIX_PATTERN = /^[a-zA-Z_:][a-zA-Z0-9_:]*$/;\n\nfunction describeValue(value: unknown): string {\n if (typeof value === 'string') return value;\n // JSON.stringify renders NaN and +-Infinity as null; show them as written.\n if (Array.isArray(value) && value.some((v) => typeof v === 'number' && !Number.isFinite(v))) {\n return `[${value\n .map((v: unknown) =>\n typeof v === 'number' && !Number.isFinite(v)\n ? String(v)\n : typeof v === 'string'\n ? JSON.stringify(v)\n : describeValue(v),\n )\n .join(',')}]`;\n }\n try {\n return value === undefined ? 'undefined' : JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\n/** @internal Validates the module options in the documented order and fills the defaults. */\nexport function resolvePrometheusOptions(\n options: CachePrometheusOptions,\n): ResolvedPrometheusOptions {\n const client = options.client as Partial<PrometheusClientLike> | undefined;\n if (\n typeof client?.Counter !== 'function' ||\n typeof client.Histogram !== 'function' ||\n typeof client.Gauge !== 'function'\n ) {\n throw new CacheConfigError(\n 'Invalid cachePrometheus option client: must provide Counter, Histogram and Gauge',\n );\n }\n const prefix: unknown = options.prefix ?? 'cache_';\n if (typeof prefix !== 'string' || !PREFIX_PATTERN.test(prefix)) {\n throw new CacheConfigError(`Invalid cachePrometheus option prefix: ${describeValue(prefix)}`);\n }\n const buckets: unknown = options.buckets;\n if (buckets !== undefined) {\n const valid =\n Array.isArray(buckets) &&\n buckets.length > 0 &&\n buckets.every(\n (b, i, all) =>\n typeof b === 'number' && Number.isFinite(b) && (i === 0 || b > (all[i - 1] as number)),\n );\n if (!valid) {\n throw new CacheConfigError(\n `Invalid cachePrometheus option buckets: ${describeValue(buckets)}`,\n );\n }\n }\n return {\n client: options.client,\n registry: options.registry ?? options.client.register,\n prefix,\n buckets: options.buckets,\n };\n}\n\nconst BREAKER_VALUE: Record<BreakerState, number> = { closed: 0, 'half-open': 1, open: 2 };\n\n/**\n * @internal Listens to `CacheEvents` and records the five cache metrics through the user's\n * Prometheus client. Metrics are removed from the registry on shutdown.\n */\nexport class CacheMetricsCollector implements OnModuleInit, OnModuleDestroy {\n private unsubscribers: (() => void)[] = [];\n\n private created: { name: string; metric: unknown }[] = [];\n\n constructor(\n private readonly events: CacheEvents,\n private readonly options: ResolvedPrometheusOptions,\n private readonly logger: CacheLogger,\n ) {}\n\n onModuleInit(): void {\n const { client, registry, prefix, buckets } = this.options;\n const name = (suffix: string): string => `${prefix}${suffix}`;\n const names = [\n 'requests_total',\n 'errors_total',\n 'load_duration_seconds',\n 'lock_wait_seconds',\n 'circuit_breaker_state',\n ].map(name);\n for (const metric of names) {\n if (registry.getSingleMetric(metric) !== undefined) {\n throw new CacheConfigError(\n `Metric \"${metric}\" is already registered; use a different prefix or registry`,\n );\n }\n }\n const registers = [registry];\n const histogramBuckets = buckets === undefined ? {} : { buckets };\n try {\n const requests = this.create(client.Counter, {\n name: name('requests_total'),\n help: 'Cache reads by result',\n labelNames: ['store', 'namespace', 'result'],\n registers,\n });\n const errors = this.create(client.Counter, {\n name: name('errors_total'),\n help: 'Cache errors by operation',\n labelNames: ['store', 'operation'],\n registers,\n });\n const load = this.create(client.Histogram, {\n name: name('load_duration_seconds'),\n help: 'Loader duration on cache misses and refreshes',\n labelNames: ['store', 'namespace', 'success'],\n registers,\n ...histogramBuckets,\n });\n const lock = this.create(client.Histogram, {\n name: name('lock_wait_seconds'),\n help: 'Time spent acquiring or waiting for the distributed lock',\n labelNames: ['store', 'acquired'],\n registers,\n ...histogramBuckets,\n });\n const breaker = this.create(client.Gauge, {\n name: name('circuit_breaker_state'),\n help: 'Circuit breaker state: 0 closed, 1 half-open, 2 open',\n labelNames: ['store'],\n registers,\n });\n const guard = (store: string, update: () => void): void => {\n try {\n update();\n } catch (error) {\n this.logger.storeError(store, 'metrics', error);\n }\n };\n const ns = (namespace: string | undefined): string => namespace ?? '';\n this.unsubscribers = [\n this.events.on('hit', (p) => {\n guard(p.store, () => {\n requests.inc({\n store: p.store,\n namespace: ns(p.namespace),\n result: p.stale ? 'stale' : 'hit',\n });\n });\n }),\n this.events.on('miss', (p) => {\n guard(p.store, () => {\n requests.inc({ store: p.store, namespace: ns(p.namespace), result: 'miss' });\n });\n }),\n this.events.on('error', (p) => {\n guard(p.store, () => {\n errors.inc({ store: p.store, operation: p.operation });\n });\n }),\n this.events.on('load', (p) => {\n guard(p.store, () => {\n load.observe(\n { store: p.store, namespace: ns(p.namespace), success: String(p.success) },\n p.durationMs / 1000,\n );\n });\n }),\n this.events.on('lock', (p) => {\n guard(p.store, () => {\n lock.observe({ store: p.store, acquired: String(p.acquired) }, p.waitedMs / 1000);\n });\n }),\n this.events.on('breaker', (p) => {\n guard(p.store, () => {\n breaker.set({ store: p.store }, BREAKER_VALUE[p.state]);\n });\n }),\n ];\n } catch (error) {\n this.onModuleDestroy();\n throw error;\n }\n }\n\n onModuleDestroy(): void {\n for (const off of this.unsubscribers.splice(0)) off();\n for (const { name, metric } of this.created.splice(0)) {\n try {\n // Skip a metric that is no longer ours (the registry was cleared and another source\n // registered the same name).\n if (this.options.registry.getSingleMetric(name) === metric) {\n this.options.registry.removeSingleMetric(name);\n }\n } catch (error) {\n this.logger.warn(\n `Could not remove metric \"${name}\": ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n }\n\n private create<T>(\n ctor: Parameters<typeof construct<T>>[0],\n config: Parameters<typeof construct<T>>[1],\n ): T {\n const metric = construct(ctor, config);\n this.created.push({ name: config.name, metric });\n return metric;\n }\n}\n","import type { DynamicModule, Provider } from '@nestjs/common';\nimport { Module } from '@nestjs/common';\nimport { CACHE_TRACING_OPTIONS, CACHE_TRACING_REGISTRATION } from '../module/tokens.js';\nimport { CacheTracing, resolveTracingOptions } from './cache-tracing.js';\nimport type { CacheTracingAsyncOptions, CacheTracingOptions } from './tracing.types.js';\n\n/**\n * Registers the options with the `CacheModule`'s `CacheTracing` when the module is instantiated.\n * Invalid options, or a second registration, throw `CacheConfigError` and fail the app init.\n */\nfunction registrationProvider(): Provider {\n return {\n provide: CACHE_TRACING_REGISTRATION,\n useFactory: (tracing: CacheTracing, options: CacheTracingOptions) => {\n tracing.use(options);\n return true;\n },\n inject: [CacheTracing, CACHE_TRACING_OPTIONS],\n };\n}\n\n/**\n * Traces cache calls through an OpenTelemetry tracer you pass in, for example\n * `trace.getTracer('my-app')`; without this module nothing is traced. Needs a global\n * `CacheModule`. Register it once: a second registration fails the app init with\n * `CacheConfigError`.\n */\n@Module({})\nexport class CacheTracingModule {\n /** Registers the tracer given up front. Invalid options throw `CacheConfigError`. */\n static forRoot(options: CacheTracingOptions): DynamicModule {\n const resolved = resolveTracingOptions(options);\n return {\n module: CacheTracingModule,\n providers: [{ provide: CACHE_TRACING_OPTIONS, useValue: resolved }, registrationProvider()],\n };\n }\n\n /**\n * Registers the tracer `useFactory` returns; it can inject providers. Invalid options fail\n * the app init with `CacheConfigError`.\n */\n static forRootAsync(options: CacheTracingAsyncOptions): DynamicModule {\n return {\n module: CacheTracingModule,\n imports: options.imports ?? [],\n providers: [\n {\n provide: CACHE_TRACING_OPTIONS,\n useFactory: async (...args: never[]) => options.useFactory(...args),\n inject: options.inject ?? [],\n },\n registrationProvider(),\n ],\n };\n }\n}\n"],"mappings":"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","names":["import_reflect_metadata","import_common","resolve","options","options","invalid","import_common","import_common","resolve","DEFAULT_TIMEOUT","resolve","import_core","import_common","logger","outcome","load","loading","invalid","resolve","load","resolve","import_node_crypto","name","resolve","refreshed","invalid","load","import_common","warned","fullKey","logger","import_common","messageOf","logger","import_node_crypto","slot","resolve","singleNodeCommands","clusterCommands","createSubscriber","scanMasters","resolve","import_node_crypto","import_common","import_common","logger","load","logger","import_common"]}
|