@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
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,1861 @@
|
|
|
1
|
+
import { ModuleMetadata, FactoryProvider, NestInterceptor, ExecutionContext, CallHandler, DynamicModule } from '@nestjs/common';
|
|
2
|
+
import { Reflector, HttpAdapterHost } from '@nestjs/core';
|
|
3
|
+
import { Observable } from 'rxjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Thrown for invalid configuration: bad decorator or module options, an unknown store name, or
|
|
7
|
+
* an invalid per-call argument.
|
|
8
|
+
*/
|
|
9
|
+
declare class CacheConfigError extends Error {
|
|
10
|
+
constructor(message: string);
|
|
11
|
+
/**
|
|
12
|
+
* The ESM and CommonJS builds each define this class, so `instanceof` also accepts any `Error`
|
|
13
|
+
* named `CacheConfigError`. Subclasses keep the normal prototype check.
|
|
14
|
+
*/
|
|
15
|
+
static [Symbol.hasInstance](value: unknown): boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A cache key: a template rendered against the method arguments (`'user:{0}'`, `'{0.id}'`), or
|
|
20
|
+
* a callback of the arguments. Without one, the key is built from all the arguments.
|
|
21
|
+
*/
|
|
22
|
+
type KeySpec<A extends unknown[]> = string | ((...args: A) => string);
|
|
23
|
+
/**
|
|
24
|
+
* The tags of a cached method (spec 2.1): templates with the key syntax (`'{0}'`, `'{0.id}'`),
|
|
25
|
+
* rendered against the call's arguments, or a callback of the result then the arguments.
|
|
26
|
+
*/
|
|
27
|
+
type TagSpec<A extends unknown[], R> = readonly string[] | ((result: R, ...args: A) => readonly string[]);
|
|
28
|
+
/** The tags `@CacheEvict` invalidates: templates over the arguments, or a callback of them. */
|
|
29
|
+
type EvictTagSpec<A extends unknown[]> = readonly string[] | ((...args: A) => readonly string[]);
|
|
30
|
+
/**
|
|
31
|
+
* The expiry strategy of a call that does not load (`@CachePut`, `set`, `setMany`, `get`,
|
|
32
|
+
* `getMany`): `'fixed'` (the default), `'swr'` with `staleTtl` (ms an entry is served stale
|
|
33
|
+
* after `ttl`), or `'sliding'` with an optional `maxTtl` cap (ms). `softTimeout` is not
|
|
34
|
+
* supported here; see `LoadStrategyOptions`.
|
|
35
|
+
*/
|
|
36
|
+
type StrategyOptions = {
|
|
37
|
+
strategy?: 'fixed';
|
|
38
|
+
staleTtl?: never;
|
|
39
|
+
maxTtl?: never;
|
|
40
|
+
softTimeout?: never;
|
|
41
|
+
} | {
|
|
42
|
+
strategy: 'swr';
|
|
43
|
+
staleTtl: number;
|
|
44
|
+
maxTtl?: never;
|
|
45
|
+
softTimeout?: never;
|
|
46
|
+
} | {
|
|
47
|
+
strategy: 'sliding';
|
|
48
|
+
maxTtl?: number;
|
|
49
|
+
staleTtl?: never;
|
|
50
|
+
softTimeout?: never;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* The expiry strategy of a call that loads (`@Cacheable`, `@HttpCache`, `getOrSet`,
|
|
54
|
+
* `getOrSetMany`): `StrategyOptions` plus `softTimeout` (swr only). On a stale hit, wait up to
|
|
55
|
+
* `softTimeout` ms for the background refresh and return its value if it lands in time, else
|
|
56
|
+
* the stale one.
|
|
57
|
+
*/
|
|
58
|
+
type LoadStrategyOptions = {
|
|
59
|
+
strategy?: 'fixed';
|
|
60
|
+
staleTtl?: never;
|
|
61
|
+
maxTtl?: never;
|
|
62
|
+
softTimeout?: never;
|
|
63
|
+
} | {
|
|
64
|
+
strategy: 'swr';
|
|
65
|
+
staleTtl: number;
|
|
66
|
+
maxTtl?: never;
|
|
67
|
+
softTimeout?: number;
|
|
68
|
+
} | {
|
|
69
|
+
strategy: 'sliding';
|
|
70
|
+
maxTtl?: number;
|
|
71
|
+
staleTtl?: never;
|
|
72
|
+
softTimeout?: never;
|
|
73
|
+
};
|
|
74
|
+
interface TargetOptions {
|
|
75
|
+
namespace?: string;
|
|
76
|
+
store?: string;
|
|
77
|
+
}
|
|
78
|
+
interface WritePolicy$1<C extends unknown[], R> {
|
|
79
|
+
ttl?: number;
|
|
80
|
+
cacheNull?: boolean;
|
|
81
|
+
nullTtl?: number;
|
|
82
|
+
condition?: (...args: C) => boolean;
|
|
83
|
+
unless?: (result: R) => boolean;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Options of `@Cacheable`. `K`, `C` and `G` are the argument lists the `key`, `condition` and
|
|
87
|
+
* `tags` callbacks declare; `R` is the method's resolved result.
|
|
88
|
+
*/
|
|
89
|
+
type CacheableOptions<K extends unknown[], C extends unknown[], R, G extends unknown[] = never[]> = TargetOptions & LoadStrategyOptions & WritePolicy$1<C, R> & {
|
|
90
|
+
key?: KeySpec<K>;
|
|
91
|
+
lock?: boolean;
|
|
92
|
+
tags?: TagSpec<G, R>;
|
|
93
|
+
};
|
|
94
|
+
/** Options of `@CachePut`: those of `@Cacheable` without `lock` and `softTimeout`. */
|
|
95
|
+
type CachePutOptions<K extends unknown[], C extends unknown[], R, G extends unknown[] = never[]> = TargetOptions & StrategyOptions & WritePolicy$1<C, R> & {
|
|
96
|
+
key?: KeySpec<K>;
|
|
97
|
+
tags?: TagSpec<G, R>;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Options of `@CacheEvict`: evict `key` (one spec or several) and invalidate `tags`, or clear
|
|
101
|
+
* the whole `namespace` with `allEntries: true`. `beforeInvocation: true` evicts before the
|
|
102
|
+
* method runs; by default eviction follows a successful call.
|
|
103
|
+
*/
|
|
104
|
+
type CacheEvictOptions<A extends unknown[], G extends unknown[] = never[]> = (TargetOptions & {
|
|
105
|
+
key?: KeySpec<A> | readonly KeySpec<A>[];
|
|
106
|
+
allEntries?: false;
|
|
107
|
+
beforeInvocation?: boolean;
|
|
108
|
+
tags?: EvictTagSpec<G>;
|
|
109
|
+
}) | {
|
|
110
|
+
namespace: string;
|
|
111
|
+
store?: string;
|
|
112
|
+
allEntries: true;
|
|
113
|
+
key?: never;
|
|
114
|
+
beforeInvocation?: boolean;
|
|
115
|
+
tags?: EvictTagSpec<G>;
|
|
116
|
+
};
|
|
117
|
+
type MethodFn<A extends unknown[], R> = (...args: [...A, ...never[]]) => Promise<R>;
|
|
118
|
+
/** `G` is the argument list a tags callback declares; it is checked like `K` and `C`. */
|
|
119
|
+
type AsyncMethodDecorator<K extends unknown[], C extends unknown[], R, G extends unknown[] = never[]> = <T extends MethodFn<K, R> & MethodFn<C, R> & MethodFn<G, R>>(target: object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => void;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Caches the result of an async method: a hit returns the cached value without running the
|
|
123
|
+
* method; a miss runs it and stores the result. Invalid options throw `CacheConfigError` at
|
|
124
|
+
* class definition.
|
|
125
|
+
*/
|
|
126
|
+
declare function Cacheable<K extends unknown[] = never[], C extends unknown[] = never[], R = unknown, G extends unknown[] = never[]>(options?: CacheableOptions<K, C, R, G>): AsyncMethodDecorator<K, C, R, G>;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Always runs the async method and writes its result to the cache (unless `condition` is false
|
|
130
|
+
* or `unless` is true). Invalid options throw `CacheConfigError` at class definition.
|
|
131
|
+
*/
|
|
132
|
+
declare function CachePut<K extends unknown[] = never[], C extends unknown[] = never[], R = unknown, G extends unknown[] = never[]>(options?: CachePutOptions<K, C, R, G>): AsyncMethodDecorator<K, C, R, G>;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Evicts cache entries around an async method: keys, tags or a whole namespace, after the
|
|
136
|
+
* method succeeds (or before it, with `beforeInvocation`). Eviction failures never reject the
|
|
137
|
+
* call. Invalid options throw `CacheConfigError` at class definition.
|
|
138
|
+
*/
|
|
139
|
+
declare function CacheEvict<K extends unknown[] = never[], G extends unknown[] = never[]>(options?: CacheEvictOptions<K, G>): AsyncMethodDecorator<K, never[], unknown, G>;
|
|
140
|
+
|
|
141
|
+
/** The state of a `CircuitBreakerStore`, as `breaker` events report it. */
|
|
142
|
+
type BreakerState = 'closed' | 'open' | 'half-open';
|
|
143
|
+
/** How much the library logs: nothing, errors and warnings (the default), or also one debug line per event. */
|
|
144
|
+
type CacheLogLevel = 'off' | 'error' | 'debug';
|
|
145
|
+
/**
|
|
146
|
+
* The operation an `error` event reports as failed.
|
|
147
|
+
*
|
|
148
|
+
* Provided by the library. New members, events, fields or values may be added in a minor release;
|
|
149
|
+
* handle unknown ones.
|
|
150
|
+
*/
|
|
151
|
+
type CacheOperation = 'get' | 'set' | 'delete' | 'clear' | 'deserialize' | 'key' | 'publish' | 'subscribe' | 'refresh' | 'lock' | 'version'
|
|
152
|
+
/** An invalid tag list (a throwing tag callback included); the entry is not written. */
|
|
153
|
+
| 'tag';
|
|
154
|
+
/**
|
|
155
|
+
* The payload of each `CacheEvents` event. `store` is the store name; `key` and `keys` are the
|
|
156
|
+
* user keys, without the prefix, namespace or version token.
|
|
157
|
+
*
|
|
158
|
+
* Provided by the library. New members, events, fields or values may be added in a minor release;
|
|
159
|
+
* handle unknown ones.
|
|
160
|
+
*/
|
|
161
|
+
interface CacheEventMap {
|
|
162
|
+
/** A read found the entry; `stale` is an `swr` entry past its `ttl`. */
|
|
163
|
+
hit: {
|
|
164
|
+
store: string;
|
|
165
|
+
namespace: string | undefined;
|
|
166
|
+
key: string;
|
|
167
|
+
stale: boolean;
|
|
168
|
+
};
|
|
169
|
+
miss: {
|
|
170
|
+
store: string;
|
|
171
|
+
namespace: string | undefined;
|
|
172
|
+
key: string;
|
|
173
|
+
};
|
|
174
|
+
set: {
|
|
175
|
+
store: string;
|
|
176
|
+
namespace: string | undefined;
|
|
177
|
+
key: string;
|
|
178
|
+
/**
|
|
179
|
+
* The TTL the store was given, in ms: under `swr` it includes `staleTtl`, and it carries the
|
|
180
|
+
* `defaults.jitter` (not under `sliding`).
|
|
181
|
+
*/
|
|
182
|
+
ttl: number;
|
|
183
|
+
};
|
|
184
|
+
delete: {
|
|
185
|
+
store: string;
|
|
186
|
+
namespace: string | undefined;
|
|
187
|
+
/** The user keys deleted, as passed (not the store keys). */
|
|
188
|
+
keys: readonly string[];
|
|
189
|
+
};
|
|
190
|
+
clear: {
|
|
191
|
+
store: string;
|
|
192
|
+
namespace: string;
|
|
193
|
+
};
|
|
194
|
+
/** One loader call finished (`success: false` when it threw). */
|
|
195
|
+
load: {
|
|
196
|
+
store: string;
|
|
197
|
+
namespace: string | undefined;
|
|
198
|
+
/** The loaded key; on a batch load, the first of `keys`. */
|
|
199
|
+
key: string;
|
|
200
|
+
/** Only on a batch load (`getOrSetMany`): every key passed to the loader; `key` is the first. */
|
|
201
|
+
keys?: readonly string[];
|
|
202
|
+
durationMs: number;
|
|
203
|
+
success: boolean;
|
|
204
|
+
};
|
|
205
|
+
/** A cache failure the call did not surface; see `CacheOperation`. */
|
|
206
|
+
error: {
|
|
207
|
+
store: string;
|
|
208
|
+
operation: CacheOperation;
|
|
209
|
+
error: unknown;
|
|
210
|
+
};
|
|
211
|
+
lock: {
|
|
212
|
+
store: string;
|
|
213
|
+
namespace: string | undefined;
|
|
214
|
+
key: string;
|
|
215
|
+
waitedMs: number;
|
|
216
|
+
acquired: boolean;
|
|
217
|
+
};
|
|
218
|
+
breaker: {
|
|
219
|
+
store: string;
|
|
220
|
+
state: BreakerState;
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* What a store gets from `CacheStore.bind`: it reports its own failures (`error`) and breaker
|
|
225
|
+
* state changes (`breaker`) through it; the module adds the store name.
|
|
226
|
+
*
|
|
227
|
+
* Provided by the library. New members, events, fields or values may be added in a minor release;
|
|
228
|
+
* handle unknown ones.
|
|
229
|
+
*/
|
|
230
|
+
interface CacheEventSink {
|
|
231
|
+
emit(event: 'error', payload: {
|
|
232
|
+
operation: CacheOperation;
|
|
233
|
+
error: unknown;
|
|
234
|
+
}): void;
|
|
235
|
+
emit(event: 'breaker', payload: {
|
|
236
|
+
state: BreakerState;
|
|
237
|
+
}): void;
|
|
238
|
+
/**
|
|
239
|
+
* The module's log level, so a store can skip its own warnings at `'off'`. Sinks from
|
|
240
|
+
* `CacheModule` always set it; a missing value (a hand-built sink) means `'error'`.
|
|
241
|
+
*/
|
|
242
|
+
readonly logLevel?: CacheLogLevel;
|
|
243
|
+
}
|
|
244
|
+
type Listener<E extends keyof CacheEventMap> = (payload: CacheEventMap[E]) => void;
|
|
245
|
+
/**
|
|
246
|
+
* The cache event bus, provided by `CacheModule`: inject it and subscribe with `on`. Only the
|
|
247
|
+
* library emits events.
|
|
248
|
+
*
|
|
249
|
+
* Created by Nest; inject it, do not construct it. Constructor parameters are not part of the
|
|
250
|
+
* public API.
|
|
251
|
+
*/
|
|
252
|
+
declare class CacheEvents {
|
|
253
|
+
private readonly onListenerError?;
|
|
254
|
+
private readonly listeners;
|
|
255
|
+
constructor(onListenerError?: ((error: unknown) => void) | undefined);
|
|
256
|
+
/**
|
|
257
|
+
* Calls `listener` with the payload of every `event`, synchronously, in registration order.
|
|
258
|
+
* A listener that throws is isolated: the module logs it (unless `logging.level` is `'off'`)
|
|
259
|
+
* and it never reaches the cache call. Returns a function that removes this registration.
|
|
260
|
+
*/
|
|
261
|
+
on<E extends keyof CacheEventMap>(event: E, listener: Listener<E>): () => void;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/** What the engine stores per entry; a `Serializer` turns it into the stored string. */
|
|
265
|
+
interface CacheEnvelope {
|
|
266
|
+
/** The envelope format version. */
|
|
267
|
+
v: 1;
|
|
268
|
+
/** The cached value; `null` when `nil` is set. */
|
|
269
|
+
value: unknown;
|
|
270
|
+
/** When the entry was written, in ms since the epoch. */
|
|
271
|
+
storedAt: number;
|
|
272
|
+
/** When the entry expires (ms since the epoch); under `swr`, when its stale window ends. */
|
|
273
|
+
expiresAt?: number;
|
|
274
|
+
/** `swr` only: when the entry turns stale (ms since the epoch); it is fresh before. */
|
|
275
|
+
staleAt?: number;
|
|
276
|
+
/** Set on a stored empty value (`cacheNull`): which one it was, as `value` is `null`. */
|
|
277
|
+
nil?: 'null' | 'undefined';
|
|
278
|
+
/** The tag versions the entry was written with, tag to token; absent on an untagged entry. */
|
|
279
|
+
tags?: Readonly<Record<string, string>>;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Turns an entry's envelope into the string a store holds, and back
|
|
284
|
+
* (`CacheModuleOptions.serializer`).
|
|
285
|
+
* `deserialize` must throw on input it does not recognise: the engine reports that as an `error`
|
|
286
|
+
* event with operation `'deserialize'` and treats the entry as a miss.
|
|
287
|
+
*
|
|
288
|
+
* `deserialize(serialize(e))` must keep every field of `e`, including fields this version does
|
|
289
|
+
* not know.
|
|
290
|
+
*
|
|
291
|
+
* Implemented by you. In 1.x, members are only added as optional, and the library checks that
|
|
292
|
+
* they exist before calling them.
|
|
293
|
+
*/
|
|
294
|
+
interface Serializer {
|
|
295
|
+
serialize(envelope: CacheEnvelope): string;
|
|
296
|
+
deserialize(raw: string): CacheEnvelope;
|
|
297
|
+
}
|
|
298
|
+
/** The default serializer: `JSON.stringify` and `JSON.parse`, with an envelope shape check. */
|
|
299
|
+
declare const jsonSerializer: Serializer;
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* A message announcing that keys were written or removed on one instance.
|
|
303
|
+
* Receivers drop the matching entries from their local (L1) cache.
|
|
304
|
+
*
|
|
305
|
+
* `origin` identifies the publishing instance, so receivers can ignore their
|
|
306
|
+
* own messages. A message carries either exact `keys` or a `prefix`.
|
|
307
|
+
*
|
|
308
|
+
* Provided by the library. New members, events, fields or values may be added in a minor release;
|
|
309
|
+
* handle unknown ones.
|
|
310
|
+
*
|
|
311
|
+
* A bus passes messages through as opaque JSON.
|
|
312
|
+
*/
|
|
313
|
+
type InvalidationMessage = {
|
|
314
|
+
origin: string;
|
|
315
|
+
keys: readonly string[];
|
|
316
|
+
} | {
|
|
317
|
+
origin: string;
|
|
318
|
+
prefix: string;
|
|
319
|
+
};
|
|
320
|
+
/**
|
|
321
|
+
* Cross-instance channel that keeps local caches in sync (for example Redis
|
|
322
|
+
* Pub/Sub, NATS or Kafka). It only affects the freshness of L1 entries; the
|
|
323
|
+
* data in the shared store is always correct.
|
|
324
|
+
*
|
|
325
|
+
* Implemented by you. In 1.x, members are only added as optional, and the library checks that
|
|
326
|
+
* they exist before calling them.
|
|
327
|
+
*/
|
|
328
|
+
interface InvalidationBus {
|
|
329
|
+
/** Broadcasts a message to every subscribed instance. */
|
|
330
|
+
publish(message: InvalidationMessage): Promise<void>;
|
|
331
|
+
/**
|
|
332
|
+
* Registers the handler that receives messages from the channel. If it rejects, the bus
|
|
333
|
+
* should keep trying to subscribe (for example when its connection becomes ready), and a
|
|
334
|
+
* later call should retry rather than return the same rejection.
|
|
335
|
+
*/
|
|
336
|
+
subscribe(handler: (message: InvalidationMessage) => void): Promise<void>;
|
|
337
|
+
/**
|
|
338
|
+
* Registers a handler called after the connection is re-established, or after a
|
|
339
|
+
* subscription that had failed is established later. Messages may have been missed
|
|
340
|
+
* meanwhile, so receivers clear their L1.
|
|
341
|
+
*/
|
|
342
|
+
onReconnect(handler: () => void): void;
|
|
343
|
+
/**
|
|
344
|
+
* Optional. Registers a handler for errors the bus handles internally, such as a lost
|
|
345
|
+
* subscriber connection or a failed re-subscribe. `TieredStore` reports them as `error`
|
|
346
|
+
* events with `operation: 'subscribe'`. Handlers must not throw.
|
|
347
|
+
*/
|
|
348
|
+
onError?(handler: (error: unknown) => void): void;
|
|
349
|
+
/** Releases the bus connection. Called at shutdown; must be idempotent. */
|
|
350
|
+
close(): Promise<void>;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Distributed mutual exclusion, used by the cache engine to avoid stampedes across instances.
|
|
354
|
+
*
|
|
355
|
+
* Implemented by you. In 1.x, members are only added as optional, and the library checks that
|
|
356
|
+
* they exist before calling them.
|
|
357
|
+
*/
|
|
358
|
+
interface LockProvider {
|
|
359
|
+
/**
|
|
360
|
+
* Tries to take the lock for `key`, the complete lock key the engine computed (the provider adds nothing to it), for at most `ttlMs` milliseconds (integer >= 1). Returns a
|
|
361
|
+
* handle when acquired, or `undefined` when the lock is held by someone else. Never waits.
|
|
362
|
+
*/
|
|
363
|
+
acquire(key: string, ttlMs: number): Promise<LockHandle | undefined>;
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Proof of ownership of an acquired lock.
|
|
367
|
+
*
|
|
368
|
+
* Implemented by you. In 1.x, members are only added as optional, and the library checks that
|
|
369
|
+
* they exist before calling them.
|
|
370
|
+
*/
|
|
371
|
+
interface LockHandle {
|
|
372
|
+
/**
|
|
373
|
+
* Releases the lock only if it is still ours (it may have expired and been taken by another
|
|
374
|
+
* owner). A second call is a no-op.
|
|
375
|
+
*/
|
|
376
|
+
release(): Promise<void>;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Contract for a cache backend. Values are opaque serialized strings.
|
|
380
|
+
*
|
|
381
|
+
* Implemented by you. In 1.x, members are only added as optional, and the library checks that
|
|
382
|
+
* they exist before calling them.
|
|
383
|
+
*/
|
|
384
|
+
interface CacheStore {
|
|
385
|
+
/** Returns the stored string, or `undefined` for a miss or an expired entry. */
|
|
386
|
+
get(key: string): Promise<string | undefined>;
|
|
387
|
+
/**
|
|
388
|
+
* Stores `value` under `key`.
|
|
389
|
+
*
|
|
390
|
+
* @param ttlMs Time to live in milliseconds; always an integer >= 1.
|
|
391
|
+
*/
|
|
392
|
+
set(key: string, value: string, ttlMs: number): Promise<void>;
|
|
393
|
+
/** Removes the given keys. Deleting an unknown key is a no-op. */
|
|
394
|
+
delete(keys: readonly string[]): Promise<void>;
|
|
395
|
+
/**
|
|
396
|
+
* Removes every key that starts with `prefix`. An empty prefix (`''`)
|
|
397
|
+
* removes everything.
|
|
398
|
+
*/
|
|
399
|
+
clear(prefix: string): Promise<void>;
|
|
400
|
+
/**
|
|
401
|
+
* Optional. Reads the entry and resets its TTL to `ttlMs` in one step
|
|
402
|
+
* (milliseconds, integer >= 1). Returns `undefined` for a miss. Used by the `sliding` strategy. The memory and Redis stores are atomic; a
|
|
403
|
+
* tiered store refreshes the window on L1 misses only.
|
|
404
|
+
* Stores should implement it: when it is missing, the engine falls back to `get` followed by a
|
|
405
|
+
* `set`, which is not atomic.
|
|
406
|
+
*/
|
|
407
|
+
getAndTouch?(key: string, ttlMs: number): Promise<string | undefined>;
|
|
408
|
+
/**
|
|
409
|
+
* Optional. Reads several keys at once. The result has one element per key, in the same order,
|
|
410
|
+
* `undefined` for a miss or an expired entry. An empty list resolves `[]` without any command.
|
|
411
|
+
* When missing, callers fall back to one `get` per key.
|
|
412
|
+
*/
|
|
413
|
+
getMany?(keys: readonly string[]): Promise<(string | undefined)[]>;
|
|
414
|
+
/**
|
|
415
|
+
* Optional. Stores several entries at once; each `ttlMs` is an integer >= 1. An empty list
|
|
416
|
+
* resolves without any command. When missing, callers fall back to one `set` per entry.
|
|
417
|
+
*/
|
|
418
|
+
setMany?(entries: readonly {
|
|
419
|
+
key: string;
|
|
420
|
+
value: string;
|
|
421
|
+
ttlMs: number;
|
|
422
|
+
}[]): Promise<void>;
|
|
423
|
+
/**
|
|
424
|
+
* Optional. Like `get`, but rejects instead of degrading when the durable tier cannot be read.
|
|
425
|
+
* Stores whose `get` already rejects on failure (memory, Redis) need not implement it.
|
|
426
|
+
* Implementing it also opts the store into the version-token fallback (a failed version read
|
|
427
|
+
* reuses the last token this process knew).
|
|
428
|
+
*/
|
|
429
|
+
getStrict?(key: string): Promise<string | undefined>;
|
|
430
|
+
/**
|
|
431
|
+
* Optional. Like `set`, but rejects unless the durable tier stored the value.
|
|
432
|
+
* Stores whose `set` already rejects on failure need not implement it.
|
|
433
|
+
*/
|
|
434
|
+
setStrict?(key: string, value: string, ttlMs: number): Promise<void>;
|
|
435
|
+
/**
|
|
436
|
+
* Optional. Distributed lock backed by this store. Absent when the store cannot lock; the
|
|
437
|
+
* engine then falls back to a per-process lock.
|
|
438
|
+
*/
|
|
439
|
+
readonly lock?: LockProvider;
|
|
440
|
+
/**
|
|
441
|
+
* Optional bus that `TieredStore` uses to sync L1 caches when this store is
|
|
442
|
+
* the L2.
|
|
443
|
+
*/
|
|
444
|
+
readonly invalidation?: InvalidationBus;
|
|
445
|
+
/**
|
|
446
|
+
* Optional. Called once at module init with a sink scoped to this store's
|
|
447
|
+
* name, so the store can report errors it handles internally.
|
|
448
|
+
*/
|
|
449
|
+
bind?(events: CacheEventSink): void;
|
|
450
|
+
/**
|
|
451
|
+
* Optional. Health probe used by `CacheHealthIndicator`: resolves when the store is
|
|
452
|
+
* reachable and rejects otherwise. Absent when the store cannot be probed.
|
|
453
|
+
*/
|
|
454
|
+
ping?(): Promise<void>;
|
|
455
|
+
/** Optional. Called at shutdown to release resources; must be idempotent. */
|
|
456
|
+
close?(): Promise<void>;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/** `defaults.lock`: the distributed lock taken on a miss, for stores that have one. */
|
|
460
|
+
interface CacheLockDefaults {
|
|
461
|
+
/**
|
|
462
|
+
* Whether `getOrSet`, `@Cacheable` and `@HttpCache` lock by default; a call's `lock` overrides
|
|
463
|
+
* it. Default `false`.
|
|
464
|
+
*/
|
|
465
|
+
enabled?: boolean;
|
|
466
|
+
/** How long a lock is held at most, in ms. Default 10 000. */
|
|
467
|
+
ttl?: number;
|
|
468
|
+
/**
|
|
469
|
+
* How long a caller that did not get the lock waits for the holder's value, in ms; then it
|
|
470
|
+
* loads without the lock. Default 3 000.
|
|
471
|
+
*/
|
|
472
|
+
waitTimeout?: number;
|
|
473
|
+
/** Delay between two re-reads of the entry while waiting, in ms. Default 50. */
|
|
474
|
+
retryDelay?: number;
|
|
475
|
+
}
|
|
476
|
+
/** `defaults`: what a call or decorator that does not set an option uses. */
|
|
477
|
+
interface CacheDefaults {
|
|
478
|
+
/** Entry TTL in ms. Default 60 000. */
|
|
479
|
+
ttl?: number;
|
|
480
|
+
/** Random TTL spread: `ttl x (1 + r)`, `r` in `[-jitter, +jitter]`; in `[0, 1)`. Default 0. */
|
|
481
|
+
jitter?: number;
|
|
482
|
+
/** Whether `null` and `undefined` results are stored. Default `false`. */
|
|
483
|
+
cacheNull?: boolean;
|
|
484
|
+
/** TTL of a stored empty value, in ms. Default 30 000. */
|
|
485
|
+
nullTtl?: number;
|
|
486
|
+
lock?: CacheLockDefaults;
|
|
487
|
+
}
|
|
488
|
+
/** Options of `CacheModule.forRoot`, and the value `forRootAsync`'s `useFactory` resolves. */
|
|
489
|
+
interface CacheModuleOptions {
|
|
490
|
+
/** Prepended to every key as `<prefix>:`. Default none. */
|
|
491
|
+
prefix?: string;
|
|
492
|
+
/**
|
|
493
|
+
* Named stores; `default` is required when `stores` is set. Default
|
|
494
|
+
* `{ default: memoryStore() }`.
|
|
495
|
+
*/
|
|
496
|
+
stores?: {
|
|
497
|
+
default: CacheStore;
|
|
498
|
+
[name: string]: CacheStore;
|
|
499
|
+
};
|
|
500
|
+
defaults?: CacheDefaults;
|
|
501
|
+
/** Turns entry envelopes into the strings stores hold. Default `jsonSerializer`. */
|
|
502
|
+
serializer?: Serializer;
|
|
503
|
+
/** `level` defaults to `'error'`. */
|
|
504
|
+
logging?: {
|
|
505
|
+
level?: CacheLogLevel;
|
|
506
|
+
};
|
|
507
|
+
/**
|
|
508
|
+
* Percent-encodes `%` and `:` in string and number arguments rendered into template keys.
|
|
509
|
+
* Defaults to `false`; key callbacks are never escaped.
|
|
510
|
+
*/
|
|
511
|
+
escapeKeyArgs?: boolean;
|
|
512
|
+
/**
|
|
513
|
+
* Namespaces with `versioned: true` get O(1) `clear` through a version token in their keys.
|
|
514
|
+
* Matching is exact: a sub-namespace such as `users:admin` does not follow a versioned `users`.
|
|
515
|
+
*/
|
|
516
|
+
namespaces?: {
|
|
517
|
+
[namespace: string]: {
|
|
518
|
+
versioned?: boolean;
|
|
519
|
+
};
|
|
520
|
+
};
|
|
521
|
+
/** `cacheTtl` (ms, default 1000) is how long a version token is cached in this process. */
|
|
522
|
+
versioning?: {
|
|
523
|
+
cacheTtl?: number;
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
/** Options of `CacheModule.forRootAsync`: `useFactory` resolves the `CacheModuleOptions`. */
|
|
527
|
+
interface CacheModuleAsyncOptions {
|
|
528
|
+
/** Registers the module globally. Default `false`. */
|
|
529
|
+
isGlobal?: boolean;
|
|
530
|
+
imports?: ModuleMetadata['imports'];
|
|
531
|
+
inject?: FactoryProvider['inject'];
|
|
532
|
+
useFactory: (...args: never[]) => CacheModuleOptions | Promise<CacheModuleOptions>;
|
|
533
|
+
}
|
|
534
|
+
interface ResolvedDefaults {
|
|
535
|
+
ttl: number;
|
|
536
|
+
jitter: number;
|
|
537
|
+
cacheNull: boolean;
|
|
538
|
+
nullTtl: number;
|
|
539
|
+
lock: {
|
|
540
|
+
enabled: boolean;
|
|
541
|
+
ttl: number;
|
|
542
|
+
waitTimeout: number;
|
|
543
|
+
retryDelay: number;
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
interface ResolvedCacheOptions {
|
|
547
|
+
prefix: string | undefined;
|
|
548
|
+
stores: ReadonlyMap<string, CacheStore>;
|
|
549
|
+
defaults: ResolvedDefaults;
|
|
550
|
+
serializer: Serializer;
|
|
551
|
+
logging: {
|
|
552
|
+
level: CacheLogLevel;
|
|
553
|
+
};
|
|
554
|
+
escapeKeyArgs: boolean;
|
|
555
|
+
versionedNamespaces: ReadonlySet<string>;
|
|
556
|
+
versionCacheTtl: number;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/** A span attribute value the library sets: a string, number, boolean or list of strings. */
|
|
560
|
+
type SpanAttributeValue = string | number | boolean | string[];
|
|
561
|
+
/**
|
|
562
|
+
* Structural subset of an OpenTelemetry `SpanContext`: what a link needs to point at a span.
|
|
563
|
+
* Satisfied by the result of `span.spanContext()` in the OpenTelemetry JS API 1.x.
|
|
564
|
+
*
|
|
565
|
+
* Satisfied by the client you pass in. In 1.x, members are only added as optional, and the
|
|
566
|
+
* library checks that they exist before calling them.
|
|
567
|
+
*/
|
|
568
|
+
interface SpanContextLike {
|
|
569
|
+
traceId: string;
|
|
570
|
+
spanId: string;
|
|
571
|
+
traceFlags: number;
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Structural subset of an OpenTelemetry `Span`: only the methods the library calls. Satisfied by
|
|
575
|
+
* the spans of the OpenTelemetry JS API 1.x, so no dependency on that package is needed.
|
|
576
|
+
*
|
|
577
|
+
* Satisfied by the client you pass in. In 1.x, members are only added as optional, and the
|
|
578
|
+
* library checks that they exist before calling them.
|
|
579
|
+
*/
|
|
580
|
+
interface SpanLike {
|
|
581
|
+
/** Sets one attribute (`cache.store`, `cache.result`, ...). */
|
|
582
|
+
setAttribute(key: string, value: SpanAttributeValue): unknown;
|
|
583
|
+
/** Adds an event; the library adds `cache.error` with `cache.error.operation` on a swallowed error. */
|
|
584
|
+
addEvent(name: string, attributes?: Record<string, SpanAttributeValue>): unknown;
|
|
585
|
+
/** Records an error: one the caller receives, or one the library swallowed. */
|
|
586
|
+
recordException(exception: unknown): void;
|
|
587
|
+
/** Sets the status; the library only sets `{ code: 2 }` (`ERROR`) for an error the caller receives. */
|
|
588
|
+
setStatus(status: {
|
|
589
|
+
code: number;
|
|
590
|
+
message?: string;
|
|
591
|
+
}): unknown;
|
|
592
|
+
/** Ends the span; the library calls it exactly once per span it starts. */
|
|
593
|
+
end(): void;
|
|
594
|
+
/** The span's identity, used to link a background `cache.refresh` to the span that started it. */
|
|
595
|
+
spanContext(): SpanContextLike;
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Structural subset of an OpenTelemetry `SpanOptions`: the options the library passes.
|
|
599
|
+
*
|
|
600
|
+
* Satisfied by the client you pass in. In 1.x, members are only added as optional, and the
|
|
601
|
+
* library checks that they exist before calling them.
|
|
602
|
+
*/
|
|
603
|
+
interface SpanOptionsLike {
|
|
604
|
+
/** Attributes set when the span starts. */
|
|
605
|
+
attributes?: Record<string, SpanAttributeValue>;
|
|
606
|
+
/** `true` starts a new trace (the background `cache.refresh` span). */
|
|
607
|
+
root?: boolean;
|
|
608
|
+
/** Links to related spans (`cache.refresh` links to the span that triggered it). */
|
|
609
|
+
links?: {
|
|
610
|
+
context: SpanContextLike;
|
|
611
|
+
}[];
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Structural subset of an OpenTelemetry `Tracer`. Pass `trace.getTracer('my-app')` from
|
|
615
|
+
* the OpenTelemetry JS API 1.x; it is assignable without a cast.
|
|
616
|
+
*
|
|
617
|
+
* Satisfied by the client you pass in. In 1.x, members are only added as optional, and the
|
|
618
|
+
* library checks that they exist before calling them.
|
|
619
|
+
*/
|
|
620
|
+
interface TracerLike {
|
|
621
|
+
/**
|
|
622
|
+
* Starts a span, makes it the active one while `fn` runs (so spans started inside `fn` are
|
|
623
|
+
* its children), and returns what `fn` returns. Must call `fn` synchronously.
|
|
624
|
+
*/
|
|
625
|
+
startActiveSpan<F extends (span: SpanLike) => unknown>(name: string, options: SpanOptionsLike, fn: F): ReturnType<F>;
|
|
626
|
+
/** Starts a span under the active one without activating it (the `cache.lock` wait). */
|
|
627
|
+
startSpan(name: string, options?: SpanOptionsLike): SpanLike;
|
|
628
|
+
}
|
|
629
|
+
/** Options of `CacheTracingModule.forRoot`. */
|
|
630
|
+
interface CacheTracingOptions {
|
|
631
|
+
/** The tracer spans are started with, for example `trace.getTracer('my-app')`. */
|
|
632
|
+
tracer: TracerLike;
|
|
633
|
+
/**
|
|
634
|
+
* Record `cache.key`: the full key (prefix and namespace version included), an array of full
|
|
635
|
+
* keys on batch calls and `delete`, the tag names on `invalidateTags`. Default `false`: keys
|
|
636
|
+
* may hold user data and have a very large number of values.
|
|
637
|
+
*/
|
|
638
|
+
recordKeys?: boolean;
|
|
639
|
+
}
|
|
640
|
+
/** Options of `CacheTracingModule.forRootAsync`: `useFactory` resolves the module options. */
|
|
641
|
+
interface CacheTracingAsyncOptions {
|
|
642
|
+
imports?: ModuleMetadata['imports'];
|
|
643
|
+
/** Providers passed to `useFactory`, in order. */
|
|
644
|
+
inject?: FactoryProvider['inject'];
|
|
645
|
+
/** Returns the module options, or a promise of them. */
|
|
646
|
+
useFactory: (...args: never[]) => CacheTracingOptions | Promise<CacheTracingOptions>;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
/** The store (and namespace) a main or refresh span is about. */
|
|
650
|
+
interface TraceBase {
|
|
651
|
+
store: string;
|
|
652
|
+
namespace?: string;
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* Internal: not part of the public API. Owns the user's tracer once `CacheTracingModule`
|
|
656
|
+
* registers it, and the current cache scope (an `AsyncLocalStorage`, created on registration).
|
|
657
|
+
* Until then every method calls its function directly or does nothing. A throwing tracer or span
|
|
658
|
+
* method is logged (as `'tracing'`) and never reaches the caller, and never runs a function twice.
|
|
659
|
+
*/
|
|
660
|
+
declare class CacheTracing {
|
|
661
|
+
private readonly logger?;
|
|
662
|
+
private on;
|
|
663
|
+
/** Whether a tracer is registered. */
|
|
664
|
+
get enabled(): boolean;
|
|
665
|
+
/** Whether `cache.key` is recorded; lets a caller skip building a key list for `key`. */
|
|
666
|
+
get recordKeys(): boolean;
|
|
667
|
+
/** Registers the tracer; throws `CacheConfigError` for invalid options or a second call. */
|
|
668
|
+
use(options: CacheTracingOptions): void;
|
|
669
|
+
/**
|
|
670
|
+
* Runs `fn` in a new active main span `name` and its own scope. A rejection (or a
|
|
671
|
+
* synchronous throw) records the exception and sets `ERROR`, then reaches the caller as is.
|
|
672
|
+
* A `'batch'` scope counts hits, stale hits and misses instead of setting `cache.result`, and
|
|
673
|
+
* its span always gets the three counters, 0 when none.
|
|
674
|
+
*/
|
|
675
|
+
span<T>(name: string, base: TraceBase, fn: () => Promise<T>, kind?: 'single' | 'batch'): Promise<T>;
|
|
676
|
+
/**
|
|
677
|
+
* Runs `fn` in an active child span of the current one. A rejection marks the child and the
|
|
678
|
+
* current scope's span `ERROR`. Untraced outside a scope or after the scope ended.
|
|
679
|
+
*/
|
|
680
|
+
child<T>(name: 'cache.load', fn: () => Promise<T>): Promise<T>;
|
|
681
|
+
/**
|
|
682
|
+
* Runs `fn` in a new root span `cache.refresh` linked to the current scope's span (no link
|
|
683
|
+
* outside a scope), in a scope of its own: a background refresh outlives its trigger. If the
|
|
684
|
+
* tracer fails, `fn` runs untraced outside any scope, so it never writes to its trigger.
|
|
685
|
+
*/
|
|
686
|
+
root<T>(base: TraceBase, fn: () => Promise<T>): Promise<T>;
|
|
687
|
+
/**
|
|
688
|
+
* Starts `cache.lock` under the active span, not activated. `end` is idempotent; `true` or
|
|
689
|
+
* `false` sets `cache.lock.acquired`, `undefined` (the acquire failed) sets nothing.
|
|
690
|
+
*/
|
|
691
|
+
lockSpan(): {
|
|
692
|
+
end(acquired: boolean | undefined): void;
|
|
693
|
+
};
|
|
694
|
+
/** A hit: `cache.result` `'hit'`/`'stale'` on a single scope, a count on a batch scope. */
|
|
695
|
+
hit(stale: boolean): void;
|
|
696
|
+
/** A miss: `cache.result = 'miss'` on a single scope, a count on a batch scope. */
|
|
697
|
+
miss(): void;
|
|
698
|
+
/** Sets `cache.result` (`'bypass'`: the call skipped the cache). */
|
|
699
|
+
result(value: 'bypass'): void;
|
|
700
|
+
/** Sets one attribute on the current scope's span. */
|
|
701
|
+
set(key: string, value: SpanAttributeValue): void;
|
|
702
|
+
/** Sets `cache.key` (a full key, or a list of them) when `recordKeys` is on. */
|
|
703
|
+
key(full: string | readonly string[]): void;
|
|
704
|
+
/**
|
|
705
|
+
* A failure the library swallowed: records the exception (unless the span already has it) and
|
|
706
|
+
* a `cache.error` event carrying `cache.error.operation`. The status stays unset, since the
|
|
707
|
+
* caller still gets a result.
|
|
708
|
+
*/
|
|
709
|
+
error(operation: CacheOperation, error: unknown): void;
|
|
710
|
+
/** The live scope, or `undefined` when tracing is off, outside a scope, or after it ended. */
|
|
711
|
+
private current;
|
|
712
|
+
/** Starts an active span that owns a new scope (`span`, `root`). */
|
|
713
|
+
private scoped;
|
|
714
|
+
/**
|
|
715
|
+
* Calls `tracer.startActiveSpan` with `body`. If the tracer throws before calling `body`, or
|
|
716
|
+
* returns without calling it, `untraced` runs instead; if it throws after, the outcome of
|
|
717
|
+
* `body` is kept. Either way the user function runs once: a callback the tracer invokes again,
|
|
718
|
+
* or late (after the fallback ran), only ends its span. A synchronous throw of the user
|
|
719
|
+
* function is rethrown here, not mistaken for a tracer error.
|
|
720
|
+
*/
|
|
721
|
+
private activate;
|
|
722
|
+
/**
|
|
723
|
+
* Runs `run` and ends `span` once when it settles, on a side branch: the caller gets the
|
|
724
|
+
* promise `run` returned, so tracing adds no tick, and the side branch's reactions (registered
|
|
725
|
+
* first) end the span before the caller resumes. The side branch handles the rejection, which
|
|
726
|
+
* still reaches the caller through the original promise. A rejection or synchronous throw
|
|
727
|
+
* first calls `onError`, which records it. With a `scope`, the scope is closed (its batch
|
|
728
|
+
* counters set) before the span ends.
|
|
729
|
+
*/
|
|
730
|
+
private settle;
|
|
731
|
+
/**
|
|
732
|
+
* Marks the scope's span `ERROR` for an error that reaches its caller (a failed child, or the
|
|
733
|
+
* call's own rejection). An error the span already has (from the child, or a swallowed one) is
|
|
734
|
+
* not recorded again.
|
|
735
|
+
*/
|
|
736
|
+
private failScope;
|
|
737
|
+
/** Records `error` on the scope's span, once per error. */
|
|
738
|
+
private record;
|
|
739
|
+
private fail;
|
|
740
|
+
/** Sets the batch counters and closes the scope; the caller ends the span. */
|
|
741
|
+
private close;
|
|
742
|
+
private attribute;
|
|
743
|
+
/** Runs one tracer or span call; a throw is logged and never escapes. */
|
|
744
|
+
private guard;
|
|
745
|
+
private report;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
/** What a token versions: a versioned namespace or a cache tag. */
|
|
749
|
+
type TokenKind = 'ns' | 'tag';
|
|
750
|
+
/**
|
|
751
|
+
* Version tokens per (store, kind, name), for versioned namespaces (`'ns'`) and cache tags
|
|
752
|
+
* (`'tag'`). Emits nothing; store failures reject. A token key is read with `getStrict` and
|
|
753
|
+
* written with `setStrict` when the store has them (a tiered store), so a token is never created
|
|
754
|
+
* or changed in L1 alone while L2 is down. An empty token key counts as missing.
|
|
755
|
+
*/
|
|
756
|
+
declare class VersionTokens {
|
|
757
|
+
private readonly prefix;
|
|
758
|
+
private readonly cacheTtl;
|
|
759
|
+
private readonly kinds;
|
|
760
|
+
/** `maxTagTokens` is `MAX_TAG_TOKENS` outside tests. */
|
|
761
|
+
constructor(prefix: string | undefined, cacheTtl: number, maxTagTokens?: number);
|
|
762
|
+
/** The bump counts `fresh` reads in flight compare, keyed by `<store>\0<name>`. */
|
|
763
|
+
bumpCounts(kind: TokenKind): ReadonlyMap<string, number>;
|
|
764
|
+
/**
|
|
765
|
+
* The token of `name`: cached for `cacheTtl`, else read from the store, and created when the
|
|
766
|
+
* key is missing. Concurrent reads of one name share one store read.
|
|
767
|
+
*/
|
|
768
|
+
current(target: Target, kind: TokenKind, name: string): Promise<string>;
|
|
769
|
+
/** The token this instance has cached, even past `cacheTtl`; never reads the store. */
|
|
770
|
+
cached(target: Target, kind: TokenKind, name: string): string | undefined;
|
|
771
|
+
/**
|
|
772
|
+
* Reads the token from the store (creating it when missing), bypassing the cache, then caches
|
|
773
|
+
* it for `cacheTtl`. A bump that completes during the read keeps its token in the cache.
|
|
774
|
+
*/
|
|
775
|
+
fresh(target: Target, kind: TokenKind, name: string): Promise<string>;
|
|
776
|
+
/**
|
|
777
|
+
* Whether `name` may be re-read now (spec 3.3 step 3): true at most once per `cacheTtl` per
|
|
778
|
+
* (store, name), and the time is recorded. The record keeps at most as many slots as the
|
|
779
|
+
* token cache (`MAX_TAG_TOKENS` for tags), evicting the oldest first.
|
|
780
|
+
*/
|
|
781
|
+
mayRecheck(target: Target, kind: TokenKind, name: string): boolean;
|
|
782
|
+
/**
|
|
783
|
+
* Re-reads the token of `name` from the store, bypassing the cache, for a stamp that differs
|
|
784
|
+
* from the cached token (spec 3.3). Joins the slot's re-read in flight; otherwise starts one
|
|
785
|
+
* when `mayRecheck` allows it, and returns `undefined` (no read) when it does not. Never
|
|
786
|
+
* creates the token: a missing or empty key resolves `undefined` and drops a cached tag
|
|
787
|
+
* token. As with `fresh`, the result is cached unless a bump completed meanwhile; a bump also
|
|
788
|
+
* unregisters the re-read, so no later call joins a read older than the bump. A rejection
|
|
789
|
+
* reaches every waiter and caches nothing.
|
|
790
|
+
*/
|
|
791
|
+
recheck(target: Target, kind: TokenKind, name: string): Promise<string | undefined> | undefined;
|
|
792
|
+
/**
|
|
793
|
+
* The store's token of `name`, bypassing the cache; `create` writes one when the key is
|
|
794
|
+
* missing, else a missing (or empty) key is `undefined`. What it read is cached unless a bump
|
|
795
|
+
* completed during the read; a missing tag key then drops the cached token instead.
|
|
796
|
+
*/
|
|
797
|
+
private readFresh;
|
|
798
|
+
/** Writes a new token and caches it; on a failed write the cached token is unchanged. */
|
|
799
|
+
bump(target: Target, kind: TokenKind, name: string): Promise<void>;
|
|
800
|
+
/**
|
|
801
|
+
* The tokens of `names` (deduplicated, in first-occurrence order), `undefined` for a missing
|
|
802
|
+
* or empty key; never creates one. Cached tokens are served without a store call. A name with
|
|
803
|
+
* a plain read already in flight (from another `currentMany`) joins it; the others are read
|
|
804
|
+
* with one `getStrict` each, in parallel, when the store has it, else with one `getMany` (one
|
|
805
|
+
* `get` each without it). A token read is cached unless a bump or a fresh read completed
|
|
806
|
+
* meanwhile, and an older read-or-create still in flight then no longer updates the cache; a
|
|
807
|
+
* missing key is not cached, and for a tag it also drops the cached token. A `current` that
|
|
808
|
+
* caches a token also unregisters a plain read still in flight, so that read cannot undo it.
|
|
809
|
+
* Rejects when any store read rejects, for every waiter on it. The names served from the
|
|
810
|
+
* process cache (not read by this call nor joined to a read) are added to `fromCache`.
|
|
811
|
+
*/
|
|
812
|
+
currentMany(target: Target, kind: TokenKind, names: readonly string[], fromCache?: Set<string>): Promise<Map<string, string | undefined>>;
|
|
813
|
+
/**
|
|
814
|
+
* `current` for each of `names` (deduplicated), in parallel: missing tokens are created, and
|
|
815
|
+
* reads already in flight are shared. Rejects when any read or create rejects.
|
|
816
|
+
*/
|
|
817
|
+
ensureMany(target: Target, kind: TokenKind, names: readonly string[]): Promise<Map<string, string>>;
|
|
818
|
+
/**
|
|
819
|
+
* `bump` for each of `names` (deduplicated), in parallel. Every name is tried; then the call
|
|
820
|
+
* rejects with the first failing name's error. Successful bumps are cached either way.
|
|
821
|
+
*/
|
|
822
|
+
bumpMany(target: Target, kind: TokenKind, names: readonly string[]): Promise<void>;
|
|
823
|
+
/**
|
|
824
|
+
* Registers the plain read of `k` so concurrent `currentMany` calls join it. On success a token
|
|
825
|
+
* is cached while the read is still registered; `''` becomes `undefined`. A rejection is
|
|
826
|
+
* passed to every waiter and caches nothing.
|
|
827
|
+
*/
|
|
828
|
+
private shareRead;
|
|
829
|
+
/** Caches `token` as the most recently refreshed entry, evicting the oldest beyond the cap. */
|
|
830
|
+
private remember;
|
|
831
|
+
/** Reads the token key, creating it when missing; a concurrent creator's token wins. */
|
|
832
|
+
private read;
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
interface Target {
|
|
836
|
+
name: string;
|
|
837
|
+
store: CacheStore;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
/** The tag versions an entry was written with: each tag mapped to its token. */
|
|
841
|
+
type TagStamp = Readonly<Record<string, string>>;
|
|
842
|
+
/**
|
|
843
|
+
* The engine-level tags of a single write (D2). An array is known before the load, so its tokens
|
|
844
|
+
* are taken before the loader runs; a function gets the value once the write is decided.
|
|
845
|
+
*/
|
|
846
|
+
type TagOption<T> = readonly string[] | ((value: T) => readonly string[]);
|
|
847
|
+
/** The tags of a batch write (D2): an array for every entry, or a function of each entry. */
|
|
848
|
+
type BatchTagOption<T> = readonly string[] | ((value: T, key: string) => readonly string[]);
|
|
849
|
+
/**
|
|
850
|
+
* How a write is stamped: a stamp (empty means the untagged 0.6 envelope), or `'skip'` after a
|
|
851
|
+
* reported failure, and the entry is then not written.
|
|
852
|
+
*/
|
|
853
|
+
type Stamping = TagStamp | 'skip';
|
|
854
|
+
|
|
855
|
+
type Classification = 'fresh' | 'stale' | 'expired';
|
|
856
|
+
interface ExpiryStrategy {
|
|
857
|
+
readonly kind: 'fixed' | 'swr' | 'sliding';
|
|
858
|
+
/** The engine adds jitter to the ttl before calling `wrap` when true. */
|
|
859
|
+
readonly jittered: boolean;
|
|
860
|
+
/** Only receives non-null/undefined-or-nil values; `ttl` is an integer >= 1. */
|
|
861
|
+
wrap(value: unknown, now: number, ttl: number): {
|
|
862
|
+
envelope: CacheEnvelope;
|
|
863
|
+
storeTtl: number;
|
|
864
|
+
};
|
|
865
|
+
read(ttl: number): {
|
|
866
|
+
touch: false;
|
|
867
|
+
} | {
|
|
868
|
+
touch: true;
|
|
869
|
+
touchTtl: number;
|
|
870
|
+
};
|
|
871
|
+
classify(envelope: CacheEnvelope, now: number): Classification;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
/** The write policy a loaded or put value is checked against (`writePlan`). */
|
|
875
|
+
interface WritePolicy<T> {
|
|
876
|
+
ttl?: number;
|
|
877
|
+
cacheNull?: boolean;
|
|
878
|
+
nullTtl?: number;
|
|
879
|
+
unless?: (result: T) => boolean;
|
|
880
|
+
}
|
|
881
|
+
/** `tags` per D2: an array is known before the load, a function gets the value. */
|
|
882
|
+
type PutOptions<T> = WritePolicy<T> & {
|
|
883
|
+
tags?: TagOption<T>;
|
|
884
|
+
} & LoadStrategyOptions;
|
|
885
|
+
/** `PutOptions` of a batch load: a tag function also gets each entry's key (D2). */
|
|
886
|
+
type BatchPutOptions<T> = WritePolicy<T> & {
|
|
887
|
+
tags?: BatchTagOption<T>;
|
|
888
|
+
} & LoadStrategyOptions;
|
|
889
|
+
|
|
890
|
+
interface KeyRef {
|
|
891
|
+
store?: string;
|
|
892
|
+
namespace?: string;
|
|
893
|
+
key: string;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
/** The store and namespace a batch call works in. */
|
|
897
|
+
interface BatchScope {
|
|
898
|
+
store?: string;
|
|
899
|
+
namespace?: string;
|
|
900
|
+
}
|
|
901
|
+
type BatchLoader<T> = (missing: string[]) => Promise<ReadonlyMap<string, T>>;
|
|
902
|
+
|
|
903
|
+
/** `lock` overrides `defaults.lock.enabled`; it has no effect on a store without `lock`. */
|
|
904
|
+
type LoadOptions<T> = PutOptions<T> & {
|
|
905
|
+
lock?: boolean;
|
|
906
|
+
};
|
|
907
|
+
/** `getOrSetMany` options: batch tags (D2); `lock: true` is rejected. */
|
|
908
|
+
type BatchLoadOptions<T> = BatchPutOptions<T> & {
|
|
909
|
+
lock?: boolean;
|
|
910
|
+
};
|
|
911
|
+
type SetOptions<T = unknown> = {
|
|
912
|
+
ttl?: number;
|
|
913
|
+
tags?: TagOption<T>;
|
|
914
|
+
} & LoadStrategyOptions;
|
|
915
|
+
/** `setMany` options: a tag function also gets each entry's key (D2). */
|
|
916
|
+
type BatchSetOptions<T = unknown> = {
|
|
917
|
+
ttl?: number;
|
|
918
|
+
tags?: BatchTagOption<T>;
|
|
919
|
+
} & LoadStrategyOptions;
|
|
920
|
+
/** Public facade: validates each call, then delegates to the store I/O and load orchestration. */
|
|
921
|
+
declare class CacheEngine {
|
|
922
|
+
private readonly options;
|
|
923
|
+
private readonly tracing;
|
|
924
|
+
private readonly io;
|
|
925
|
+
private readonly load;
|
|
926
|
+
private readonly batch;
|
|
927
|
+
/** The module's `logging.level`. */
|
|
928
|
+
readonly logLevel: CacheLogLevel;
|
|
929
|
+
/** The module's `escapeKeyArgs`; decorators pass it to template key rendering at call time. */
|
|
930
|
+
readonly escapeKeyArgs: boolean;
|
|
931
|
+
/** Internal: the version tokens of namespaces and tags, one set per engine. */
|
|
932
|
+
readonly tokens: VersionTokens;
|
|
933
|
+
/**
|
|
934
|
+
* @param tracing Internal: the module's tracing; until a tracer is registered with it, every
|
|
935
|
+
* call runs untraced, as before 0.10.
|
|
936
|
+
*/
|
|
937
|
+
constructor(options: ResolvedCacheOptions, events: CacheEvents, tracing?: CacheTracing);
|
|
938
|
+
hasStore(name: string): boolean;
|
|
939
|
+
/** True when the store is configured and can lock; never throws for an unknown name. */
|
|
940
|
+
hasLock(name: string): boolean;
|
|
941
|
+
storeNames(): string[];
|
|
942
|
+
/** Never refreshes; `options` selects the read command and the classification only. */
|
|
943
|
+
get<T>(ref: KeyRef, options?: LoadStrategyOptions): Promise<T | undefined>;
|
|
944
|
+
private getImpl;
|
|
945
|
+
/**
|
|
946
|
+
* @param preset Internal: the strategy built from `options` at decoration time, so a
|
|
947
|
+
* decorated call does not rebuild it. It must come from `createStrategy(options)`.
|
|
948
|
+
*/
|
|
949
|
+
getOrSet<T>(ref: KeyRef, loader: () => Promise<T>, options?: LoadOptions<T>, preset?: ExpiryStrategy): Promise<T>;
|
|
950
|
+
private getOrSetImpl;
|
|
951
|
+
/** With `tags`, the entry is stamped with their tokens; an invalid list skips the write. */
|
|
952
|
+
set<T>(ref: KeyRef, value: T, options?: SetOptions<T>): Promise<void>;
|
|
953
|
+
private setImpl;
|
|
954
|
+
/**
|
|
955
|
+
* @param preset Internal: as for `getOrSet`.
|
|
956
|
+
* @param taken Internal: the stamp `takeTags` gave before the value was produced (T4-B); the
|
|
957
|
+
* write uses exactly those tokens and `options.tags` is not stamped again.
|
|
958
|
+
*/
|
|
959
|
+
put<T>(ref: KeyRef, value: T, options?: PutOptions<T>, preset?: ExpiryStrategy, taken?: Stamping): Promise<void>;
|
|
960
|
+
private putImpl;
|
|
961
|
+
/**
|
|
962
|
+
* Internal: takes the tokens of tags known before a value is produced (spec 3.3), for a later
|
|
963
|
+
* `put`, so an invalidation in between leaves that write stale. An invalid list is one `tag`
|
|
964
|
+
* error, a failed token write one `version` error; either gives `'skip'` and never rejects.
|
|
965
|
+
*/
|
|
966
|
+
takeTags(storeName: string | undefined, tags: readonly string[]): Promise<Stamping>;
|
|
967
|
+
/**
|
|
968
|
+
* `get` for several keys of one namespace: one store read for the batch (per key under
|
|
969
|
+
* `sliding`), results in input order. A duplicate is read once; an empty or reserved key is
|
|
970
|
+
* `undefined`.
|
|
971
|
+
*/
|
|
972
|
+
getMany<T>(scope: BatchScope, keys: readonly string[], options?: LoadStrategyOptions): Promise<(T | undefined)[]>;
|
|
973
|
+
private getManyImpl;
|
|
974
|
+
/**
|
|
975
|
+
* `set` for several entries, written with one store call. A repeated key is written once,
|
|
976
|
+
* with its last value; empty or reserved keys are dropped and reported once as a key error.
|
|
977
|
+
*/
|
|
978
|
+
setMany<T>(scope: BatchScope, entries: readonly (readonly [key: string, value: NoInfer<T>])[], options?: BatchSetOptions<T>): Promise<void>;
|
|
979
|
+
private setManyImpl;
|
|
980
|
+
/**
|
|
981
|
+
* `getOrSet` for several keys of one namespace. Hits (stale `swr` ones too) are served; the
|
|
982
|
+
* misses go to one `loader(missing)` call, except those another call is loading, which are
|
|
983
|
+
* awaited. A key the loader omits counts as `undefined`; keys it was not asked for are
|
|
984
|
+
* ignored. Stale `swr` keys are refreshed in the background with one more loader call.
|
|
985
|
+
* Results are in input order, duplicates included; an empty or reserved key is
|
|
986
|
+
* `undefined`. Never locks.
|
|
987
|
+
*/
|
|
988
|
+
getOrSetMany<T>(scope: BatchScope, keys: readonly string[], loader: BatchLoader<T>, options?: BatchLoadOptions<T>): Promise<(T | undefined)[]>;
|
|
989
|
+
private getOrSetManyImpl;
|
|
990
|
+
/** Empty keys are dropped and reported once as a key error; every other key is deleted. */
|
|
991
|
+
delete(scope: {
|
|
992
|
+
store?: string;
|
|
993
|
+
namespace?: string;
|
|
994
|
+
}, keys: readonly string[]): Promise<void>;
|
|
995
|
+
private deleteImpl;
|
|
996
|
+
clear(namespace: string, storeName?: string): Promise<void>;
|
|
997
|
+
private clearImpl;
|
|
998
|
+
/**
|
|
999
|
+
* Gives each tag a new version in the store (spec 3.4), so every entry stamped with one of them
|
|
1000
|
+
* becomes a miss; this instance sees it at once, others once their cached token expires. Rejects
|
|
1001
|
+
* `CacheConfigError` for an invalid list (empty, an empty or non-string tag, more than 32 after
|
|
1002
|
+
* de-duplication) or an unknown store. A failed token write is one `version` error, and the
|
|
1003
|
+
* call rejects with the first failing tag's error once every tag was tried.
|
|
1004
|
+
*/
|
|
1005
|
+
invalidateTags(tags: readonly string[], storeName?: string): Promise<void>;
|
|
1006
|
+
private invalidateTagsImpl;
|
|
1007
|
+
reportError(store: string | undefined, operation: CacheOperation, error: unknown): void;
|
|
1008
|
+
/** Names starting with `__` are reserved for internal keys (the lock keys). */
|
|
1009
|
+
private checkNamespace;
|
|
1010
|
+
/** A `getOrSet` that skips the cache: `cache.result = 'bypass'`, the loader in `cache.load`. */
|
|
1011
|
+
private bypass;
|
|
1012
|
+
/** Reports an empty or reserved key as a key error; the caller then skips the cache. */
|
|
1013
|
+
private invalidKey;
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
/** What a `key` callback receives about the request. */
|
|
1017
|
+
interface HttpCacheRequest {
|
|
1018
|
+
method: string;
|
|
1019
|
+
/** The raw request URL, as received (query unsorted, nothing escaped). */
|
|
1020
|
+
url: string;
|
|
1021
|
+
/**
|
|
1022
|
+
* The key used when `key` is not set: the path plus the query sorted by name then value, with
|
|
1023
|
+
* `%` and `:` percent-encoded. It varies on path and query only.
|
|
1024
|
+
*/
|
|
1025
|
+
defaultKey: string;
|
|
1026
|
+
path: string;
|
|
1027
|
+
query: Readonly<Record<string, string | readonly string[]>>;
|
|
1028
|
+
params: Readonly<Record<string, string>>;
|
|
1029
|
+
headers: Readonly<Record<string, string | readonly string[] | undefined>>;
|
|
1030
|
+
}
|
|
1031
|
+
/** Options of `@HttpCache`; the strategy options include `softTimeout` (a cached route loads). */
|
|
1032
|
+
type HttpCacheOptions = LoadStrategyOptions & {
|
|
1033
|
+
ttl?: number;
|
|
1034
|
+
/** Defaults to 'http'. */
|
|
1035
|
+
namespace?: string;
|
|
1036
|
+
store?: string;
|
|
1037
|
+
lock?: boolean;
|
|
1038
|
+
cacheNull?: boolean;
|
|
1039
|
+
nullTtl?: number;
|
|
1040
|
+
/**
|
|
1041
|
+
* A string is a fixed key, not a template: a non-empty string without `{` or `}`, and only on a
|
|
1042
|
+
* method (a class-level string throws `CacheConfigError` at decoration). A callback derives the
|
|
1043
|
+
* key per request; `undefined` skips caching that request.
|
|
1044
|
+
*/
|
|
1045
|
+
key?: string | ((req: HttpCacheRequest) => string | undefined);
|
|
1046
|
+
/** Returns `true` to keep the body out of the cache. */
|
|
1047
|
+
unless?: (body: unknown) => boolean;
|
|
1048
|
+
/**
|
|
1049
|
+
* Tags the cached body (spec 2.1): fixed strings (not templates), or a callback of the body
|
|
1050
|
+
* and the request, called once the body is to be written.
|
|
1051
|
+
*/
|
|
1052
|
+
tags?: readonly string[] | HttpCacheTags;
|
|
1053
|
+
};
|
|
1054
|
+
/** An `@HttpCache` tags callback. */
|
|
1055
|
+
type HttpCacheTags = (body: unknown, req: HttpCacheRequest) => readonly string[];
|
|
1056
|
+
/** Caches the HTTP response body of a route (method) or of every route of a controller (class). */
|
|
1057
|
+
declare function HttpCache(options?: HttpCacheOptions): MethodDecorator & ClassDecorator;
|
|
1058
|
+
|
|
1059
|
+
/**
|
|
1060
|
+
* Caches GET/HEAD response bodies of routes marked with `@HttpCache`; other requests pass through.
|
|
1061
|
+
*
|
|
1062
|
+
* Created by Nest; inject it, do not construct it. Constructor parameters are not part of the
|
|
1063
|
+
* public API.
|
|
1064
|
+
*/
|
|
1065
|
+
declare class HttpCacheInterceptor implements NestInterceptor {
|
|
1066
|
+
private readonly engine;
|
|
1067
|
+
private readonly reflector;
|
|
1068
|
+
private readonly adapterHost;
|
|
1069
|
+
constructor(engine: CacheEngine, reflector: Reflector, adapterHost: HttpAdapterHost);
|
|
1070
|
+
intercept(context: ExecutionContext, next: CallHandler): Observable<unknown>;
|
|
1071
|
+
/** The cache key per spec 3.2; `undefined` skips the cache, a throw is a key error. */
|
|
1072
|
+
private keyOf;
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
/** Options of `compressedSerializer`. */
|
|
1076
|
+
interface CompressedSerializerOptions {
|
|
1077
|
+
/** Produces and reads the string that gets compressed. Default `jsonSerializer`. */
|
|
1078
|
+
inner?: Serializer;
|
|
1079
|
+
/** Algorithm used for writes; reads follow the prefix of the stored value. Default `'gzip'`. */
|
|
1080
|
+
algorithm?: 'gzip' | 'brotli';
|
|
1081
|
+
/**
|
|
1082
|
+
* Compression level: 0-9 for gzip (default 6, zlib's default) and 0-11 for brotli (default 4).
|
|
1083
|
+
* Compression runs synchronously on the event loop. Brotli's own default, 11, is much slower:
|
|
1084
|
+
* about 1.6 s for a 724 KB JSON value, against about 2 ms at 4. Reads accept any level.
|
|
1085
|
+
*/
|
|
1086
|
+
level?: number;
|
|
1087
|
+
/** UTF-8 byte length of the inner string above which compression is tried. Default 1024. */
|
|
1088
|
+
threshold?: number;
|
|
1089
|
+
/**
|
|
1090
|
+
* Upper bound of a decompressed payload, in bytes. Default 16 MiB. Larger payloads are written
|
|
1091
|
+
* uncompressed so they stay readable.
|
|
1092
|
+
*/
|
|
1093
|
+
maxDecompressedBytes?: number;
|
|
1094
|
+
}
|
|
1095
|
+
/**
|
|
1096
|
+
* Wraps a serializer with gzip or brotli compression of large payloads. A compressed value is
|
|
1097
|
+
* `"\u0000nc1:gz:"` or `"\u0000nc1:br:"` plus base64; anything else is read by `inner`.
|
|
1098
|
+
* `inner` must not produce strings starting with `"\u0000nc1:"`.
|
|
1099
|
+
*/
|
|
1100
|
+
declare function compressedSerializer(options?: CompressedSerializerOptions): Serializer;
|
|
1101
|
+
|
|
1102
|
+
/** Options of `memoryStore`. */
|
|
1103
|
+
interface MemoryStoreOptions {
|
|
1104
|
+
/** Entries kept before the least recently used one is evicted; an integer >= 1. Default 1 000. */
|
|
1105
|
+
maxEntries?: number;
|
|
1106
|
+
}
|
|
1107
|
+
/**
|
|
1108
|
+
* In-process LRU store on Map insertion order. Expiry is lazy; no timers.
|
|
1109
|
+
*
|
|
1110
|
+
* The version tokens of namespaces and tags live in a second LRU with the same `maxEntries`, so
|
|
1111
|
+
* data writes never evict them. An evicted token would be re-created with a new value, and every
|
|
1112
|
+
* entry of its namespace or tag would then read as a miss.
|
|
1113
|
+
*/
|
|
1114
|
+
declare class MemoryStore implements CacheStore {
|
|
1115
|
+
private readonly data;
|
|
1116
|
+
private readonly tokens;
|
|
1117
|
+
private reservedPrefixes;
|
|
1118
|
+
constructor(options?: MemoryStoreOptions);
|
|
1119
|
+
/** The data entries in LRU order, oldest first. */
|
|
1120
|
+
private get entries();
|
|
1121
|
+
private partitionOf;
|
|
1122
|
+
ping(): Promise<void>;
|
|
1123
|
+
get(key: string): Promise<string | undefined>;
|
|
1124
|
+
/** Reads the entry and resets its TTL to `ttlMs`; a live hit also becomes most recently used. */
|
|
1125
|
+
getAndTouch(key: string, ttlMs: number): Promise<string | undefined>;
|
|
1126
|
+
set(key: string, value: string, ttlMs: number): Promise<void>;
|
|
1127
|
+
getMany(keys: readonly string[]): Promise<(string | undefined)[]>;
|
|
1128
|
+
/** Writes every entry in one synchronous step, so no other task can interleave between them. */
|
|
1129
|
+
setMany(entries: readonly {
|
|
1130
|
+
key: string;
|
|
1131
|
+
value: string;
|
|
1132
|
+
ttlMs: number;
|
|
1133
|
+
}[]): Promise<void>;
|
|
1134
|
+
delete(keys: readonly string[]): Promise<void>;
|
|
1135
|
+
clear(prefix: string): Promise<void>;
|
|
1136
|
+
}
|
|
1137
|
+
/** An in-process LRU store; the default store when `CacheModule` gets no `stores`. */
|
|
1138
|
+
declare function memoryStore(options?: MemoryStoreOptions): MemoryStore;
|
|
1139
|
+
|
|
1140
|
+
/** Terminus-compatible result for one indicator key. */
|
|
1141
|
+
type CacheHealthResult = {
|
|
1142
|
+
status: 'up';
|
|
1143
|
+
ping?: 'unsupported';
|
|
1144
|
+
} | {
|
|
1145
|
+
status: 'down';
|
|
1146
|
+
message: string;
|
|
1147
|
+
};
|
|
1148
|
+
/**
|
|
1149
|
+
* Probes a configured store with `ping()` and returns a result in the shape `@nestjs/terminus`
|
|
1150
|
+
* expects, without importing it. `check` never rejects except with `CacheConfigError` for an
|
|
1151
|
+
* unknown store or an invalid timeout; a failing store is reported as `down`.
|
|
1152
|
+
*/
|
|
1153
|
+
declare class CacheHealthIndicator {
|
|
1154
|
+
private readonly options;
|
|
1155
|
+
/** Created by `CacheModule`; do not construct it, inject it. */
|
|
1156
|
+
constructor(options: ResolvedCacheOptions);
|
|
1157
|
+
check<K extends string>(key: K, options?: {
|
|
1158
|
+
store?: string;
|
|
1159
|
+
timeout?: number;
|
|
1160
|
+
}): Promise<Record<K, CacheHealthResult>>;
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
/**
|
|
1164
|
+
* The cache module: provides `CacheService`, `CacheEvents` and `CacheHealthIndicator`, and
|
|
1165
|
+
* wires the cache decorators of every provider. Register it once, usually with `isGlobal`.
|
|
1166
|
+
*/
|
|
1167
|
+
declare class CacheModule {
|
|
1168
|
+
/** Registers the module with options known up front. Invalid options throw `CacheConfigError`. */
|
|
1169
|
+
static forRoot(options?: CacheModuleOptions & {
|
|
1170
|
+
isGlobal?: boolean;
|
|
1171
|
+
}): DynamicModule;
|
|
1172
|
+
/** Registers the module with options built by `useFactory`, which can inject providers. */
|
|
1173
|
+
static forRootAsync(options: CacheModuleAsyncOptions): DynamicModule;
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
/** Where a key lives: its `namespace` (default none) and `store` name (default `'default'`). */
|
|
1177
|
+
interface KeyOptions {
|
|
1178
|
+
namespace?: string;
|
|
1179
|
+
store?: string;
|
|
1180
|
+
}
|
|
1181
|
+
/**
|
|
1182
|
+
* `tags`: fixed tag strings (not templates), or a function of the value. The entry is stamped
|
|
1183
|
+
* with each tag's version, so `invalidateTags` turns it into a miss. On `getOrSet` an array's
|
|
1184
|
+
* versions are taken before the loader runs; a function runs after it, and only when the entry
|
|
1185
|
+
* is written, so an invalidation during that load can be missed until the entry expires. An
|
|
1186
|
+
* invalid list (an empty tag, more than 32 tags, a throwing function) is an `error` event with
|
|
1187
|
+
* operation `'tag'`: the entry is not written and the call still resolves.
|
|
1188
|
+
*/
|
|
1189
|
+
type WriteOptions<T = unknown> = KeyOptions & Writes<T> & StrategyOptions;
|
|
1190
|
+
/** The options of the batch writes: a tag function also gets each entry's key. */
|
|
1191
|
+
type WriteManyOptions<T = unknown> = KeyOptions & WritesMany<T> & StrategyOptions;
|
|
1192
|
+
/** `ttl` and `tags` of a single-key write; see `WriteOptions`. */
|
|
1193
|
+
interface Writes<T> {
|
|
1194
|
+
ttl?: number;
|
|
1195
|
+
tags?: readonly string[] | ((value: T) => readonly string[]);
|
|
1196
|
+
}
|
|
1197
|
+
/** `ttl` and `tags` of a batch write; see `WriteManyOptions`. */
|
|
1198
|
+
interface WritesMany<T> {
|
|
1199
|
+
ttl?: number;
|
|
1200
|
+
tags?: readonly string[] | ((value: T, key: string) => readonly string[]);
|
|
1201
|
+
}
|
|
1202
|
+
/** The load options; `L` narrows `lock` (`false` for `getOrSetMany`, which never locks). */
|
|
1203
|
+
interface LoadPolicy<T, L extends boolean = boolean> {
|
|
1204
|
+
cacheNull?: boolean;
|
|
1205
|
+
nullTtl?: number;
|
|
1206
|
+
unless?: (result: T) => boolean;
|
|
1207
|
+
lock?: L;
|
|
1208
|
+
}
|
|
1209
|
+
/**
|
|
1210
|
+
* `getOrSet` options: the `WriteOptions` fields with `LoadStrategyOptions` (so `softTimeout` is
|
|
1211
|
+
* accepted), plus the load policy. It is not built on `WriteOptions`, whose
|
|
1212
|
+
* `softTimeout?: never` would make the intersection reject `softTimeout`.
|
|
1213
|
+
*/
|
|
1214
|
+
type GetOrSetOptions<T> = KeyOptions & Writes<T> & LoadStrategyOptions & LoadPolicy<T>;
|
|
1215
|
+
/**
|
|
1216
|
+
* `getOrSetMany` options. `lock` accepts only `false`: a batch never locks, and `lock: true`
|
|
1217
|
+
* from JavaScript rejects with `CacheConfigError`.
|
|
1218
|
+
*/
|
|
1219
|
+
type GetOrSetManyOptions<T> = KeyOptions & WritesMany<T> & LoadStrategyOptions & LoadPolicy<T, false>;
|
|
1220
|
+
/**
|
|
1221
|
+
* The programmatic cache API, injected from `CacheModule`. Cache failures (store, serializer,
|
|
1222
|
+
* key, lock) are reported as `error` events and do not reject a call, with one exception:
|
|
1223
|
+
* `invalidateTags` rejects with the store's error when a tag version write fails, so the caller
|
|
1224
|
+
* knows the invalidation did not happen. Invalid arguments reject with `CacheConfigError`.
|
|
1225
|
+
*/
|
|
1226
|
+
declare class CacheService {
|
|
1227
|
+
private readonly engine;
|
|
1228
|
+
/** Created by `CacheModule`; do not construct it, inject it. */
|
|
1229
|
+
constructor(engine: CacheEngine);
|
|
1230
|
+
/**
|
|
1231
|
+
* Reads a value; returns `undefined` on a miss.
|
|
1232
|
+
*
|
|
1233
|
+
* Strategy options pick the read command (`sliding` touches the entry) and how the entry is
|
|
1234
|
+
* classified; a stale `swr` entry is returned as a hit with `stale: true`. `get` never refreshes.
|
|
1235
|
+
*
|
|
1236
|
+
* With `strategy: 'sliding'` the entry's window is reset to `defaults.ttl`, not to the `ttl` it
|
|
1237
|
+
* was written with, because `getAndTouch` needs the TTL before the entry is read.
|
|
1238
|
+
*/
|
|
1239
|
+
get<T>(key: string, options?: KeyOptions & StrategyOptions): Promise<T | undefined>;
|
|
1240
|
+
/**
|
|
1241
|
+
* Writes a value with `options.ttl` (else `defaults.ttl`). An empty value (`null` or
|
|
1242
|
+
* `undefined`) is written as is, under the `fixed` strategy.
|
|
1243
|
+
*/
|
|
1244
|
+
set<T>(key: string, value: T, options?: WriteOptions<T>): Promise<void>;
|
|
1245
|
+
/** Deletes one key or several keys of one namespace and store, with one store call. */
|
|
1246
|
+
delete(key: string | readonly string[], options?: KeyOptions): Promise<void>;
|
|
1247
|
+
/**
|
|
1248
|
+
* Deletes every entry of `namespace` in the store (`options.store`, else `default`): the
|
|
1249
|
+
* store's `clear` of its key prefix, or one version token change for a versioned namespace.
|
|
1250
|
+
* Rejects `CacheConfigError` for `''`.
|
|
1251
|
+
*/
|
|
1252
|
+
clear(namespace: string, options?: {
|
|
1253
|
+
store?: string;
|
|
1254
|
+
}): Promise<void>;
|
|
1255
|
+
/**
|
|
1256
|
+
* Returns the cached value, or runs `loader` once per key across concurrent callers (and, with
|
|
1257
|
+
* `lock`, across instances), stores its result and returns it. A loader error rejects the
|
|
1258
|
+
* call; nothing is stored. Under `swr` a stale value is served while one refresh runs.
|
|
1259
|
+
*/
|
|
1260
|
+
getOrSet<T>(key: string, loader: () => Promise<T>, options?: GetOrSetOptions<T>): Promise<T>;
|
|
1261
|
+
/**
|
|
1262
|
+
* Invalidates every entry stamped with one of `tags` in the store (`options.store`, else
|
|
1263
|
+
* `default`), across namespaces: each tag gets a new version, so those entries read as misses.
|
|
1264
|
+
* This instance sees it at once; other instances once their cached version expires
|
|
1265
|
+
* (`versioning.cacheTtl`). Tags are plain strings, used as is.
|
|
1266
|
+
*
|
|
1267
|
+
* Rejects with `CacheConfigError` when `tags` is not a non-empty array of non-empty strings,
|
|
1268
|
+
* has more than 32 tags after de-duplication, or the store is unknown. When a version write
|
|
1269
|
+
* fails, every tag is still tried; an `error` event with operation `'version'` is emitted and
|
|
1270
|
+
* the call rejects with the first failure.
|
|
1271
|
+
*/
|
|
1272
|
+
invalidateTags(tags: readonly string[], options?: {
|
|
1273
|
+
store?: string;
|
|
1274
|
+
}): Promise<void>;
|
|
1275
|
+
/**
|
|
1276
|
+
* Reads several keys of one namespace and store; results follow `keys`, `undefined` for a
|
|
1277
|
+
* miss. One store read for the batch (MGET on Redis), except with `strategy: 'sliding'`,
|
|
1278
|
+
* which touches each entry with its own `getAndTouch`.
|
|
1279
|
+
*/
|
|
1280
|
+
getMany<T>(keys: readonly string[], options?: KeyOptions & StrategyOptions): Promise<(T | undefined)[]>;
|
|
1281
|
+
/** Writes several entries, each as `set` would, with one store call when the store allows. */
|
|
1282
|
+
setMany<T>(entries: readonly (readonly [key: string, value: T])[], options?: WriteManyOptions<T>): Promise<void>;
|
|
1283
|
+
/**
|
|
1284
|
+
* `getOrSet` for several keys: hits are served, and the misses are loaded with one
|
|
1285
|
+
* `loader(missing)` call that resolves a Map. A key the loader omits is treated as
|
|
1286
|
+
* `undefined`; keys it was not asked for are ignored. `lock: true` is not supported.
|
|
1287
|
+
*/
|
|
1288
|
+
getOrSetMany<T>(keys: readonly string[], loader: (missing: string[]) => Promise<ReadonlyMap<string, T>>, options?: GetOrSetManyOptions<T>): Promise<(T | undefined)[]>;
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
/**
|
|
1292
|
+
* Minimal Redis surface the cache needs; implemented over ioredis by `ioredisAdapter` and over
|
|
1293
|
+
* node-redis by `nodeRedisAdapter`.
|
|
1294
|
+
*
|
|
1295
|
+
* Implemented by you. In 1.x, members are only added as optional, and the library checks that
|
|
1296
|
+
* they exist before calling them.
|
|
1297
|
+
*
|
|
1298
|
+
* `redisStore` tells an adapter from an ioredis client by checking that `createSubscriber` is a
|
|
1299
|
+
* function.
|
|
1300
|
+
*/
|
|
1301
|
+
interface RedisClientAdapter {
|
|
1302
|
+
get(key: string): Promise<string | undefined>;
|
|
1303
|
+
/** SET key value PX ttlMs */
|
|
1304
|
+
set(key: string, value: string, ttlMs: number): Promise<void>;
|
|
1305
|
+
/** GETEX key PX ttlMs */
|
|
1306
|
+
getex(key: string, ttlMs: number): Promise<string | undefined>;
|
|
1307
|
+
/**
|
|
1308
|
+
* An empty list sends no command. The keys may belong to several hash slots; a Cluster adapter
|
|
1309
|
+
* must split the command per slot.
|
|
1310
|
+
*/
|
|
1311
|
+
unlink(keys: readonly string[]): Promise<void>;
|
|
1312
|
+
scan(cursor: string, match: string, count: number): Promise<{
|
|
1313
|
+
cursor: string;
|
|
1314
|
+
keys: string[];
|
|
1315
|
+
}>;
|
|
1316
|
+
/**
|
|
1317
|
+
* Optional. SET key value PX ttlMs NX. Resolves `true` when the key was set, `false` when it
|
|
1318
|
+
* already existed.
|
|
1319
|
+
*/
|
|
1320
|
+
setIfAbsent?(key: string, value: string, ttlMs: number): Promise<boolean>;
|
|
1321
|
+
/**
|
|
1322
|
+
* Optional. Deletes `key` only if it holds `value`, atomically. Resolves `true` when it
|
|
1323
|
+
* deleted the key.
|
|
1324
|
+
*/
|
|
1325
|
+
deleteIfEquals?(key: string, value: string): Promise<boolean>;
|
|
1326
|
+
/** Optional. Sends a PING; resolves when Redis answers, rejects otherwise. */
|
|
1327
|
+
ping?(): Promise<void>;
|
|
1328
|
+
/**
|
|
1329
|
+
* Optional. MGET; resolves the values in key order, `undefined` for a missing key. An empty
|
|
1330
|
+
* list sends no command and resolves `[]`. The keys may belong to several hash slots; a
|
|
1331
|
+
* Cluster adapter must split the command per slot.
|
|
1332
|
+
*/
|
|
1333
|
+
mget?(keys: readonly string[]): Promise<(string | undefined)[]>;
|
|
1334
|
+
/**
|
|
1335
|
+
* Optional. Every key matching `match`, in pages, across every node that holds data (each master
|
|
1336
|
+
* of a cluster). When present, `RedisStore.clear` uses it instead of the `scan` cursor loop.
|
|
1337
|
+
*/
|
|
1338
|
+
scanIterator?(match: string, count: number): AsyncIterable<string[]>;
|
|
1339
|
+
publish(channel: string, message: string): Promise<void>;
|
|
1340
|
+
createSubscriber(): RedisSubscriberAdapter;
|
|
1341
|
+
}
|
|
1342
|
+
/**
|
|
1343
|
+
* The subscriber connection of a `RedisClientAdapter`, used by the invalidation bus.
|
|
1344
|
+
*
|
|
1345
|
+
* Implemented by you. In 1.x, members are only added as optional, and the library checks that
|
|
1346
|
+
* they exist before calling them.
|
|
1347
|
+
*/
|
|
1348
|
+
interface RedisSubscriberAdapter {
|
|
1349
|
+
/**
|
|
1350
|
+
* Subscribes to `channel`. If it rejects (for example Redis was unreachable), the adapter
|
|
1351
|
+
* should subscribe again once the connection is ready, and a later call retries too.
|
|
1352
|
+
*/
|
|
1353
|
+
subscribe(channel: string, onMessage: (message: string) => void): Promise<void>;
|
|
1354
|
+
/**
|
|
1355
|
+
* Fires on every 'ready' after the first (the first is the initial connect), and when a
|
|
1356
|
+
* subscription that had failed is established later: messages may have been missed meanwhile.
|
|
1357
|
+
*/
|
|
1358
|
+
onReconnect(handler: () => void): void;
|
|
1359
|
+
/**
|
|
1360
|
+
* Optional. Registers a handler for errors of the dedicated connection (connection errors,
|
|
1361
|
+
* failed re-subscribes). Handlers must not throw.
|
|
1362
|
+
*/
|
|
1363
|
+
onError?(handler: (error: unknown) => void): void;
|
|
1364
|
+
/** Quits the dedicated connection; calling it again is a no-op. Never rejects. */
|
|
1365
|
+
close(): Promise<void>;
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
/**
|
|
1369
|
+
* Structural subset of an ioredis client (v5 and v6). Declared by hand so the
|
|
1370
|
+
* library never imports ioredis.
|
|
1371
|
+
*
|
|
1372
|
+
* Satisfied by the client you pass in. In 1.x, members are only added as optional, and the
|
|
1373
|
+
* library checks that they exist before calling them.
|
|
1374
|
+
*/
|
|
1375
|
+
interface IoredisLike {
|
|
1376
|
+
get(key: string): Promise<string | null>;
|
|
1377
|
+
set(key: string, value: string, mode: 'PX', ttlMs: number): Promise<unknown>;
|
|
1378
|
+
set(key: string, value: string, mode: 'PX', ttlMs: number, nx: 'NX'): Promise<'OK' | null>;
|
|
1379
|
+
eval(script: string, numKeys: number, ...args: string[]): Promise<unknown>;
|
|
1380
|
+
getex(key: string, mode: 'PX', ttlMs: number): Promise<string | null>;
|
|
1381
|
+
unlink(...keys: string[]): Promise<unknown>;
|
|
1382
|
+
scan(cursor: string, matchToken: 'MATCH', pattern: string, countToken: 'COUNT', count: number): Promise<[cursor: string, keys: string[]]>;
|
|
1383
|
+
publish(channel: string, message: string): Promise<unknown>;
|
|
1384
|
+
/** Optional. Used by health checks; the adapter exposes `ping` only when it exists. */
|
|
1385
|
+
ping?(): Promise<unknown>;
|
|
1386
|
+
/** Optional. Used by batch reads; the adapter exposes `mget` only when it exists. */
|
|
1387
|
+
mget?(...keys: string[]): Promise<(string | null)[]>;
|
|
1388
|
+
duplicate(): IoredisLike;
|
|
1389
|
+
subscribe(...channels: string[]): Promise<unknown>;
|
|
1390
|
+
on(event: string, listener: (...args: never[]) => void): unknown;
|
|
1391
|
+
quit(): Promise<unknown>;
|
|
1392
|
+
/** Optional. Closes the connection at once; used when `quit` does not settle in time. */
|
|
1393
|
+
disconnect?(): void;
|
|
1394
|
+
}
|
|
1395
|
+
/** The data commands a Cluster shares with a single-node client. */
|
|
1396
|
+
type IoredisCommands = Omit<IoredisLike, 'duplicate' | 'on'>;
|
|
1397
|
+
/**
|
|
1398
|
+
* Structural subset of an ioredis `Cluster` (ioredis 5.6.0 or later, for sharded pub/sub).
|
|
1399
|
+
* Declared by hand so the library never imports ioredis. `ioredisAdapter` runs in Cluster mode
|
|
1400
|
+
* when `isCluster` is `true`.
|
|
1401
|
+
*
|
|
1402
|
+
* Satisfied by the client you pass in. In 1.x, members are only added as optional, and the
|
|
1403
|
+
* library checks that they exist before calling them.
|
|
1404
|
+
*/
|
|
1405
|
+
interface IoredisClusterLike extends IoredisCommands {
|
|
1406
|
+
readonly isCluster: boolean;
|
|
1407
|
+
/** The master nodes; `scanIterator` scans each of them. */
|
|
1408
|
+
nodes(role: 'master'): IoredisLike[];
|
|
1409
|
+
spublish(channel: string, message: string): Promise<unknown>;
|
|
1410
|
+
ssubscribe(...channels: string[]): Promise<unknown>;
|
|
1411
|
+
on(event: string, listener: (...args: any[]) => void): unknown;
|
|
1412
|
+
/** The adapter's subscriber is `duplicate([], { shardedSubscribers: true })`. */
|
|
1413
|
+
duplicate(startupNodes?: unknown[], options?: {
|
|
1414
|
+
shardedSubscribers?: boolean;
|
|
1415
|
+
}): IoredisClusterLike;
|
|
1416
|
+
}
|
|
1417
|
+
/**
|
|
1418
|
+
* Adapts an ioredis client or Cluster to `RedisClientAdapter`. `redisStore` does this itself;
|
|
1419
|
+
* call it to wrap or decorate the adapter.
|
|
1420
|
+
*/
|
|
1421
|
+
declare function ioredisAdapter(client: IoredisLike | IoredisClusterLike): RedisClientAdapter;
|
|
1422
|
+
|
|
1423
|
+
/** Options of `redisInvalidationBus`. */
|
|
1424
|
+
interface RedisInvalidationBusOptions {
|
|
1425
|
+
/** An ioredis client or Cluster, or a `RedisClientAdapter` (e.g. `nodeRedisAdapter(client)`). */
|
|
1426
|
+
client: IoredisLike | IoredisClusterLike | RedisClientAdapter;
|
|
1427
|
+
/** The pub/sub channel of invalidation messages. Defaults to 'nestjs-cache:invalidate'. */
|
|
1428
|
+
channel?: string;
|
|
1429
|
+
}
|
|
1430
|
+
/**
|
|
1431
|
+
* The Redis pub/sub `InvalidationBus` a `RedisStore` uses, on its own: for a custom store, or a
|
|
1432
|
+
* `tieredStore` whose L2 is not Redis. Its subscriber is created on the first `subscribe`.
|
|
1433
|
+
*/
|
|
1434
|
+
declare function redisInvalidationBus(options: RedisInvalidationBusOptions): InvalidationBus;
|
|
1435
|
+
|
|
1436
|
+
/**
|
|
1437
|
+
* Options of `redisStore`: the client and the invalidation channel, the same fields as
|
|
1438
|
+
* `RedisInvalidationBusOptions`.
|
|
1439
|
+
*/
|
|
1440
|
+
interface RedisStoreOptions extends RedisInvalidationBusOptions {
|
|
1441
|
+
}
|
|
1442
|
+
/**
|
|
1443
|
+
* A Redis store over an ioredis client or Cluster, or any `RedisClientAdapter` (node-redis via
|
|
1444
|
+
* `nodeRedisAdapter`). It brings a pub/sub invalidation bus on `channel`, and a lock when the
|
|
1445
|
+
* adapter can `setIfAbsent` and `deleteIfEquals`. The caller's client is never closed.
|
|
1446
|
+
*/
|
|
1447
|
+
declare class RedisStore implements CacheStore {
|
|
1448
|
+
readonly invalidation: InvalidationBus;
|
|
1449
|
+
/** Present only when the adapter implements `setIfAbsent` and `deleteIfEquals`. */
|
|
1450
|
+
readonly lock?: LockProvider;
|
|
1451
|
+
/** Present only when the adapter implements `ping`. */
|
|
1452
|
+
readonly ping?: () => Promise<void>;
|
|
1453
|
+
private readonly adapter;
|
|
1454
|
+
constructor(options: RedisStoreOptions);
|
|
1455
|
+
get(key: string): Promise<string | undefined>;
|
|
1456
|
+
set(key: string, value: string, ttlMs: number): Promise<void>;
|
|
1457
|
+
getMany(keys: readonly string[]): Promise<(string | undefined)[]>;
|
|
1458
|
+
setMany(entries: readonly {
|
|
1459
|
+
key: string;
|
|
1460
|
+
value: string;
|
|
1461
|
+
ttlMs: number;
|
|
1462
|
+
}[]): Promise<void>;
|
|
1463
|
+
delete(keys: readonly string[]): Promise<void>;
|
|
1464
|
+
clear(prefix: string): Promise<void>;
|
|
1465
|
+
getAndTouch(key: string, ttlMs: number): Promise<string | undefined>;
|
|
1466
|
+
/** Closes the bus's subscriber connection; the caller's client is left open. */
|
|
1467
|
+
close(): Promise<void>;
|
|
1468
|
+
}
|
|
1469
|
+
/** Builds a `RedisStore`; requires Redis 6.2 or later (`GETEX`). */
|
|
1470
|
+
declare function redisStore(options: RedisStoreOptions): RedisStore;
|
|
1471
|
+
|
|
1472
|
+
/** node-redis's pub/sub listener: it receives the message first, then the channel. */
|
|
1473
|
+
type PubSubListener = (message: string, channel: string) => void;
|
|
1474
|
+
/**
|
|
1475
|
+
* Structural subset of a node-redis v5 or v6 client (`createClient()` from `redis`). Declared
|
|
1476
|
+
* by hand so the library never imports `redis`. The client must be connected before it is
|
|
1477
|
+
* passed to `nodeRedisAdapter`; the library never connects it.
|
|
1478
|
+
*
|
|
1479
|
+
* Satisfied by the client you pass in. In 1.x, members are only added as optional, and the
|
|
1480
|
+
* library checks that they exist before calling them.
|
|
1481
|
+
*/
|
|
1482
|
+
interface NodeRedisLike {
|
|
1483
|
+
get(key: string): Promise<string | null>;
|
|
1484
|
+
set(key: string, value: string, options: {
|
|
1485
|
+
expiration: {
|
|
1486
|
+
type: 'PX';
|
|
1487
|
+
value: number;
|
|
1488
|
+
};
|
|
1489
|
+
condition?: 'NX';
|
|
1490
|
+
}): Promise<string | null>;
|
|
1491
|
+
getEx(key: string, options: {
|
|
1492
|
+
type: 'PX';
|
|
1493
|
+
value: number;
|
|
1494
|
+
}): Promise<string | null>;
|
|
1495
|
+
eval(script: string, options: {
|
|
1496
|
+
keys: string[];
|
|
1497
|
+
arguments: string[];
|
|
1498
|
+
}): Promise<unknown>;
|
|
1499
|
+
unlink(keys: string[]): Promise<unknown>;
|
|
1500
|
+
mGet(keys: string[]): Promise<(string | null)[]>;
|
|
1501
|
+
/** Optional. Used by health checks; the adapter exposes `ping` only when it exists. */
|
|
1502
|
+
ping?(): Promise<unknown>;
|
|
1503
|
+
scan(cursor: string, options: {
|
|
1504
|
+
MATCH: string;
|
|
1505
|
+
COUNT: number;
|
|
1506
|
+
}): Promise<{
|
|
1507
|
+
cursor: string;
|
|
1508
|
+
keys: string[];
|
|
1509
|
+
}>;
|
|
1510
|
+
publish(channel: string, message: string): Promise<unknown>;
|
|
1511
|
+
/** The subscriber's dedicated connection: a new, unconnected client. */
|
|
1512
|
+
duplicate(): NodeRedisLike;
|
|
1513
|
+
connect(): Promise<unknown>;
|
|
1514
|
+
subscribe(channel: string, listener: PubSubListener): Promise<unknown>;
|
|
1515
|
+
close(): Promise<unknown>;
|
|
1516
|
+
destroy(): void;
|
|
1517
|
+
on(event: string, listener: (...args: any[]) => void): unknown;
|
|
1518
|
+
}
|
|
1519
|
+
/**
|
|
1520
|
+
* Structural subset of a node-redis v5 or v6 cluster (`createCluster()` from `redis`). Declared
|
|
1521
|
+
* by hand so the library never imports `redis`. `nodeRedisAdapter` runs in cluster mode when the
|
|
1522
|
+
* client has `masters`. Like a single client, it must be connected before it is passed in.
|
|
1523
|
+
*
|
|
1524
|
+
* Satisfied by the client you pass in. In 1.x, members are only added as optional, and the
|
|
1525
|
+
* library checks that they exist before calling them.
|
|
1526
|
+
*/
|
|
1527
|
+
interface NodeRedisClusterLike extends Omit<NodeRedisLike, 'scan' | 'duplicate'> {
|
|
1528
|
+
/** The master nodes, passed back to `nodeClient`; `scanIterator` scans each of them. */
|
|
1529
|
+
readonly masters: readonly unknown[];
|
|
1530
|
+
/** The client of one master node. */
|
|
1531
|
+
nodeClient(master: unknown): Promise<Pick<NodeRedisLike, 'scan'>>;
|
|
1532
|
+
sPublish(channel: string, message: string): Promise<unknown>;
|
|
1533
|
+
sSubscribe(channel: string, listener: PubSubListener): Promise<unknown>;
|
|
1534
|
+
/** The subscriber's dedicated connection: a new, unconnected cluster. */
|
|
1535
|
+
duplicate(): NodeRedisClusterLike;
|
|
1536
|
+
}
|
|
1537
|
+
/**
|
|
1538
|
+
* Structural subset of a node-redis v5 or v6 Sentinel client (`createSentinel()` from `redis`).
|
|
1539
|
+
* Declared by hand so the library never imports `redis`. `nodeRedisAdapter` runs in Sentinel
|
|
1540
|
+
* mode when `getSentinelNode` is a function. Data commands go to the sentinel, which sends them
|
|
1541
|
+
* to the current master. It has no `duplicate`: the subscriber subscribes on the sentinel
|
|
1542
|
+
* itself, whose pub/sub connection follows the master, and closing the subscriber only
|
|
1543
|
+
* unsubscribes its own channels; the sentinel is never closed. Like a single client, it must be
|
|
1544
|
+
* connected before it is passed in.
|
|
1545
|
+
*
|
|
1546
|
+
* Satisfied by the client you pass in. In 1.x, members are only added as optional, and the
|
|
1547
|
+
* library checks that they exist before calling them.
|
|
1548
|
+
*/
|
|
1549
|
+
interface NodeRedisSentinelLike extends Omit<NodeRedisLike, 'duplicate'> {
|
|
1550
|
+
/** Marks a Sentinel client; never called. */
|
|
1551
|
+
getSentinelNode(): unknown;
|
|
1552
|
+
/**
|
|
1553
|
+
* Removes one listener of `channel`; the channel's other listeners keep it subscribed. node-redis
|
|
1554
|
+
* types the listener for string and buffer mode alike.
|
|
1555
|
+
*/
|
|
1556
|
+
unsubscribe(channel: string, listener: AnyModePubSubListener): Promise<unknown>;
|
|
1557
|
+
off(event: string, listener: (arg: unknown) => void): unknown;
|
|
1558
|
+
}
|
|
1559
|
+
/** A pub/sub listener as node-redis types it for either mode: string or buffer messages. */
|
|
1560
|
+
type AnyModePubSubListener = (message: string | Uint8Array, channel: string | Uint8Array) => void;
|
|
1561
|
+
/**
|
|
1562
|
+
* Adapts a connected node-redis v5 or v6 client, cluster or Sentinel to the cache's
|
|
1563
|
+
* `RedisClientAdapter`. A cluster (spec 3.4) splits `mget`/`unlink` per slot, scans every master
|
|
1564
|
+
* through `scanIterator`, and publishes and subscribes with sharded pub/sub. A Sentinel subscribes
|
|
1565
|
+
* on itself (see `NodeRedisSentinelLike`).
|
|
1566
|
+
*/
|
|
1567
|
+
declare function nodeRedisAdapter(client: NodeRedisLike | NodeRedisClusterLike | NodeRedisSentinelLike): RedisClientAdapter;
|
|
1568
|
+
|
|
1569
|
+
/** Options of `tieredStore`. */
|
|
1570
|
+
interface TieredStoreOptions {
|
|
1571
|
+
/** The local tier, usually `memoryStore()`. */
|
|
1572
|
+
l1: CacheStore;
|
|
1573
|
+
/** The shared tier, usually `redisStore(...)`; its bus is used unless `invalidation` is set. */
|
|
1574
|
+
l2: CacheStore;
|
|
1575
|
+
/** Upper bound on how long a value lives in L1. Defaults to 10_000 ms. */
|
|
1576
|
+
l1Ttl?: number;
|
|
1577
|
+
/** Overrides `l2.invalidation`. */
|
|
1578
|
+
invalidation?: InvalidationBus;
|
|
1579
|
+
}
|
|
1580
|
+
/**
|
|
1581
|
+
* Two-tier store: a fast local L1 in front of a shared L2. Every write, delete and clear is
|
|
1582
|
+
* published on the invalidation bus so other instances drop their L1 copies. Failures are reported
|
|
1583
|
+
* through the sink given to `bind`; no method rejects except `getStrict` and `setStrict`, which
|
|
1584
|
+
* reject when L2 cannot be read or written.
|
|
1585
|
+
*/
|
|
1586
|
+
declare class TieredStore implements CacheStore {
|
|
1587
|
+
/** The L2's lock, when it has one. */
|
|
1588
|
+
readonly lock?: LockProvider;
|
|
1589
|
+
/** Present only when the L2 has `ping`; probes the L2. */
|
|
1590
|
+
readonly ping?: () => Promise<void>;
|
|
1591
|
+
private readonly l1;
|
|
1592
|
+
private readonly l2;
|
|
1593
|
+
private readonly l1Ttl;
|
|
1594
|
+
private readonly bus;
|
|
1595
|
+
private readonly ownedBus;
|
|
1596
|
+
private readonly origin;
|
|
1597
|
+
private readonly logger;
|
|
1598
|
+
private sink;
|
|
1599
|
+
private subscribed;
|
|
1600
|
+
private warned;
|
|
1601
|
+
private closing;
|
|
1602
|
+
/**
|
|
1603
|
+
* One token per key with an L2 read in flight. Invalidating a key drops its token, so a read
|
|
1604
|
+
* that straddles an invalidation does not backfill L1 with the value it read before it.
|
|
1605
|
+
*/
|
|
1606
|
+
private readonly pending;
|
|
1607
|
+
constructor(options: TieredStoreOptions);
|
|
1608
|
+
bind(sink: CacheEventSink): void;
|
|
1609
|
+
get(key: string): Promise<string | undefined>;
|
|
1610
|
+
/**
|
|
1611
|
+
* Like `get`, but an L2 failure (including `CircuitOpenError`) is reported as `get` and then
|
|
1612
|
+
* rejects with that error instead of counting as a miss. An L1 failure still counts as a miss.
|
|
1613
|
+
*/
|
|
1614
|
+
getStrict(key: string): Promise<string | undefined>;
|
|
1615
|
+
/**
|
|
1616
|
+
* Reads several keys: L1 first, then one L2 read for the misses, backfilling L1 (with `l1Ttl`)
|
|
1617
|
+
* only the keys not invalidated meanwhile. A failing tier counts as misses; an L2 failure is
|
|
1618
|
+
* reported once for the batch.
|
|
1619
|
+
*/
|
|
1620
|
+
getMany(keys: readonly string[]): Promise<(string | undefined)[]>;
|
|
1621
|
+
/**
|
|
1622
|
+
* Writes L2 first, then L1 (each TTL capped at `l1Ttl`), then publishes one message with every
|
|
1623
|
+
* key, unless the L2 refused the write because its circuit is open.
|
|
1624
|
+
*/
|
|
1625
|
+
setMany(entries: readonly {
|
|
1626
|
+
key: string;
|
|
1627
|
+
value: string;
|
|
1628
|
+
ttlMs: number;
|
|
1629
|
+
}[]): Promise<void>;
|
|
1630
|
+
/**
|
|
1631
|
+
* Reads the value and resets its TTL to `ttlMs` on L2 (through `l2.getAndTouch` when it has
|
|
1632
|
+
* one, otherwise `l2.get`). L1 is read but never extended; a backfill lives `min(ttlMs, l1Ttl)`.
|
|
1633
|
+
*/
|
|
1634
|
+
getAndTouch(key: string, ttlMs: number): Promise<string | undefined>;
|
|
1635
|
+
/** L1 read; a failure is reported as `get` and counts as a miss. */
|
|
1636
|
+
private readL1;
|
|
1637
|
+
/**
|
|
1638
|
+
* L2 read after an L1 miss, backfilling L1 unless the key was invalidated meanwhile. A failure
|
|
1639
|
+
* is reported as `get` and counts as a miss, or, when `strict`, rejects with the same error.
|
|
1640
|
+
*/
|
|
1641
|
+
private readL2;
|
|
1642
|
+
set(key: string, value: string, ttlMs: number): Promise<void>;
|
|
1643
|
+
/**
|
|
1644
|
+
* Like `set`, but an L2 failure (including `CircuitOpenError`) is reported as `set` and then
|
|
1645
|
+
* rejects with that error; L1 is not written and nothing is published. Once L2 stored the
|
|
1646
|
+
* value, it continues as `set` does.
|
|
1647
|
+
*/
|
|
1648
|
+
setStrict(key: string, value: string, ttlMs: number): Promise<void>;
|
|
1649
|
+
/** The rest of a set once L2 was tried: L1 with `min(ttlMs, l1Ttl)`, then the publish. */
|
|
1650
|
+
private afterL2Set;
|
|
1651
|
+
delete(keys: readonly string[]): Promise<void>;
|
|
1652
|
+
clear(prefix: string): Promise<void>;
|
|
1653
|
+
/** Idempotent. Closes both tiers and a bus passed in options; `l2.invalidation` belongs to `l2`. */
|
|
1654
|
+
close(): Promise<void>;
|
|
1655
|
+
private closeAll;
|
|
1656
|
+
private readonly onMessage;
|
|
1657
|
+
private readonly onReconnect;
|
|
1658
|
+
/** Errors the bus handles internally, such as a lost subscriber connection. */
|
|
1659
|
+
private readonly onBusError;
|
|
1660
|
+
/** Drops the pending read token of `key` if it is still `token`; true when it was. */
|
|
1661
|
+
private release;
|
|
1662
|
+
private forgetKeys;
|
|
1663
|
+
private forgetPrefix;
|
|
1664
|
+
private publish;
|
|
1665
|
+
/**
|
|
1666
|
+
* Runs `fn`, reporting a rejection or a synchronous throw. Never rejects. Returns the caught
|
|
1667
|
+
* error, or `undefined` on success.
|
|
1668
|
+
*/
|
|
1669
|
+
private attempt;
|
|
1670
|
+
private report;
|
|
1671
|
+
}
|
|
1672
|
+
/** Builds a two-tier store (see `TieredStore`). */
|
|
1673
|
+
declare function tieredStore(options: TieredStoreOptions): TieredStore;
|
|
1674
|
+
|
|
1675
|
+
/** Options of `circuitBreakerStore`. */
|
|
1676
|
+
interface CircuitBreakerStoreOptions {
|
|
1677
|
+
/** Consecutive failures that open the circuit. Integer >= 1; defaults to 5. */
|
|
1678
|
+
failureThreshold?: number;
|
|
1679
|
+
/** How long the circuit stays open before a probe is allowed, in ms. Defaults to 10_000. */
|
|
1680
|
+
openDuration?: number;
|
|
1681
|
+
/**
|
|
1682
|
+
* Per-operation timeout in ms; a timeout counts as a failure. Does not apply to `clear`.
|
|
1683
|
+
* Defaults to 500.
|
|
1684
|
+
*/
|
|
1685
|
+
timeout?: number;
|
|
1686
|
+
}
|
|
1687
|
+
/** Rejection of an operation that the circuit breaker did not pass to the store. */
|
|
1688
|
+
declare class CircuitOpenError extends Error {
|
|
1689
|
+
constructor(message?: string);
|
|
1690
|
+
/**
|
|
1691
|
+
* The ESM and CommonJS builds each define this class, so `instanceof` also accepts any `Error`
|
|
1692
|
+
* named `CircuitOpenError`. Subclasses keep the normal prototype check.
|
|
1693
|
+
*/
|
|
1694
|
+
static [Symbol.hasInstance](value: unknown): boolean;
|
|
1695
|
+
}
|
|
1696
|
+
/**
|
|
1697
|
+
* Wraps a store with a circuit breaker (spec 0.2, 4.6). `get`, `set`, `delete`, `clear`,
|
|
1698
|
+
* `getAndTouch`, `getMany`, `setMany`, `getStrict`, `setStrict`, `ping`, `lock.acquire` and
|
|
1699
|
+
* `LockHandle.release` are guarded: each races a timeout, except `clear`. `clear` runs only
|
|
1700
|
+
* while the circuit is closed (open or half-open it rejects with `CircuitOpenError`, and it is
|
|
1701
|
+
* never the half-open probe); it is not bounded by `timeout`, so set a command or socket timeout
|
|
1702
|
+
* on the client. Its real outcome is recorded once. `failureThreshold` consecutive failures open
|
|
1703
|
+
* the circuit so calls reject with
|
|
1704
|
+
* `CircuitOpenError` without reaching the store. After `openDuration` one probe is let through.
|
|
1705
|
+
* `invalidation`, `bind` and `close` are forwarded unchanged.
|
|
1706
|
+
*/
|
|
1707
|
+
declare class CircuitBreakerStore implements CacheStore {
|
|
1708
|
+
/** Present only when the inner store has `getAndTouch`. */
|
|
1709
|
+
readonly getAndTouch?: (key: string, ttlMs: number) => Promise<string | undefined>;
|
|
1710
|
+
/** Present only when the inner store has `getMany`; one batch counts as one outcome. */
|
|
1711
|
+
readonly getMany?: (keys: readonly string[]) => Promise<(string | undefined)[]>;
|
|
1712
|
+
/** Present only when the inner store has `setMany`; one batch counts as one outcome. */
|
|
1713
|
+
readonly setMany?: (entries: readonly {
|
|
1714
|
+
key: string;
|
|
1715
|
+
value: string;
|
|
1716
|
+
ttlMs: number;
|
|
1717
|
+
}[]) => Promise<void>;
|
|
1718
|
+
/** Present only when the inner store has `getStrict`. */
|
|
1719
|
+
readonly getStrict?: (key: string) => Promise<string | undefined>;
|
|
1720
|
+
/** Present only when the inner store has `setStrict`. */
|
|
1721
|
+
readonly setStrict?: (key: string, value: string, ttlMs: number) => Promise<void>;
|
|
1722
|
+
/** Present only when the inner store has a lock; `acquire` and `release` are guarded. */
|
|
1723
|
+
readonly lock?: LockProvider;
|
|
1724
|
+
/** Present only when the inner store has `ping`; guarded like every other operation. */
|
|
1725
|
+
readonly ping?: () => Promise<void>;
|
|
1726
|
+
/** The inner store's bus, when it has one. */
|
|
1727
|
+
readonly invalidation?: InvalidationBus;
|
|
1728
|
+
private readonly inner;
|
|
1729
|
+
private readonly failureThreshold;
|
|
1730
|
+
private readonly openDuration;
|
|
1731
|
+
private readonly timeout;
|
|
1732
|
+
private current;
|
|
1733
|
+
private failures;
|
|
1734
|
+
private openedAt;
|
|
1735
|
+
/**
|
|
1736
|
+
* Bumped on every state change. An operation only affects the state if no change happened
|
|
1737
|
+
* since it was admitted, so late outcomes from an earlier state are ignored.
|
|
1738
|
+
*/
|
|
1739
|
+
private generation;
|
|
1740
|
+
private sink;
|
|
1741
|
+
constructor(inner: CacheStore, options?: CircuitBreakerStoreOptions);
|
|
1742
|
+
get state(): BreakerState;
|
|
1743
|
+
get(key: string): Promise<string | undefined>;
|
|
1744
|
+
set(key: string, value: string, ttlMs: number): Promise<void>;
|
|
1745
|
+
delete(keys: readonly string[]): Promise<void>;
|
|
1746
|
+
clear(prefix: string): Promise<void>;
|
|
1747
|
+
bind(sink: CacheEventSink): void;
|
|
1748
|
+
close(): Promise<void>;
|
|
1749
|
+
private guardHandle;
|
|
1750
|
+
/**
|
|
1751
|
+
* Admits the call or rejects it with `CircuitOpenError`, then races it against the timeout
|
|
1752
|
+
* (unless `timed` is false, as for `clear`). The first outcome (result, rejection or timeout)
|
|
1753
|
+
* settles the call and is recorded once.
|
|
1754
|
+
*/
|
|
1755
|
+
private guard;
|
|
1756
|
+
private record;
|
|
1757
|
+
private open;
|
|
1758
|
+
private reset;
|
|
1759
|
+
private transition;
|
|
1760
|
+
}
|
|
1761
|
+
/** Wraps `store` with a circuit breaker. Throws `CacheConfigError` for invalid options. */
|
|
1762
|
+
declare function circuitBreakerStore(store: CacheStore, options?: CircuitBreakerStoreOptions): CircuitBreakerStore;
|
|
1763
|
+
|
|
1764
|
+
/**
|
|
1765
|
+
* Structural subset of a Prometheus registry; satisfied by prom-client and @prometheus-io/client.
|
|
1766
|
+
*
|
|
1767
|
+
* Satisfied by the client you pass in. In 1.x, members are only added as optional, and the
|
|
1768
|
+
* library checks that they exist before calling them.
|
|
1769
|
+
*/
|
|
1770
|
+
interface RegistryLike {
|
|
1771
|
+
getSingleMetric(name: string): unknown;
|
|
1772
|
+
removeSingleMetric(name: string): void;
|
|
1773
|
+
/** Real clients call this on every entry of `registers` while constructing a metric. */
|
|
1774
|
+
registerMetric(metric: unknown): void;
|
|
1775
|
+
}
|
|
1776
|
+
type PrometheusConstructor<TInstance> = new (config: never) => TInstance;
|
|
1777
|
+
/**
|
|
1778
|
+
* Structural subset of a prom-client-compatible client module; pass
|
|
1779
|
+
* `import * as client from '...'`.
|
|
1780
|
+
*
|
|
1781
|
+
* Satisfied by the client you pass in. In 1.x, members are only added as optional, and the
|
|
1782
|
+
* library checks that they exist before calling them.
|
|
1783
|
+
*
|
|
1784
|
+
* A minimal hand-written fake, for tests:
|
|
1785
|
+
*
|
|
1786
|
+
* ```ts
|
|
1787
|
+
* const registry: RegistryLike = {
|
|
1788
|
+
* getSingleMetric: () => undefined,
|
|
1789
|
+
* removeSingleMetric: () => undefined,
|
|
1790
|
+
* registerMetric: () => undefined,
|
|
1791
|
+
* };
|
|
1792
|
+
* class FakeMetric {
|
|
1793
|
+
* inc(): void {}
|
|
1794
|
+
* observe(): void {}
|
|
1795
|
+
* set(): void {}
|
|
1796
|
+
* }
|
|
1797
|
+
* const client: PrometheusClientLike = {
|
|
1798
|
+
* Counter: FakeMetric,
|
|
1799
|
+
* Histogram: FakeMetric,
|
|
1800
|
+
* Gauge: FakeMetric,
|
|
1801
|
+
* register: registry,
|
|
1802
|
+
* };
|
|
1803
|
+
* ```
|
|
1804
|
+
*/
|
|
1805
|
+
interface PrometheusClientLike {
|
|
1806
|
+
Counter: PrometheusConstructor<{
|
|
1807
|
+
inc(labels: Record<string, string>): void;
|
|
1808
|
+
}>;
|
|
1809
|
+
Histogram: PrometheusConstructor<{
|
|
1810
|
+
observe(labels: Record<string, string>, value: number): void;
|
|
1811
|
+
}>;
|
|
1812
|
+
Gauge: PrometheusConstructor<{
|
|
1813
|
+
set(labels: Record<string, string>, value: number): void;
|
|
1814
|
+
}>;
|
|
1815
|
+
register: RegistryLike;
|
|
1816
|
+
}
|
|
1817
|
+
/** Options of `CachePrometheusModule.forRoot`. */
|
|
1818
|
+
interface CachePrometheusOptions {
|
|
1819
|
+
/** The client module: `import * as client from 'prom-client'` or `'@prometheus-io/client'`. */
|
|
1820
|
+
client: PrometheusClientLike;
|
|
1821
|
+
/** Where the metrics are registered. Default `client.register`. */
|
|
1822
|
+
registry?: RegistryLike;
|
|
1823
|
+
/** Metric name prefix (not the cache key prefix). Default `'cache_'`. */
|
|
1824
|
+
prefix?: string;
|
|
1825
|
+
/** Histogram buckets in seconds, strictly increasing. Default: the client's default buckets. */
|
|
1826
|
+
buckets?: readonly number[];
|
|
1827
|
+
}
|
|
1828
|
+
/** Options of `CachePrometheusModule.forRootAsync`: `useFactory` resolves the module options. */
|
|
1829
|
+
interface CachePrometheusAsyncOptions {
|
|
1830
|
+
imports?: ModuleMetadata['imports'];
|
|
1831
|
+
inject?: FactoryProvider['inject'];
|
|
1832
|
+
useFactory: (...args: never[]) => CachePrometheusOptions | Promise<CachePrometheusOptions>;
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
/**
|
|
1836
|
+
* Records cache metrics through a Prometheus client you pass in (`prom-client` or
|
|
1837
|
+
* `@prometheus-io/client`). Needs a global `CacheModule`. Opens no endpoint.
|
|
1838
|
+
*/
|
|
1839
|
+
declare class CachePrometheusModule {
|
|
1840
|
+
static forRoot(options: CachePrometheusOptions): DynamicModule;
|
|
1841
|
+
static forRootAsync(options: CachePrometheusAsyncOptions): DynamicModule;
|
|
1842
|
+
}
|
|
1843
|
+
|
|
1844
|
+
/**
|
|
1845
|
+
* Traces cache calls through an OpenTelemetry tracer you pass in, for example
|
|
1846
|
+
* `trace.getTracer('my-app')`; without this module nothing is traced. Needs a global
|
|
1847
|
+
* `CacheModule`. Register it once: a second registration fails the app init with
|
|
1848
|
+
* `CacheConfigError`.
|
|
1849
|
+
*/
|
|
1850
|
+
declare class CacheTracingModule {
|
|
1851
|
+
/** Registers the tracer given up front. Invalid options throw `CacheConfigError`. */
|
|
1852
|
+
static forRoot(options: CacheTracingOptions): DynamicModule;
|
|
1853
|
+
/**
|
|
1854
|
+
* Registers the tracer `useFactory` returns; it can inject providers. Invalid options fail
|
|
1855
|
+
* the app init with `CacheConfigError`.
|
|
1856
|
+
*/
|
|
1857
|
+
static forRootAsync(options: CacheTracingAsyncOptions): DynamicModule;
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1860
|
+
export { CacheConfigError, CacheEvents, CacheEvict, CacheHealthIndicator, CacheModule, CachePrometheusModule, CachePut, CacheService, CacheTracingModule, Cacheable, CircuitBreakerStore, CircuitOpenError, HttpCache, HttpCacheInterceptor, MemoryStore, RedisStore, TieredStore, circuitBreakerStore, compressedSerializer, ioredisAdapter, jsonSerializer, memoryStore, nodeRedisAdapter, redisInvalidationBus, redisStore, tieredStore };
|
|
1861
|
+
export type { BreakerState, CacheDefaults, CacheEnvelope, CacheEventMap, CacheEventSink, CacheEvictOptions, CacheHealthResult, CacheLockDefaults, CacheLogLevel, CacheModuleAsyncOptions, CacheModuleOptions, CacheOperation, CachePrometheusAsyncOptions, CachePrometheusOptions, CachePutOptions, CacheStore, CacheTracingAsyncOptions, CacheTracingOptions, CacheableOptions, CircuitBreakerStoreOptions, CompressedSerializerOptions, GetOrSetManyOptions, GetOrSetOptions, HttpCacheOptions, HttpCacheRequest, HttpCacheTags, InvalidationBus, InvalidationMessage, IoredisClusterLike, IoredisLike, KeyOptions, KeySpec, LoadStrategyOptions, LockHandle, LockProvider, MemoryStoreOptions, NodeRedisClusterLike, NodeRedisLike, NodeRedisSentinelLike, PrometheusClientLike, RedisClientAdapter, RedisInvalidationBusOptions, RedisStoreOptions, RedisSubscriberAdapter, RegistryLike, Serializer, SpanAttributeValue, SpanContextLike, SpanLike, SpanOptionsLike, StrategyOptions, TagSpec, TieredStoreOptions, TracerLike, WriteManyOptions, WriteOptions };
|