UNPKG

bentocache

Version:

Multi-tier cache module for Node.js. Redis, Upstash, CloudfareKV, File, in-memory and others drivers

655 lines (642 loc) 18.9 kB
import { Exception } from '@poppinss/exception'; import { C as CacheDriver } from './driver-CldynQv4.js'; import { Transport } from '@boringnode/bus/types/main'; import { d as Duration, G as GetSetFactory, e as Factory } from './drivers_options-Dm62iGEe.js'; import { Logger } from '@julr/utils/logger'; /** * Thrown when a factory has timed out after waiting for soft timeout */ declare class FactorySoftTimeout extends Exception { static code: string; static message: string; key: string; constructor(key: string); } /** * Thrown when a factory has timed out after waiting for hard timeout */ declare class FactoryHardTimeout extends Exception { static code: string; static message: string; key: string; constructor(key: string); } /** * Thrown when a factory has thrown an error. Original error is available as `cause` */ declare class FactoryError extends Exception { static code: string; static message: string; /** * The key for which the factory was called */ key: string; /** * If the error was thrown by a factory * running in the background */ isBackgroundFactory: boolean; constructor(key: string, cause: any, isBackground?: boolean); } /** * Thrown when a `undefined` value is about to be set * in the cache. You can't set `undefined` values. */ declare class UndefinedValueError extends Exception { static code: string; constructor(key: string); } /** * Thrown when a L2 Cache operation fail */ declare class L2CacheError extends Exception { static code: string; static message: string; constructor(cause: any); } declare const errors: { E_FACTORY_ERROR: typeof FactoryError; E_FACTORY_SOFT_TIMEOUT: typeof FactorySoftTimeout; E_FACTORY_HARD_TIMEOUT: typeof FactoryHardTimeout; E_UNDEFINED_VALUE: typeof UndefinedValueError; E_L2_CACHE_ERROR: typeof L2CacheError; }; /** * Interface for the bus driver */ type BusDriver = Transport; /** * Message sent over the cache bus */ type CacheBusMessage = { keys: string[]; type: CacheBusMessageType; namespace?: string; }; declare const CacheBusMessageType: { /** * An item was set in the cache */ Set: string; /** * Whole cache was cleared */ Clear: string; /** * An item was deleted from the cache */ Delete: string; /** * An item was logically expired */ Expire: string; }; type CacheBusMessageType = (typeof CacheBusMessageType)[keyof typeof CacheBusMessageType]; type BusOptions = { /** * Configuration for the bus retry queue */ retryQueue?: { /** * If we should retry sending messages that failed to be sent */ enabled?: boolean; /** * Maximum number of messages to keep in the retry queue. Older * messages will be discarded when the queue is full. */ maxSize?: number; /** * The interval between each retry attempt * * @default '2s' */ retryInterval?: Duration | false; }; }; declare const busEvents: { messagePublished(message: CacheBusMessage): { name: string; data: { message: { keys: string[]; type: string; }; }; }; messageReceived(message: CacheBusMessage): { name: string; data: { message: { keys: string[]; type: string; }; }; }; }; declare const cacheEvents: { cleared(store: string): { name: "cache:cleared"; data: { store: string; }; }; deleted(key: string, store: string): { name: "cache:deleted"; data: { key: string; store: string; }; }; hit(key: string, value: any, store: string, graced?: boolean): { name: "cache:hit"; data: { key: string; value: any; store: string; graced: boolean; }; }; miss(key: string, store: string): { name: "cache:miss"; data: { key: string; store: string; }; }; written(key: string, value: any, store: string): { name: "cache:written"; data: { key: string; value: any; store: string; }; }; expire(key: string, store: string): { name: "cache:expire"; data: { key: string; store: string; }; }; }; /** * Shape of the emitter accepted by BentoCache * Should be compatible with node's EventEmitter and Emittery */ interface Emitter { on: (event: string, callback: (...values: any[]) => void) => void; once: (event: string, callback: (...values: any[]) => void) => void; off: (event: string, callback: (...values: any[]) => void) => void; emit: (event: string, ...values: any[]) => void; } /** * Name/payload of the events emitted by the cache emitter */ type CacheEvents = { 'cache:cleared': ReturnType<typeof cacheEvents.cleared>['data']; 'cache:deleted': ReturnType<typeof cacheEvents.deleted>['data']; 'cache:hit': ReturnType<typeof cacheEvents.hit>['data']; 'cache:miss': ReturnType<typeof cacheEvents.miss>['data']; 'cache:expire': ReturnType<typeof cacheEvents.expire>['data']; 'cache:written': ReturnType<typeof cacheEvents.written>['data']; 'bus:message:published': ReturnType<typeof busEvents.messagePublished>['data']; 'bus:message:received': ReturnType<typeof busEvents.messageReceived>['data']; }; /** * A cache event */ interface CacheEvent { name: keyof CacheEvents; data: Record<string, any>; } /** * A cache provider is a class that wraps an underlying cache driver * to provide additional features. */ interface CacheProvider { /** * Set a value in the cache * Returns true if the value was set, false otherwise */ set(options: SetOptions): Promise<boolean>; /** * Set a value in the cache forever */ setForever(options: SetOptions): Promise<boolean>; /** * Get a value from the cache, fallback to a default value * and set options */ get<T = any>(options: GetOptions<T>): Promise<T>; /** * Get or set a value in the cache */ getOrSet<T>(options: GetOrSetOptions<T>): Promise<T>; /** * Get or set a value in the cache forever */ getOrSetForever<T>(options: GetOrSetForeverOptions<T>): Promise<T>; /** * Check if a key exists in the cache */ has(options: HasOptions): Promise<boolean>; /** * Check if a key is missing from the cache */ missing(options: HasOptions): Promise<boolean>; /** * Get the value of a key and delete it * * Returns the value if the key exists, undefined otherwise */ pull<T = any>(key: string): Promise<T | undefined | null>; /** * Delete a key from the cache * Returns true if the key was deleted, false otherwise */ delete(options: DeleteOptions): Promise<boolean>; /** * Delete multiple keys from the cache */ deleteMany(options: DeleteManyOptions): Promise<boolean>; /** * Delete all keys with a specific tag */ deleteByTag(options: DeleteByTagOptions): Promise<boolean>; /** * Expire a key from the cache. * Entry will not be fully deleted but expired and * retained for the grace period if enabled. */ expire(options: DeleteOptions): Promise<boolean>; /** * Remove all items from the cache */ clear(options?: ClearOptions): Promise<void>; /** * Returns a new instance of the driver namespaced */ namespace(namespace: string): CacheProvider; /** * Closes the connection to the cache */ disconnect(): Promise<void>; } /** * These options are common to : * - BentoCache global options * - Driver options * - Core methods */ type RawCommonOptions = { /** * The soft timeout. Once this timeout is reached, * the factory will try to return a graced value * if available * * @default 0 Means, if a graced value is available, it will be returned * immediately and the factory will be refreshed in the background */ timeout?: Duration; /** * The hard timeout. Once this timeout is reached, * the factory will just throw an error that will * bubble up. You will need to handle this error * * @default null Means, no hard timeout */ hardTimeout?: Duration; /** * The duration for which the entry will be * considered valid */ ttl?: Duration; /** * Grace period options */ grace?: false | Duration; graceBackoff?: Duration; /** * Whether to suppress errors that occur when * trying to fetch from remote (l2) cache */ suppressL2Errors?: boolean; /** * Maximum time for which a lock can try to be acquired * before running a factory */ lockTimeout?: Duration; /** * A handler that will be called when a factory * throws an error */ onFactoryError?: (error: FactoryError) => void; /** * Should the cache entry be written to the L2 cache * @default false */ skipL2Write?: boolean; /** * Should the bus be used for cache invalidation * @default false */ skipBusNotify?: boolean; /** * Duration for the circuit breaker to stay open * if l2 cache fails * * @default null Means, no circuit breaker */ l2CircuitBreakerDuration?: Duration; /** * Tags that will be associated with the cache entry */ tags?: string[]; }; /** * Options accepted by Bentocache */ type RawBentoCacheOptions = { prefix?: string; /** * A logger instance that will be used to log * multiple events occurring in the cache * * Pino is compatible out of the box */ logger?: Logger; /** * An emitter instance that will be used to * emit multiple events occurring in the cache * * Emittery and node EventEmitter are compatible * out of the box */ emitter?: Emitter; /** * Custom serializer */ serializer?: CacheSerializer; } & Omit<RawCommonOptions, 'tags' | 'skipBusNotify' | 'skipL2Write'>; /** * The options that can be passed when creating * a cache driver like `memoryDriver({ ... }) */ type CacheDriverOptions = { prefix?: string; } & RawCommonOptions; /** * Options accepted by the `getOrSet` method */ type SetCommonOptions = Pick<RawCommonOptions, 'grace' | 'graceBackoff' | 'suppressL2Errors' | 'lockTimeout' | 'ttl' | 'timeout' | 'hardTimeout' | 'skipBusNotify' | 'skipL2Write' | 'onFactoryError' | 'tags'>; /** * Options accepted by the `getOrSet` method */ type GetOrSetOptions<T> = { key: string; factory: GetSetFactory<T>; } & SetCommonOptions; /** * Options accepted by the `getOrSetForever` method */ type GetOrSetForeverOptions<T> = { key: string; factory: GetSetFactory<T>; } & Omit<SetCommonOptions, 'ttl'>; /** * Options accepted by the `set` method */ type SetOptions = { key: string; value: any; } & SetCommonOptions; /** * Options accepted by the `get` method */ type GetOptions<T> = { key: string; defaultValue?: Factory<T>; } & Pick<RawCommonOptions, 'grace' | 'graceBackoff' | 'suppressL2Errors'>; /** * Options accepted by the `delete` method */ type DeleteOptions = { key: string; } & Pick<RawCommonOptions, 'suppressL2Errors'>; type DeleteManyOptions = { keys: string[]; } & Pick<RawCommonOptions, 'suppressL2Errors'>; /** * Options accepted by the `deleteByTag` method */ type DeleteByTagOptions = { tags: string[]; } & Pick<RawCommonOptions, 'suppressL2Errors'>; /** * Options accepted by the `expire` method */ type ExpireOptions = { key: string; } & Pick<RawCommonOptions, 'suppressL2Errors'>; /** * Options accepted by the `has` method */ type HasOptions = { key: string; } & Pick<RawCommonOptions, 'suppressL2Errors'>; /** * Options accepted by the `clear` method */ type ClearOptions = Pick<RawCommonOptions, 'suppressL2Errors'>; /** * Interface for a L1 cache driver. Probably a memory driver */ interface L1CacheDriver extends CacheDriver<false> { type: 'l1'; getRemainingTtl(key: string): number | undefined; } /** * Interface for a L2, distributed cache driver. */ interface L2CacheDriver extends CacheDriver<true> { type: 'l2'; } /** * Factory result for a cache driver */ interface CreateDriverResult<T extends L1CacheDriver | L2CacheDriver> { options: Record<string, any>; factory: (config: any) => T; } /** * Contract for a bus driver factory */ interface CreateBusDriverResult { options: BusOptions; factory: (config: any) => BusDriver; } /** * Cache serializer contract */ interface CacheSerializer { serialize: (value: any) => string; deserialize: (value: any) => any; } /** * Stack of cache drivers */ interface CacheStackDrivers { l1Driver?: L1CacheDriver; l2Driver?: L2CacheDriver; busDriver?: BusDriver; busOptions?: BusOptions; } /** * A Bentocache Plugin */ interface BentoCachePlugin { register(bentocache: BentoCache<any>): void; } /** * Dialect available for the SQL driver */ type DialectName = 'pg' | 'mysql2' | 'better-sqlite3' | 'sqlite3'; /** * Create a new store */ declare function bentostore(options?: RawCommonOptions & { prefix?: string; }): BentoStore; declare class BentoStore { #private; constructor(baseOptions?: RawCommonOptions & { prefix?: string; }); /** * Add a L1 layer to your store. This is usually a memory driver * for fast access purposes. */ useL1Layer(driver: CreateDriverResult<L1CacheDriver>): this; /** * Add a L2 layer to your store. This is usually something * distributed like Redis, DynamoDB, Sql database, etc. */ useL2Layer(driver: CreateDriverResult<L2CacheDriver>): this; /** * Add a bus to your store. It will be used to synchronize L1 layers between * different instances of your application. */ useBus(bus: CreateBusDriverResult): this; get entry(): { options: RawCommonOptions & { prefix?: string; }; l1: CreateDriverResult<L1CacheDriver> | undefined; l2: CreateDriverResult<L2CacheDriver> | undefined; bus: CreateBusDriverResult | undefined; }; } declare class BentoCache<KnownCaches extends Record<string, BentoStore>> implements CacheProvider { #private; constructor(config: RawBentoCacheOptions & { default: keyof KnownCaches; stores: KnownCaches; plugins?: BentoCachePlugin[]; }); get defaultStoreName(): string; /** * Use a registered cache driver */ use<CacheName extends keyof KnownCaches>(cache?: CacheName): CacheProvider; /** * Subscribe to a given cache event */ on<Event extends keyof CacheEvents>(event: Event, callback: (arg: CacheEvents[Event]) => void): this; /** * Subscribe to a given cache event only once */ once<Event extends keyof CacheEvents>(event: Event, callback: (arg: CacheEvents[Event]) => void): this; /** * Unsubscribe the callback from the given event */ off<Event extends keyof CacheEvents>(event: Event, callback: (arg: CacheEvents[Event]) => void): this; /** * Returns a new instance of the driver namespaced */ namespace(namespace: string): CacheProvider; /** * Get a value from the cache */ get<T = any>(options: GetOptions<T>): Promise<T>; /** * Put a value in the cache * Returns true if the value was set, false otherwise */ set(options: SetOptions): Promise<boolean>; /** * Put a value in the cache forever * Returns true if the value was set, false otherwise */ setForever(options: SetOptions): Promise<boolean>; /** * Retrieve an item from the cache if it exists, otherwise store the value * provided by the factory and return it */ getOrSet<T>(options: GetOrSetOptions<T>): Promise<T>; /** * Retrieve an item from the cache if it exists, otherwise store the value * provided by the factory forever and return it */ getOrSetForever<T>(options: GetOrSetForeverOptions<T>): Promise<T>; /** * Check if a key exists in the cache */ has(options: HasOptions): Promise<boolean>; /** * Check if key is missing in the cache */ missing(options: HasOptions): Promise<boolean>; /** * Get the value of a key and delete it * * Returns the value if the key exists, undefined otherwise */ pull<T = any>(key: string): Promise<T | null | undefined>; /** * Delete a key from the cache * Returns true if the key was deleted, false otherwise */ delete(keyOrOptions: DeleteOptions): Promise<boolean>; /** * Delete multiple keys from the cache */ deleteMany(options: DeleteManyOptions): Promise<boolean>; /** * Delete all keys with a specific tag */ deleteByTag(options: DeleteByTagOptions): Promise<boolean>; /** * Expire a key from the cache. * Entry will not be fully deleted but expired and * retained for the grace period if enabled. */ expire(options: ExpireOptions): Promise<boolean>; /** * Remove all items from the cache */ clear(options?: ClearOptions): Promise<void>; /** * Remove all items from all caches */ clearAll(options?: ClearOptions): Promise<void>; /** * Closes the connection to the cache */ disconnect(): Promise<void>; /** * Disconnect all cache connections created by the manager */ disconnectAll(): Promise<void>; } export { type BusOptions as B, type CacheDriverOptions as C, type DialectName as D, type Emitter as E, type GetOrSetOptions as G, type HasOptions as H, type L1CacheDriver as L, type RawCommonOptions as R, type SetCommonOptions as S, type CreateDriverResult as a, type CreateBusDriverResult as b, type L2CacheDriver as c, type CacheSerializer as d, type CacheStackDrivers as e, type BentoCachePlugin as f, type BusDriver as g, type CacheBusMessage as h, CacheBusMessageType as i, type CacheEvents as j, type CacheEvent as k, type CacheProvider as l, type RawBentoCacheOptions as m, type GetOrSetForeverOptions as n, type SetOptions as o, type GetOptions as p, type DeleteOptions as q, type DeleteManyOptions as r, type DeleteByTagOptions as s, type ExpireOptions as t, type ClearOptions as u, errors as v, BentoCache as w, bentostore as x };