layercache 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.
@@ -0,0 +1,227 @@
1
+ import Redis from 'ioredis';
2
+
3
+ interface LayerTtlMap {
4
+ [layerName: string]: number | undefined;
5
+ }
6
+ interface CacheWriteOptions {
7
+ tags?: string[];
8
+ ttl?: number | LayerTtlMap;
9
+ }
10
+ interface CacheGetOptions extends CacheWriteOptions {
11
+ }
12
+ interface CacheMGetEntry<T> {
13
+ key: string;
14
+ fetch?: () => Promise<T>;
15
+ options?: CacheGetOptions;
16
+ }
17
+ interface CacheMSetEntry<T> {
18
+ key: string;
19
+ value: T;
20
+ options?: CacheWriteOptions;
21
+ }
22
+ interface CacheLayer {
23
+ readonly name: string;
24
+ readonly defaultTtl?: number;
25
+ readonly isLocal?: boolean;
26
+ get<T>(key: string): Promise<T | null>;
27
+ set(key: string, value: unknown, ttl?: number): Promise<void>;
28
+ delete(key: string): Promise<void>;
29
+ clear(): Promise<void>;
30
+ deleteMany?(keys: string[]): Promise<void>;
31
+ keys?(): Promise<string[]>;
32
+ }
33
+ interface CacheSerializer {
34
+ serialize(value: unknown): string | Buffer;
35
+ deserialize<T>(payload: string | Buffer): T;
36
+ }
37
+ interface CacheMetricsSnapshot {
38
+ hits: number;
39
+ misses: number;
40
+ fetches: number;
41
+ sets: number;
42
+ deletes: number;
43
+ backfills: number;
44
+ invalidations: number;
45
+ }
46
+ interface CacheLogger {
47
+ debug(message: string, context?: Record<string, unknown>): void;
48
+ }
49
+ interface CacheTagIndex {
50
+ touch(key: string): Promise<void>;
51
+ track(key: string, tags: string[]): Promise<void>;
52
+ remove(key: string): Promise<void>;
53
+ keysForTag(tag: string): Promise<string[]>;
54
+ matchPattern(pattern: string): Promise<string[]>;
55
+ clear(): Promise<void>;
56
+ }
57
+ interface InvalidationMessage {
58
+ scope: 'key' | 'keys' | 'clear';
59
+ sourceId: string;
60
+ keys?: string[];
61
+ operation?: 'write' | 'delete' | 'invalidate' | 'clear';
62
+ }
63
+ interface InvalidationBus {
64
+ subscribe(handler: (message: InvalidationMessage) => Promise<void> | void): Promise<() => Promise<void> | void>;
65
+ publish(message: InvalidationMessage): Promise<void>;
66
+ }
67
+ interface CacheStackOptions {
68
+ logger?: CacheLogger | boolean;
69
+ metrics?: boolean;
70
+ stampedePrevention?: boolean;
71
+ invalidationBus?: InvalidationBus;
72
+ tagIndex?: CacheTagIndex;
73
+ publishSetInvalidation?: boolean;
74
+ }
75
+
76
+ declare class CacheStack {
77
+ private readonly layers;
78
+ private readonly options;
79
+ private readonly stampedeGuard;
80
+ private readonly metrics;
81
+ private readonly instanceId;
82
+ private readonly startup;
83
+ private unsubscribeInvalidation?;
84
+ private readonly logger;
85
+ private readonly tagIndex;
86
+ constructor(layers: CacheLayer[], options?: CacheStackOptions);
87
+ get<T>(key: string, fetcher?: () => Promise<T>, options?: CacheGetOptions): Promise<T | null>;
88
+ set<T>(key: string, value: T, options?: CacheWriteOptions): Promise<void>;
89
+ delete(key: string): Promise<void>;
90
+ clear(): Promise<void>;
91
+ mget<T>(entries: CacheMGetEntry<T>[]): Promise<Array<T | null>>;
92
+ mset<T>(entries: CacheMSetEntry<T>[]): Promise<void>;
93
+ invalidateByTag(tag: string): Promise<void>;
94
+ invalidateByPattern(pattern: string): Promise<void>;
95
+ getMetrics(): CacheMetricsSnapshot;
96
+ resetMetrics(): void;
97
+ disconnect(): Promise<void>;
98
+ private initialize;
99
+ private getFromLayers;
100
+ private backfill;
101
+ private setAcrossLayers;
102
+ private resolveTtl;
103
+ private deleteKeys;
104
+ private publishInvalidation;
105
+ private handleInvalidationMessage;
106
+ }
107
+
108
+ declare class PatternMatcher {
109
+ static matches(pattern: string, value: string): boolean;
110
+ }
111
+
112
+ interface RedisInvalidationBusOptions {
113
+ publisher: Redis;
114
+ subscriber?: Redis;
115
+ channel?: string;
116
+ }
117
+ declare class RedisInvalidationBus implements InvalidationBus {
118
+ private readonly channel;
119
+ private readonly publisher;
120
+ private readonly subscriber;
121
+ constructor(options: RedisInvalidationBusOptions);
122
+ subscribe(handler: (message: InvalidationMessage) => Promise<void> | void): Promise<() => Promise<void>>;
123
+ publish(message: InvalidationMessage): Promise<void>;
124
+ }
125
+
126
+ interface RedisTagIndexOptions {
127
+ client: Redis;
128
+ prefix?: string;
129
+ scanCount?: number;
130
+ }
131
+ declare class RedisTagIndex implements CacheTagIndex {
132
+ private readonly client;
133
+ private readonly prefix;
134
+ private readonly scanCount;
135
+ constructor(options: RedisTagIndexOptions);
136
+ touch(key: string): Promise<void>;
137
+ track(key: string, tags: string[]): Promise<void>;
138
+ remove(key: string): Promise<void>;
139
+ keysForTag(tag: string): Promise<string[]>;
140
+ matchPattern(pattern: string): Promise<string[]>;
141
+ clear(): Promise<void>;
142
+ private scanIndexKeys;
143
+ private knownKeysKey;
144
+ private keyTagsKey;
145
+ private tagKeysKey;
146
+ }
147
+
148
+ declare class TagIndex implements CacheTagIndex {
149
+ private readonly tagToKeys;
150
+ private readonly keyToTags;
151
+ private readonly knownKeys;
152
+ touch(key: string): Promise<void>;
153
+ track(key: string, tags: string[]): Promise<void>;
154
+ remove(key: string): Promise<void>;
155
+ keysForTag(tag: string): Promise<string[]>;
156
+ matchPattern(pattern: string): Promise<string[]>;
157
+ clear(): Promise<void>;
158
+ }
159
+
160
+ interface MemoryLayerOptions {
161
+ ttl?: number;
162
+ maxSize?: number;
163
+ name?: string;
164
+ }
165
+ declare class MemoryLayer implements CacheLayer {
166
+ readonly name: string;
167
+ readonly defaultTtl?: number;
168
+ readonly isLocal = true;
169
+ private readonly maxSize;
170
+ private readonly entries;
171
+ constructor(options?: MemoryLayerOptions);
172
+ get<T>(key: string): Promise<T | null>;
173
+ set(key: string, value: unknown, ttl?: number | undefined): Promise<void>;
174
+ delete(key: string): Promise<void>;
175
+ deleteMany(keys: string[]): Promise<void>;
176
+ clear(): Promise<void>;
177
+ keys(): Promise<string[]>;
178
+ private pruneExpired;
179
+ private isExpired;
180
+ }
181
+
182
+ interface RedisLayerOptions {
183
+ client: Redis;
184
+ ttl?: number;
185
+ name?: string;
186
+ serializer?: CacheSerializer;
187
+ prefix?: string;
188
+ allowUnprefixedClear?: boolean;
189
+ scanCount?: number;
190
+ }
191
+ declare class RedisLayer implements CacheLayer {
192
+ readonly name: string;
193
+ readonly defaultTtl?: number;
194
+ readonly isLocal = false;
195
+ private readonly client;
196
+ private readonly serializer;
197
+ private readonly prefix;
198
+ private readonly allowUnprefixedClear;
199
+ private readonly scanCount;
200
+ constructor(options: RedisLayerOptions);
201
+ get<T>(key: string): Promise<T | null>;
202
+ set(key: string, value: unknown, ttl?: number | undefined): Promise<void>;
203
+ delete(key: string): Promise<void>;
204
+ deleteMany(keys: string[]): Promise<void>;
205
+ clear(): Promise<void>;
206
+ keys(): Promise<string[]>;
207
+ private scanKeys;
208
+ private withPrefix;
209
+ }
210
+
211
+ declare class JsonSerializer implements CacheSerializer {
212
+ serialize(value: unknown): string;
213
+ deserialize<T>(payload: string | Buffer): T;
214
+ }
215
+
216
+ declare class MsgpackSerializer implements CacheSerializer {
217
+ serialize(value: unknown): Buffer;
218
+ deserialize<T>(payload: string | Buffer): T;
219
+ }
220
+
221
+ declare class StampedeGuard {
222
+ private readonly mutexes;
223
+ execute<T>(key: string, task: () => Promise<T>): Promise<T>;
224
+ private getMutex;
225
+ }
226
+
227
+ export { type CacheGetOptions, type CacheLayer, type CacheLogger, type CacheMGetEntry, type CacheMSetEntry, type CacheMetricsSnapshot, type CacheSerializer, CacheStack, type CacheStackOptions, type CacheTagIndex, type CacheWriteOptions, type InvalidationBus, type InvalidationMessage, JsonSerializer, type LayerTtlMap, MemoryLayer, MsgpackSerializer, PatternMatcher, RedisInvalidationBus, RedisLayer, RedisTagIndex, StampedeGuard, TagIndex };
@@ -0,0 +1,227 @@
1
+ import Redis from 'ioredis';
2
+
3
+ interface LayerTtlMap {
4
+ [layerName: string]: number | undefined;
5
+ }
6
+ interface CacheWriteOptions {
7
+ tags?: string[];
8
+ ttl?: number | LayerTtlMap;
9
+ }
10
+ interface CacheGetOptions extends CacheWriteOptions {
11
+ }
12
+ interface CacheMGetEntry<T> {
13
+ key: string;
14
+ fetch?: () => Promise<T>;
15
+ options?: CacheGetOptions;
16
+ }
17
+ interface CacheMSetEntry<T> {
18
+ key: string;
19
+ value: T;
20
+ options?: CacheWriteOptions;
21
+ }
22
+ interface CacheLayer {
23
+ readonly name: string;
24
+ readonly defaultTtl?: number;
25
+ readonly isLocal?: boolean;
26
+ get<T>(key: string): Promise<T | null>;
27
+ set(key: string, value: unknown, ttl?: number): Promise<void>;
28
+ delete(key: string): Promise<void>;
29
+ clear(): Promise<void>;
30
+ deleteMany?(keys: string[]): Promise<void>;
31
+ keys?(): Promise<string[]>;
32
+ }
33
+ interface CacheSerializer {
34
+ serialize(value: unknown): string | Buffer;
35
+ deserialize<T>(payload: string | Buffer): T;
36
+ }
37
+ interface CacheMetricsSnapshot {
38
+ hits: number;
39
+ misses: number;
40
+ fetches: number;
41
+ sets: number;
42
+ deletes: number;
43
+ backfills: number;
44
+ invalidations: number;
45
+ }
46
+ interface CacheLogger {
47
+ debug(message: string, context?: Record<string, unknown>): void;
48
+ }
49
+ interface CacheTagIndex {
50
+ touch(key: string): Promise<void>;
51
+ track(key: string, tags: string[]): Promise<void>;
52
+ remove(key: string): Promise<void>;
53
+ keysForTag(tag: string): Promise<string[]>;
54
+ matchPattern(pattern: string): Promise<string[]>;
55
+ clear(): Promise<void>;
56
+ }
57
+ interface InvalidationMessage {
58
+ scope: 'key' | 'keys' | 'clear';
59
+ sourceId: string;
60
+ keys?: string[];
61
+ operation?: 'write' | 'delete' | 'invalidate' | 'clear';
62
+ }
63
+ interface InvalidationBus {
64
+ subscribe(handler: (message: InvalidationMessage) => Promise<void> | void): Promise<() => Promise<void> | void>;
65
+ publish(message: InvalidationMessage): Promise<void>;
66
+ }
67
+ interface CacheStackOptions {
68
+ logger?: CacheLogger | boolean;
69
+ metrics?: boolean;
70
+ stampedePrevention?: boolean;
71
+ invalidationBus?: InvalidationBus;
72
+ tagIndex?: CacheTagIndex;
73
+ publishSetInvalidation?: boolean;
74
+ }
75
+
76
+ declare class CacheStack {
77
+ private readonly layers;
78
+ private readonly options;
79
+ private readonly stampedeGuard;
80
+ private readonly metrics;
81
+ private readonly instanceId;
82
+ private readonly startup;
83
+ private unsubscribeInvalidation?;
84
+ private readonly logger;
85
+ private readonly tagIndex;
86
+ constructor(layers: CacheLayer[], options?: CacheStackOptions);
87
+ get<T>(key: string, fetcher?: () => Promise<T>, options?: CacheGetOptions): Promise<T | null>;
88
+ set<T>(key: string, value: T, options?: CacheWriteOptions): Promise<void>;
89
+ delete(key: string): Promise<void>;
90
+ clear(): Promise<void>;
91
+ mget<T>(entries: CacheMGetEntry<T>[]): Promise<Array<T | null>>;
92
+ mset<T>(entries: CacheMSetEntry<T>[]): Promise<void>;
93
+ invalidateByTag(tag: string): Promise<void>;
94
+ invalidateByPattern(pattern: string): Promise<void>;
95
+ getMetrics(): CacheMetricsSnapshot;
96
+ resetMetrics(): void;
97
+ disconnect(): Promise<void>;
98
+ private initialize;
99
+ private getFromLayers;
100
+ private backfill;
101
+ private setAcrossLayers;
102
+ private resolveTtl;
103
+ private deleteKeys;
104
+ private publishInvalidation;
105
+ private handleInvalidationMessage;
106
+ }
107
+
108
+ declare class PatternMatcher {
109
+ static matches(pattern: string, value: string): boolean;
110
+ }
111
+
112
+ interface RedisInvalidationBusOptions {
113
+ publisher: Redis;
114
+ subscriber?: Redis;
115
+ channel?: string;
116
+ }
117
+ declare class RedisInvalidationBus implements InvalidationBus {
118
+ private readonly channel;
119
+ private readonly publisher;
120
+ private readonly subscriber;
121
+ constructor(options: RedisInvalidationBusOptions);
122
+ subscribe(handler: (message: InvalidationMessage) => Promise<void> | void): Promise<() => Promise<void>>;
123
+ publish(message: InvalidationMessage): Promise<void>;
124
+ }
125
+
126
+ interface RedisTagIndexOptions {
127
+ client: Redis;
128
+ prefix?: string;
129
+ scanCount?: number;
130
+ }
131
+ declare class RedisTagIndex implements CacheTagIndex {
132
+ private readonly client;
133
+ private readonly prefix;
134
+ private readonly scanCount;
135
+ constructor(options: RedisTagIndexOptions);
136
+ touch(key: string): Promise<void>;
137
+ track(key: string, tags: string[]): Promise<void>;
138
+ remove(key: string): Promise<void>;
139
+ keysForTag(tag: string): Promise<string[]>;
140
+ matchPattern(pattern: string): Promise<string[]>;
141
+ clear(): Promise<void>;
142
+ private scanIndexKeys;
143
+ private knownKeysKey;
144
+ private keyTagsKey;
145
+ private tagKeysKey;
146
+ }
147
+
148
+ declare class TagIndex implements CacheTagIndex {
149
+ private readonly tagToKeys;
150
+ private readonly keyToTags;
151
+ private readonly knownKeys;
152
+ touch(key: string): Promise<void>;
153
+ track(key: string, tags: string[]): Promise<void>;
154
+ remove(key: string): Promise<void>;
155
+ keysForTag(tag: string): Promise<string[]>;
156
+ matchPattern(pattern: string): Promise<string[]>;
157
+ clear(): Promise<void>;
158
+ }
159
+
160
+ interface MemoryLayerOptions {
161
+ ttl?: number;
162
+ maxSize?: number;
163
+ name?: string;
164
+ }
165
+ declare class MemoryLayer implements CacheLayer {
166
+ readonly name: string;
167
+ readonly defaultTtl?: number;
168
+ readonly isLocal = true;
169
+ private readonly maxSize;
170
+ private readonly entries;
171
+ constructor(options?: MemoryLayerOptions);
172
+ get<T>(key: string): Promise<T | null>;
173
+ set(key: string, value: unknown, ttl?: number | undefined): Promise<void>;
174
+ delete(key: string): Promise<void>;
175
+ deleteMany(keys: string[]): Promise<void>;
176
+ clear(): Promise<void>;
177
+ keys(): Promise<string[]>;
178
+ private pruneExpired;
179
+ private isExpired;
180
+ }
181
+
182
+ interface RedisLayerOptions {
183
+ client: Redis;
184
+ ttl?: number;
185
+ name?: string;
186
+ serializer?: CacheSerializer;
187
+ prefix?: string;
188
+ allowUnprefixedClear?: boolean;
189
+ scanCount?: number;
190
+ }
191
+ declare class RedisLayer implements CacheLayer {
192
+ readonly name: string;
193
+ readonly defaultTtl?: number;
194
+ readonly isLocal = false;
195
+ private readonly client;
196
+ private readonly serializer;
197
+ private readonly prefix;
198
+ private readonly allowUnprefixedClear;
199
+ private readonly scanCount;
200
+ constructor(options: RedisLayerOptions);
201
+ get<T>(key: string): Promise<T | null>;
202
+ set(key: string, value: unknown, ttl?: number | undefined): Promise<void>;
203
+ delete(key: string): Promise<void>;
204
+ deleteMany(keys: string[]): Promise<void>;
205
+ clear(): Promise<void>;
206
+ keys(): Promise<string[]>;
207
+ private scanKeys;
208
+ private withPrefix;
209
+ }
210
+
211
+ declare class JsonSerializer implements CacheSerializer {
212
+ serialize(value: unknown): string;
213
+ deserialize<T>(payload: string | Buffer): T;
214
+ }
215
+
216
+ declare class MsgpackSerializer implements CacheSerializer {
217
+ serialize(value: unknown): Buffer;
218
+ deserialize<T>(payload: string | Buffer): T;
219
+ }
220
+
221
+ declare class StampedeGuard {
222
+ private readonly mutexes;
223
+ execute<T>(key: string, task: () => Promise<T>): Promise<T>;
224
+ private getMutex;
225
+ }
226
+
227
+ export { type CacheGetOptions, type CacheLayer, type CacheLogger, type CacheMGetEntry, type CacheMSetEntry, type CacheMetricsSnapshot, type CacheSerializer, CacheStack, type CacheStackOptions, type CacheTagIndex, type CacheWriteOptions, type InvalidationBus, type InvalidationMessage, JsonSerializer, type LayerTtlMap, MemoryLayer, MsgpackSerializer, PatternMatcher, RedisInvalidationBus, RedisLayer, RedisTagIndex, StampedeGuard, TagIndex };