import type Redis from 'ioredis'; import type { RedisKey } from 'ioredis'; import type { AcquiredResult, AcquireDesire, AcquireOptions } from './Acquire'; import type { AcquireHelper } from './AcquireHelper'; interface Parser { parse: (text: string) => any; stringify: (value: any) => string; } interface CacheOptions { redis: Redis; parser?: Parser; acquire?: AcquireHelper; acquireType?: AcquireType; } declare type Key = RedisKey | number; declare type AcquireType = 'lua' | 'pipeline'; declare type Mapping = { [id: string]: T; }; declare type ValueSource = Mapping | T[] | Map; declare type ValueMap = Mapping; declare type Awaitable = T | Promise; declare const NOT_FOUND_VALUE: undefined; declare type CacheReturn = T | typeof NOT_FOUND_VALUE; declare class Cache { redis: Redis; private readonly acquireHelper; protected prefix: string; protected parser: Parser; /** * @param options - Either an ioredis instance directly or a CacheOptions object * with a `redis` property plus optional `parser`, `acquire`, and * `acquireType`. Throws if the redis instance doesn't satisfy the ioredis * interface check. */ constructor(options: Redis | CacheOptions); private createAcquireHelper; /** * Binds all prototype methods of Cache to a target instance so they can be * destructured and called without losing the `this` context. * * @returns The same target instance after binding. */ static bindAll(target: Cache): Cache; /** * Read-through cache for a single key. Checks the cache first; if the value * is missing, calls `fn` to produce it, stores the result, and returns it. * * @param key - Cache key to look up. * @param fn - Factory function invoked on cache miss. * @param ttl - Optional TTL in seconds. If omitted the value is stored * without expiry. */ cache(key: Key, fn: () => Awaitable, ttl?: number): Promise; /** * Retrieves a single cached value by key. Returns `undefined` when the key * is not found (the `NOT_FOUND_VALUE` sentinel), making it safe to * distinguish a cache miss from a stored value. */ getCache(key: Key): Promise>; /** * Stores a single value in the cache. The value is serialized through the * configured parser (default: JSON). * * @param ttl - Optional TTL in seconds. Uses `SETEX` when provided, plain * `SET` otherwise. */ setCache(key: Key, value: any, ttl?: number): Promise<"OK">; /** * Read-through cache for multiple keys in a single batch. Executes a single * `MGET` for all keys, then calls `fn` for any missing keys and stores the * result via `MSET` (or pipelined `SETEX` when TTL is provided). * * @param keys - List of logical keys to fetch. * @param fn - Factory invoked with the subset of keys that were not cached. * Must return values in the same order as the supplied keys. * @param prefix - Optional string (or number) prepended to every key before * interacting with Redis. The prefix is stripped from cached results. * @param ttl - Optional TTL in seconds for newly stored values. */ manyCache(keys: K[], fn: (keys: K[]) => Awaitable>, prefix?: Key, ttl?: number): Promise; /** * Retrieves multiple cached values by their keys using `MGET`. Returns an * array aligned with the input keys where missing entries are `undefined` * (the `NOT_FOUND_VALUE` sentinel). */ getManyCache(keys: Key[]): Promise[]>; /** * Stores multiple key-value pairs atomically. Uses `MSET` when no TTL is * given; otherwise uses a pipeline of `MSET` + per-key `EXPIRE` commands. * * @param valueMap - A plain object mapping string keys to serialisable values. * @param ttl - Optional TTL in seconds applied to every key in the batch. */ setManyCache(valueMap: { [id: string]: any; }, ttl?: number): Promise<[error: Error | null, result: unknown][] | "OK" | null>; /** * Deletes one or more keys from the cache. * * @returns The number of keys that were actually removed. */ deleteCache(...keys: Key[]): Promise; /** * Deletes all keys matching a glob pattern by iterating with `SCAN` in * batches. The `keyPrefix` configured on the ioredis instance is * automatically prepended to the pattern so callers don't need to include it. * * @param pattern - Redis glob pattern (e.g. `user:*`). * @param batch - Number of keys to scan and delete per pipeline (default 100). */ deletePattern(pattern: string, batch?: number): Promise; /** * Read-through cache for a single field inside a Redis hash. Checks the hash * first; on miss calls `fn`, stores the result, and returns it. * * @param key - The Redis hash key. * @param id - The field name within the hash. * @param fn - Factory function invoked on cache miss. */ hashCache(key: Key, id: Key, fn: () => Awaitable): Promise; /** * Retrieves a single field from a Redis hash. Returns `undefined` (the * `NOT_FOUND_VALUE` sentinel) when the field does not exist. */ getHashCache(key: Key, id: Key): Promise>; /** * Stores a single field in a Redis hash. The value is serialised through the * configured parser. */ setHashCache(key: Key, id: Key, value: any): Promise; /** * Read-through cache for multiple fields within a single Redis hash. Issues * a single `HMGET`, calls `fn` for any missing fields, persists them with * `HMSET`, and returns the merged result aligned with the input `ids`. * * @param key - The Redis hash key. * @param ids - Field names to fetch. * @param fn - Factory invoked with the subset of field names that are not * cached. Must return values in the same order. */ hashManyCache(key: Key, ids: K[], fn: (ids: K[]) => Awaitable>): Promise; /** * Retrieves multiple fields from a Redis hash using `HMGET`. Returns an * array aligned with the input `ids` where missing fields are `undefined` * (the `NOT_FOUND_VALUE` sentinel). */ getHashManyCache(key: Key, ids: Key[]): Promise[]>; /** * Stores multiple fields in a Redis hash atomically using `HMSET`. * * @param key - The Redis hash key. * @param valueMap - A plain object mapping field names to serialisable values. */ setHashManyCache(key: Key, valueMap: { [id: string]: any; }): Promise; /** * Deletes one or more fields from a Redis hash. * * @returns The number of fields that were actually removed. */ deleteHashCache(key: Key, ...ids: Key[]): Promise; /** * Atomically increments (or decrements) a Redis key and invokes `fn` with * the updated value. On failure the increment is automatically rolled back. * * @param key - Redis key holding the counter. * @param amount - Amount to add (use a negative number to decrement). * @param fn - Callback receiving current, acquired, and lacking amounts. * @param options - When `float` is true uses `INCRBYFLOAT`; `limit` caps * how much can be acquired. */ acquire(key: Key, amount: number, fn: (currentAmount: number, acquiredAmount: number, lackingAmount: number) => Awaitable, options?: AcquireOptions | boolean): Promise; /** * Atomically increments (or decrements) a field inside a Redis hash and * invokes `fn` with the updated value. * * @param key - The Redis hash key. * @param id - The field name within the hash. * @param amount - Amount to add. * @param fn - Callback receiving current, acquired, and lacking amounts. * @param options - When `float` is true uses `HINCRBYFLOAT`; `limit` caps * how much can be acquired. */ hashAcquire(key: Key, id: Key, amount: number, fn: (currentAmount: number, acquiredAmount: number, lackingAmount: number) => Awaitable, options?: AcquireOptions | boolean): Promise; /** * Atomically modifies multiple counters through the configured acquire * helper. Each desired change is specified as an `AcquireDesire` item; `fn` * receives the final values. */ acquireMany(items: AcquireDesire[], fn: (acquireResult: AcquiredResult[]) => Awaitable, options?: AcquireOptions): Promise; /** * Atomically modifies multiple fields inside a single Redis hash counter * through the configured acquire helper. * * @param hashKey - The Redis hash key containing the counters. * @param items - Desired changes for each field. * @param fn - Callback receiving the array of results. */ hashAcquireMany(hashKey: string, items: AcquireDesire[], fn: (acquireResult: AcquiredResult[]) => Awaitable, options?: AcquireOptions): Promise; /** * Filters the input `keys` down to those whose corresponding entry in * `cachedValues` is `NOT_FOUND_VALUE`. */ protected _getUncachedKeys(keys: K[], cachedValues: CacheReturn[]): K[]; /** * Merges a set of cached values with a map of uncached values. Where a * cached entry is `NOT_FOUND_VALUE`, the corresponding value is looked up * from `uncachedValueMap` by key. */ protected _mergeCacheValues(cachedValues: CacheReturn[], keys: K[], uncachedValueMap: ValueMap): T[]; /** * Returns a new map with every key prefixed by `prefix`. Used internally * by `manyCache` to apply the configured prefix before storing. */ protected _prefixValueMap(valueMap: ValueMap, prefix: Key): ValueMap; /** * Converts a value map into a flat array of `[key, stringifiedValue, key, * stringifiedValue, ...]` suitable for `MSET` / `HMSET`. Entries whose * value is `NOT_FOUND_VALUE` are skipped. */ protected _buildSetParams: (valueMap: { [id: string]: any; }) => string[]; /** * Normalises a `ValueSource` (array, `Map`, or plain object) into a uniform * `ValueMap` keyed by the string representation of each id. Array and `Map` * sources are aligned with `ids` by position. */ protected _buildValueMap(ids: K[], valueMap: ValueSource): ValueMap; } export default Cache;