flongo 1.0.1 → 1.1.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/dist/cache/cacheConfig.d.ts +62 -0
- package/dist/cache/cacheConfig.js +239 -0
- package/dist/cache/cacheKeyGenerator.d.ts +30 -0
- package/dist/cache/cacheKeyGenerator.js +147 -0
- package/dist/cache/cacheStats.d.ts +69 -0
- package/dist/cache/cacheStats.js +227 -0
- package/dist/cache/cacheStore.d.ts +50 -0
- package/dist/cache/cacheStore.js +57 -0
- package/dist/cache/cacheStrategies.d.ts +61 -0
- package/dist/cache/cacheStrategies.js +229 -0
- package/dist/cache/index.d.ts +7 -0
- package/dist/cache/index.js +25 -0
- package/dist/cache/memoryCache.d.ts +39 -0
- package/dist/cache/memoryCache.js +295 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +18 -1
- package/dist/types.d.ts +18 -1
- package/package.json +1 -1
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CacheMonitor = exports.CacheStatsCollector = void 0;
|
|
4
|
+
exports.getGlobalCacheMonitor = getGlobalCacheMonitor;
|
|
5
|
+
exports.resetGlobalCacheMonitor = resetGlobalCacheMonitor;
|
|
6
|
+
class CacheStatsCollector {
|
|
7
|
+
constructor(maxHistorySize = 1000) {
|
|
8
|
+
this.startTime = Date.now();
|
|
9
|
+
this.lastResetTime = Date.now();
|
|
10
|
+
this.maxHistorySize = maxHistorySize;
|
|
11
|
+
this.metrics = {
|
|
12
|
+
operationCounts: new Map(),
|
|
13
|
+
operationLatencies: new Map(),
|
|
14
|
+
collectionStats: new Map(),
|
|
15
|
+
keyAccessCounts: new Map(),
|
|
16
|
+
memoryUsageOverTime: []
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
recordOperation(operation, latencyMs) {
|
|
20
|
+
const count = this.metrics.operationCounts.get(operation) || 0;
|
|
21
|
+
this.metrics.operationCounts.set(operation, count + 1);
|
|
22
|
+
let latencies = this.metrics.operationLatencies.get(operation);
|
|
23
|
+
if (!latencies) {
|
|
24
|
+
latencies = [];
|
|
25
|
+
this.metrics.operationLatencies.set(operation, latencies);
|
|
26
|
+
}
|
|
27
|
+
latencies.push(latencyMs);
|
|
28
|
+
if (latencies.length > this.maxHistorySize) {
|
|
29
|
+
latencies.shift();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
recordKeyAccess(key) {
|
|
33
|
+
const count = this.metrics.keyAccessCounts.get(key) || 0;
|
|
34
|
+
this.metrics.keyAccessCounts.set(key, count + 1);
|
|
35
|
+
}
|
|
36
|
+
recordMemoryUsage(usageBytes) {
|
|
37
|
+
const entry = {
|
|
38
|
+
timestamp: Date.now(),
|
|
39
|
+
usage: usageBytes
|
|
40
|
+
};
|
|
41
|
+
this.metrics.memoryUsageOverTime.push(entry);
|
|
42
|
+
if (this.metrics.memoryUsageOverTime.length > this.maxHistorySize) {
|
|
43
|
+
this.metrics.memoryUsageOverTime.shift();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
updateCollectionStats(collection, stats) {
|
|
47
|
+
const existing = this.metrics.collectionStats.get(collection) || {
|
|
48
|
+
hits: 0,
|
|
49
|
+
misses: 0,
|
|
50
|
+
evictions: 0,
|
|
51
|
+
sets: 0,
|
|
52
|
+
deletes: 0,
|
|
53
|
+
clears: 0,
|
|
54
|
+
size: 0
|
|
55
|
+
};
|
|
56
|
+
this.metrics.collectionStats.set(collection, {
|
|
57
|
+
...existing,
|
|
58
|
+
...stats
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
getDetailedStats(baseStats) {
|
|
62
|
+
const totalRequests = baseStats.hits + baseStats.misses;
|
|
63
|
+
const uptime = Math.max(1, Date.now() - this.startTime);
|
|
64
|
+
return {
|
|
65
|
+
...baseStats,
|
|
66
|
+
hitRate: totalRequests > 0 ? baseStats.hits / totalRequests : 0,
|
|
67
|
+
missRate: totalRequests > 0 ? baseStats.misses / totalRequests : 0,
|
|
68
|
+
evictionRate: baseStats.sets > 0 ? baseStats.evictions / baseStats.sets : 0,
|
|
69
|
+
averageAccessTime: this.calculateAverageLatency('get'),
|
|
70
|
+
totalRequests,
|
|
71
|
+
uptime,
|
|
72
|
+
lastReset: this.lastResetTime
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
getOperationStats() {
|
|
76
|
+
const stats = new Map();
|
|
77
|
+
for (const [operation, count] of this.metrics.operationCounts.entries()) {
|
|
78
|
+
const latencies = this.metrics.operationLatencies.get(operation) || [];
|
|
79
|
+
if (latencies.length === 0) {
|
|
80
|
+
stats.set(operation, {
|
|
81
|
+
count,
|
|
82
|
+
averageLatency: 0,
|
|
83
|
+
p50: 0,
|
|
84
|
+
p95: 0,
|
|
85
|
+
p99: 0
|
|
86
|
+
});
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
const sorted = [...latencies].sort((a, b) => a - b);
|
|
90
|
+
stats.set(operation, {
|
|
91
|
+
count,
|
|
92
|
+
averageLatency: this.calculateAverage(latencies),
|
|
93
|
+
p50: this.calculatePercentile(sorted, 0.5),
|
|
94
|
+
p95: this.calculatePercentile(sorted, 0.95),
|
|
95
|
+
p99: this.calculatePercentile(sorted, 0.99)
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
return stats;
|
|
99
|
+
}
|
|
100
|
+
getTopKeys(limit = 10) {
|
|
101
|
+
const entries = Array.from(this.metrics.keyAccessCounts.entries());
|
|
102
|
+
return entries
|
|
103
|
+
.sort((a, b) => b[1] - a[1])
|
|
104
|
+
.slice(0, limit)
|
|
105
|
+
.map(([key, count]) => ({ key, count }));
|
|
106
|
+
}
|
|
107
|
+
getMemoryTrend() {
|
|
108
|
+
return [...this.metrics.memoryUsageOverTime];
|
|
109
|
+
}
|
|
110
|
+
getCollectionStats() {
|
|
111
|
+
return new Map(this.metrics.collectionStats);
|
|
112
|
+
}
|
|
113
|
+
reset() {
|
|
114
|
+
this.lastResetTime = Date.now();
|
|
115
|
+
this.metrics = {
|
|
116
|
+
operationCounts: new Map(),
|
|
117
|
+
operationLatencies: new Map(),
|
|
118
|
+
collectionStats: new Map(),
|
|
119
|
+
keyAccessCounts: new Map(),
|
|
120
|
+
memoryUsageOverTime: []
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
calculateAverage(values) {
|
|
124
|
+
if (values.length === 0)
|
|
125
|
+
return 0;
|
|
126
|
+
const sum = values.reduce((a, b) => a + b, 0);
|
|
127
|
+
return sum / values.length;
|
|
128
|
+
}
|
|
129
|
+
calculatePercentile(sortedValues, percentile) {
|
|
130
|
+
if (sortedValues.length === 0)
|
|
131
|
+
return 0;
|
|
132
|
+
const index = Math.ceil(sortedValues.length * percentile) - 1;
|
|
133
|
+
return sortedValues[Math.max(0, Math.min(index, sortedValues.length - 1))];
|
|
134
|
+
}
|
|
135
|
+
calculateAverageLatency(operation) {
|
|
136
|
+
const latencies = this.metrics.operationLatencies.get(operation);
|
|
137
|
+
if (!latencies || latencies.length === 0)
|
|
138
|
+
return 0;
|
|
139
|
+
return this.calculateAverage(latencies);
|
|
140
|
+
}
|
|
141
|
+
toJSON() {
|
|
142
|
+
const operationStats = Object.fromEntries(this.getOperationStats());
|
|
143
|
+
const collectionStats = Object.fromEntries(this.getCollectionStats());
|
|
144
|
+
return {
|
|
145
|
+
uptime: Date.now() - this.startTime,
|
|
146
|
+
lastReset: this.lastResetTime,
|
|
147
|
+
operations: operationStats,
|
|
148
|
+
collections: collectionStats,
|
|
149
|
+
topKeys: this.getTopKeys(10),
|
|
150
|
+
memoryTrend: this.getMemoryTrend().slice(-100)
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
exports.CacheStatsCollector = CacheStatsCollector;
|
|
155
|
+
class CacheMonitor {
|
|
156
|
+
constructor() {
|
|
157
|
+
this.collectors = new Map();
|
|
158
|
+
this.globalCollector = new CacheStatsCollector();
|
|
159
|
+
}
|
|
160
|
+
getCollector(name) {
|
|
161
|
+
let collector = this.collectors.get(name);
|
|
162
|
+
if (!collector) {
|
|
163
|
+
collector = new CacheStatsCollector();
|
|
164
|
+
this.collectors.set(name, collector);
|
|
165
|
+
}
|
|
166
|
+
return collector;
|
|
167
|
+
}
|
|
168
|
+
getGlobalCollector() {
|
|
169
|
+
return this.globalCollector;
|
|
170
|
+
}
|
|
171
|
+
startMonitoring(intervalMs = 60000, callback) {
|
|
172
|
+
if (this.intervalId) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
this.intervalId = setInterval(() => {
|
|
176
|
+
const stats = this.getSnapshot();
|
|
177
|
+
if (callback) {
|
|
178
|
+
callback(stats);
|
|
179
|
+
}
|
|
180
|
+
}, intervalMs);
|
|
181
|
+
if (this.intervalId.unref) {
|
|
182
|
+
this.intervalId.unref();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
stopMonitoring() {
|
|
186
|
+
if (this.intervalId) {
|
|
187
|
+
clearInterval(this.intervalId);
|
|
188
|
+
this.intervalId = undefined;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
getSnapshot() {
|
|
192
|
+
const snapshot = {
|
|
193
|
+
timestamp: Date.now(),
|
|
194
|
+
global: this.globalCollector.toJSON(),
|
|
195
|
+
caches: {}
|
|
196
|
+
};
|
|
197
|
+
for (const [name, collector] of this.collectors.entries()) {
|
|
198
|
+
snapshot.caches[name] = collector.toJSON();
|
|
199
|
+
}
|
|
200
|
+
return snapshot;
|
|
201
|
+
}
|
|
202
|
+
reset() {
|
|
203
|
+
this.globalCollector.reset();
|
|
204
|
+
for (const collector of this.collectors.values()) {
|
|
205
|
+
collector.reset();
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
destroy() {
|
|
209
|
+
this.stopMonitoring();
|
|
210
|
+
this.collectors.clear();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
exports.CacheMonitor = CacheMonitor;
|
|
214
|
+
let globalMonitor;
|
|
215
|
+
function getGlobalCacheMonitor() {
|
|
216
|
+
if (!globalMonitor) {
|
|
217
|
+
globalMonitor = new CacheMonitor();
|
|
218
|
+
}
|
|
219
|
+
return globalMonitor;
|
|
220
|
+
}
|
|
221
|
+
function resetGlobalCacheMonitor() {
|
|
222
|
+
if (globalMonitor) {
|
|
223
|
+
globalMonitor.destroy();
|
|
224
|
+
globalMonitor = undefined;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=cacheStats.js.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export interface CacheEntry<T> {
|
|
2
|
+
value: T;
|
|
3
|
+
ttl?: number;
|
|
4
|
+
createdAt: number;
|
|
5
|
+
lastAccessedAt: number;
|
|
6
|
+
accessCount: number;
|
|
7
|
+
}
|
|
8
|
+
export interface CacheStats {
|
|
9
|
+
hits: number;
|
|
10
|
+
misses: number;
|
|
11
|
+
evictions: number;
|
|
12
|
+
sets: number;
|
|
13
|
+
deletes: number;
|
|
14
|
+
clears: number;
|
|
15
|
+
size: number;
|
|
16
|
+
memoryUsage?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface CacheStore<T> {
|
|
19
|
+
get(key: string): Promise<T | undefined>;
|
|
20
|
+
set(key: string, value: T, ttlSeconds?: number): Promise<void>;
|
|
21
|
+
delete(key: string): Promise<boolean>;
|
|
22
|
+
clear(): Promise<void>;
|
|
23
|
+
has(key: string): Promise<boolean>;
|
|
24
|
+
size(): Promise<number>;
|
|
25
|
+
keys(): Promise<string[]>;
|
|
26
|
+
getStats(): Promise<CacheStats>;
|
|
27
|
+
resetStats(): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
export interface CacheStoreOptions {
|
|
30
|
+
maxEntries?: number;
|
|
31
|
+
defaultTTL?: number;
|
|
32
|
+
enableStats?: boolean;
|
|
33
|
+
onEviction?: <T>(key: string, value: T) => void;
|
|
34
|
+
}
|
|
35
|
+
export declare abstract class BaseCacheStore<T> implements CacheStore<T> {
|
|
36
|
+
protected stats: CacheStats;
|
|
37
|
+
protected options: Required<CacheStoreOptions>;
|
|
38
|
+
constructor(options?: CacheStoreOptions);
|
|
39
|
+
abstract get(key: string): Promise<T | undefined>;
|
|
40
|
+
abstract set(key: string, value: T, ttlSeconds?: number): Promise<void>;
|
|
41
|
+
abstract delete(key: string): Promise<boolean>;
|
|
42
|
+
abstract clear(): Promise<void>;
|
|
43
|
+
abstract has(key: string): Promise<boolean>;
|
|
44
|
+
abstract size(): Promise<number>;
|
|
45
|
+
abstract keys(): Promise<string[]>;
|
|
46
|
+
getStats(): Promise<CacheStats>;
|
|
47
|
+
resetStats(): Promise<void>;
|
|
48
|
+
protected incrementStat(stat: keyof CacheStats, amount?: number): void;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=cacheStore.d.ts.map
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BaseCacheStore = void 0;
|
|
4
|
+
class BaseCacheStore {
|
|
5
|
+
constructor(options = {}) {
|
|
6
|
+
this.stats = {
|
|
7
|
+
hits: 0,
|
|
8
|
+
misses: 0,
|
|
9
|
+
evictions: 0,
|
|
10
|
+
sets: 0,
|
|
11
|
+
deletes: 0,
|
|
12
|
+
clears: 0,
|
|
13
|
+
size: 0,
|
|
14
|
+
memoryUsage: 0
|
|
15
|
+
};
|
|
16
|
+
this.options = {
|
|
17
|
+
maxEntries: options.maxEntries ?? 10000,
|
|
18
|
+
defaultTTL: options.defaultTTL ?? 300,
|
|
19
|
+
enableStats: options.enableStats ?? true,
|
|
20
|
+
onEviction: options.onEviction ?? (() => { })
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
async getStats() {
|
|
24
|
+
if (!this.options.enableStats) {
|
|
25
|
+
return {
|
|
26
|
+
hits: 0,
|
|
27
|
+
misses: 0,
|
|
28
|
+
evictions: 0,
|
|
29
|
+
sets: 0,
|
|
30
|
+
deletes: 0,
|
|
31
|
+
clears: 0,
|
|
32
|
+
size: await this.size(),
|
|
33
|
+
memoryUsage: 0
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return { ...this.stats, size: await this.size() };
|
|
37
|
+
}
|
|
38
|
+
async resetStats() {
|
|
39
|
+
this.stats = {
|
|
40
|
+
hits: 0,
|
|
41
|
+
misses: 0,
|
|
42
|
+
evictions: 0,
|
|
43
|
+
sets: 0,
|
|
44
|
+
deletes: 0,
|
|
45
|
+
clears: 0,
|
|
46
|
+
size: 0,
|
|
47
|
+
memoryUsage: 0
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
incrementStat(stat, amount = 1) {
|
|
51
|
+
if (this.options.enableStats && typeof this.stats[stat] === 'number') {
|
|
52
|
+
this.stats[stat] += amount;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.BaseCacheStore = BaseCacheStore;
|
|
57
|
+
//# sourceMappingURL=cacheStore.js.map
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { CacheStore } from './cacheStore';
|
|
2
|
+
import { ICollectionQuery } from '../types';
|
|
3
|
+
export declare enum InvalidationStrategy {
|
|
4
|
+
TTL = "ttl",
|
|
5
|
+
LRU = "lru",
|
|
6
|
+
Manual = "manual",
|
|
7
|
+
Smart = "smart"
|
|
8
|
+
}
|
|
9
|
+
export interface InvalidationRule {
|
|
10
|
+
strategy: InvalidationStrategy;
|
|
11
|
+
pattern?: string;
|
|
12
|
+
ttlSeconds?: number;
|
|
13
|
+
maxAge?: number;
|
|
14
|
+
dependencies?: string[];
|
|
15
|
+
}
|
|
16
|
+
export interface InvalidationOptions<T = unknown> {
|
|
17
|
+
collection: string;
|
|
18
|
+
operation: 'create' | 'update' | 'delete' | 'batchCreate' | 'batchUpdate' | 'batchDelete';
|
|
19
|
+
ids?: string[];
|
|
20
|
+
query?: ICollectionQuery;
|
|
21
|
+
data?: T;
|
|
22
|
+
}
|
|
23
|
+
export declare class CacheInvalidator<T = unknown> {
|
|
24
|
+
private cache;
|
|
25
|
+
private rules;
|
|
26
|
+
private dependencies;
|
|
27
|
+
constructor(cache: CacheStore<T>);
|
|
28
|
+
addRule(pattern: string, rule: InvalidationRule): void;
|
|
29
|
+
invalidate(options: InvalidationOptions<T>): Promise<void>;
|
|
30
|
+
invalidatePattern(pattern: string): Promise<void>;
|
|
31
|
+
invalidateCollection(collection: string): Promise<void>;
|
|
32
|
+
invalidateOperation(collection: string, operation: string): Promise<void>;
|
|
33
|
+
smartInvalidate(options: InvalidationOptions<T>): Promise<void>;
|
|
34
|
+
private findAffectedKeys;
|
|
35
|
+
private isKeyAffected;
|
|
36
|
+
private invalidateByIds;
|
|
37
|
+
private invalidateByQuery;
|
|
38
|
+
private invalidateListQueries;
|
|
39
|
+
private invalidateCountQueries;
|
|
40
|
+
private invalidateRelatedQueries;
|
|
41
|
+
private invalidateDependencies;
|
|
42
|
+
private patternToRegex;
|
|
43
|
+
}
|
|
44
|
+
export declare class TTLStrategy {
|
|
45
|
+
private defaultTTL;
|
|
46
|
+
private customTTLs;
|
|
47
|
+
constructor(defaultTTLSeconds?: number);
|
|
48
|
+
setTTL(pattern: string, ttlSeconds: number): void;
|
|
49
|
+
getTTL(key: string): number;
|
|
50
|
+
private patternToRegex;
|
|
51
|
+
}
|
|
52
|
+
export declare class LRUStrategy {
|
|
53
|
+
private maxEntries;
|
|
54
|
+
private maxMemoryMB;
|
|
55
|
+
constructor(maxEntries?: number, maxMemoryMB?: number);
|
|
56
|
+
getMaxEntries(): number;
|
|
57
|
+
getMaxMemoryMB(): number;
|
|
58
|
+
setMaxEntries(max: number): void;
|
|
59
|
+
setMaxMemoryMB(max: number): void;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=cacheStrategies.d.ts.map
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LRUStrategy = exports.TTLStrategy = exports.CacheInvalidator = exports.InvalidationStrategy = void 0;
|
|
4
|
+
const cacheKeyGenerator_1 = require("./cacheKeyGenerator");
|
|
5
|
+
var InvalidationStrategy;
|
|
6
|
+
(function (InvalidationStrategy) {
|
|
7
|
+
InvalidationStrategy["TTL"] = "ttl";
|
|
8
|
+
InvalidationStrategy["LRU"] = "lru";
|
|
9
|
+
InvalidationStrategy["Manual"] = "manual";
|
|
10
|
+
InvalidationStrategy["Smart"] = "smart";
|
|
11
|
+
})(InvalidationStrategy || (exports.InvalidationStrategy = InvalidationStrategy = {}));
|
|
12
|
+
class CacheInvalidator {
|
|
13
|
+
constructor(cache) {
|
|
14
|
+
this.cache = cache;
|
|
15
|
+
this.rules = new Map();
|
|
16
|
+
this.dependencies = new Map();
|
|
17
|
+
}
|
|
18
|
+
addRule(pattern, rule) {
|
|
19
|
+
const rules = this.rules.get(pattern) || [];
|
|
20
|
+
rules.push(rule);
|
|
21
|
+
this.rules.set(pattern, rules);
|
|
22
|
+
if (rule.dependencies) {
|
|
23
|
+
for (const dep of rule.dependencies) {
|
|
24
|
+
const deps = this.dependencies.get(dep) || new Set();
|
|
25
|
+
deps.add(pattern);
|
|
26
|
+
this.dependencies.set(dep, deps);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async invalidate(options) {
|
|
31
|
+
const affectedKeys = await this.findAffectedKeys(options);
|
|
32
|
+
for (const key of affectedKeys) {
|
|
33
|
+
await this.cache.delete(key);
|
|
34
|
+
}
|
|
35
|
+
await this.invalidateDependencies(options);
|
|
36
|
+
}
|
|
37
|
+
async invalidatePattern(pattern) {
|
|
38
|
+
const keys = await this.cache.keys();
|
|
39
|
+
const regex = this.patternToRegex(pattern);
|
|
40
|
+
for (const key of keys) {
|
|
41
|
+
if (regex.test(key)) {
|
|
42
|
+
await this.cache.delete(key);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async invalidateCollection(collection) {
|
|
47
|
+
const pattern = cacheKeyGenerator_1.CacheKeyGenerator.generatePattern(collection);
|
|
48
|
+
await this.invalidatePattern(pattern);
|
|
49
|
+
}
|
|
50
|
+
async invalidateOperation(collection, operation) {
|
|
51
|
+
const pattern = cacheKeyGenerator_1.CacheKeyGenerator.generatePattern(collection, operation);
|
|
52
|
+
await this.invalidatePattern(pattern);
|
|
53
|
+
}
|
|
54
|
+
async smartInvalidate(options) {
|
|
55
|
+
switch (options.operation) {
|
|
56
|
+
case 'create':
|
|
57
|
+
case 'batchCreate':
|
|
58
|
+
await this.invalidateListQueries(options.collection);
|
|
59
|
+
await this.invalidateCountQueries(options.collection);
|
|
60
|
+
break;
|
|
61
|
+
case 'update':
|
|
62
|
+
if (options.ids && options.ids.length > 0) {
|
|
63
|
+
await this.invalidateByIds(options.collection, options.ids);
|
|
64
|
+
}
|
|
65
|
+
await this.invalidateRelatedQueries(options);
|
|
66
|
+
break;
|
|
67
|
+
case 'batchUpdate':
|
|
68
|
+
if (options.query) {
|
|
69
|
+
await this.invalidateByQuery(options.collection, options.query);
|
|
70
|
+
}
|
|
71
|
+
else if (options.ids && options.ids.length > 0) {
|
|
72
|
+
await this.invalidateByIds(options.collection, options.ids);
|
|
73
|
+
}
|
|
74
|
+
await this.invalidateListQueries(options.collection);
|
|
75
|
+
break;
|
|
76
|
+
case 'delete':
|
|
77
|
+
case 'batchDelete':
|
|
78
|
+
if (options.ids && options.ids.length > 0) {
|
|
79
|
+
await this.invalidateByIds(options.collection, options.ids);
|
|
80
|
+
}
|
|
81
|
+
await this.invalidateListQueries(options.collection);
|
|
82
|
+
await this.invalidateCountQueries(options.collection);
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async findAffectedKeys(options) {
|
|
87
|
+
const keys = await this.cache.keys();
|
|
88
|
+
const affected = [];
|
|
89
|
+
for (const key of keys) {
|
|
90
|
+
if (this.isKeyAffected(key, options)) {
|
|
91
|
+
affected.push(key);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return affected;
|
|
95
|
+
}
|
|
96
|
+
isKeyAffected(key, options) {
|
|
97
|
+
if (!cacheKeyGenerator_1.CacheKeyGenerator.isFlongoKey(key)) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
const collection = cacheKeyGenerator_1.CacheKeyGenerator.getCollectionFromKey(key);
|
|
101
|
+
if (collection !== options.collection) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
const operation = cacheKeyGenerator_1.CacheKeyGenerator.getOperationFromKey(key);
|
|
105
|
+
switch (options.operation) {
|
|
106
|
+
case 'create':
|
|
107
|
+
case 'batchCreate':
|
|
108
|
+
return operation === 'getAll' ||
|
|
109
|
+
operation === 'getSome' ||
|
|
110
|
+
operation === 'count' ||
|
|
111
|
+
operation === 'exists';
|
|
112
|
+
case 'update':
|
|
113
|
+
case 'batchUpdate':
|
|
114
|
+
return true;
|
|
115
|
+
case 'delete':
|
|
116
|
+
case 'batchDelete':
|
|
117
|
+
return true;
|
|
118
|
+
default:
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
async invalidateByIds(collection, ids) {
|
|
123
|
+
for (const id of ids) {
|
|
124
|
+
const key = cacheKeyGenerator_1.CacheKeyGenerator.generate({
|
|
125
|
+
collection,
|
|
126
|
+
operation: 'get',
|
|
127
|
+
id
|
|
128
|
+
});
|
|
129
|
+
await this.cache.delete(key);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async invalidateByQuery(collection, query) {
|
|
133
|
+
const keys = await this.cache.keys();
|
|
134
|
+
for (const key of keys) {
|
|
135
|
+
if (cacheKeyGenerator_1.CacheKeyGenerator.getCollectionFromKey(key) === collection) {
|
|
136
|
+
await this.cache.delete(key);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
async invalidateListQueries(collection) {
|
|
141
|
+
const operations = ['getAll', 'getSome', 'getFirst'];
|
|
142
|
+
for (const op of operations) {
|
|
143
|
+
await this.invalidateOperation(collection, op);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
async invalidateCountQueries(collection) {
|
|
147
|
+
await this.invalidateOperation(collection, 'count');
|
|
148
|
+
await this.invalidateOperation(collection, 'exists');
|
|
149
|
+
}
|
|
150
|
+
async invalidateRelatedQueries(options) {
|
|
151
|
+
if (!options.data) {
|
|
152
|
+
// If no data provided, invalidate all list queries for safety
|
|
153
|
+
await this.invalidateListQueries(options.collection);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const keys = await this.cache.keys();
|
|
157
|
+
const changedFields = Object.keys(options.data);
|
|
158
|
+
for (const key of keys) {
|
|
159
|
+
if (cacheKeyGenerator_1.CacheKeyGenerator.getCollectionFromKey(key) === options.collection) {
|
|
160
|
+
const operation = cacheKeyGenerator_1.CacheKeyGenerator.getOperationFromKey(key);
|
|
161
|
+
// Only invalidate list queries since individual item queries are handled by invalidateByIds
|
|
162
|
+
if (operation === 'getAll' ||
|
|
163
|
+
operation === 'getSome' ||
|
|
164
|
+
operation === 'getFirst') {
|
|
165
|
+
await this.cache.delete(key);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
async invalidateDependencies(options) {
|
|
171
|
+
const pattern = `${options.collection}:*`;
|
|
172
|
+
const dependentPatterns = this.dependencies.get(pattern) || new Set();
|
|
173
|
+
for (const depPattern of dependentPatterns) {
|
|
174
|
+
await this.invalidatePattern(depPattern);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
patternToRegex(pattern) {
|
|
178
|
+
const escaped = pattern
|
|
179
|
+
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
180
|
+
.replace(/\\\*/g, '.*');
|
|
181
|
+
return new RegExp(`^${escaped}$`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
exports.CacheInvalidator = CacheInvalidator;
|
|
185
|
+
class TTLStrategy {
|
|
186
|
+
constructor(defaultTTLSeconds = 300) {
|
|
187
|
+
this.defaultTTL = defaultTTLSeconds;
|
|
188
|
+
this.customTTLs = new Map();
|
|
189
|
+
}
|
|
190
|
+
setTTL(pattern, ttlSeconds) {
|
|
191
|
+
this.customTTLs.set(pattern, ttlSeconds);
|
|
192
|
+
}
|
|
193
|
+
getTTL(key) {
|
|
194
|
+
for (const [pattern, ttl] of this.customTTLs.entries()) {
|
|
195
|
+
const regex = this.patternToRegex(pattern);
|
|
196
|
+
if (regex.test(key)) {
|
|
197
|
+
return ttl;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return this.defaultTTL;
|
|
201
|
+
}
|
|
202
|
+
patternToRegex(pattern) {
|
|
203
|
+
const escaped = pattern
|
|
204
|
+
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
205
|
+
.replace(/\\\*/g, '.*');
|
|
206
|
+
return new RegExp(`^${escaped}$`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
exports.TTLStrategy = TTLStrategy;
|
|
210
|
+
class LRUStrategy {
|
|
211
|
+
constructor(maxEntries = 10000, maxMemoryMB = 100) {
|
|
212
|
+
this.maxEntries = maxEntries;
|
|
213
|
+
this.maxMemoryMB = maxMemoryMB;
|
|
214
|
+
}
|
|
215
|
+
getMaxEntries() {
|
|
216
|
+
return this.maxEntries;
|
|
217
|
+
}
|
|
218
|
+
getMaxMemoryMB() {
|
|
219
|
+
return this.maxMemoryMB;
|
|
220
|
+
}
|
|
221
|
+
setMaxEntries(max) {
|
|
222
|
+
this.maxEntries = max;
|
|
223
|
+
}
|
|
224
|
+
setMaxMemoryMB(max) {
|
|
225
|
+
this.maxMemoryMB = max;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
exports.LRUStrategy = LRUStrategy;
|
|
229
|
+
//# sourceMappingURL=cacheStrategies.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { CacheStore, CacheEntry, CacheStats, CacheStoreOptions, BaseCacheStore } from './cacheStore';
|
|
2
|
+
export { MemoryCache, MemoryCacheOptions } from './memoryCache';
|
|
3
|
+
export { CacheKeyGenerator, CacheKeyOptions } from './cacheKeyGenerator';
|
|
4
|
+
export { InvalidationStrategy, InvalidationRule, InvalidationOptions, CacheInvalidator, TTLStrategy, LRUStrategy } from './cacheStrategies';
|
|
5
|
+
export { CacheConfig, CacheProviderConfig, CacheConfiguration, createDefaultConfig, createProductionConfig, createDevelopmentConfig } from './cacheConfig';
|
|
6
|
+
export { DetailedCacheStats, CacheMetrics, CacheStatsCollector, CacheMonitor, getGlobalCacheMonitor, resetGlobalCacheMonitor } from './cacheStats';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resetGlobalCacheMonitor = exports.getGlobalCacheMonitor = exports.CacheMonitor = exports.CacheStatsCollector = exports.createDevelopmentConfig = exports.createProductionConfig = exports.createDefaultConfig = exports.CacheConfiguration = exports.LRUStrategy = exports.TTLStrategy = exports.CacheInvalidator = exports.InvalidationStrategy = exports.CacheKeyGenerator = exports.MemoryCache = exports.BaseCacheStore = void 0;
|
|
4
|
+
var cacheStore_1 = require("./cacheStore");
|
|
5
|
+
Object.defineProperty(exports, "BaseCacheStore", { enumerable: true, get: function () { return cacheStore_1.BaseCacheStore; } });
|
|
6
|
+
var memoryCache_1 = require("./memoryCache");
|
|
7
|
+
Object.defineProperty(exports, "MemoryCache", { enumerable: true, get: function () { return memoryCache_1.MemoryCache; } });
|
|
8
|
+
var cacheKeyGenerator_1 = require("./cacheKeyGenerator");
|
|
9
|
+
Object.defineProperty(exports, "CacheKeyGenerator", { enumerable: true, get: function () { return cacheKeyGenerator_1.CacheKeyGenerator; } });
|
|
10
|
+
var cacheStrategies_1 = require("./cacheStrategies");
|
|
11
|
+
Object.defineProperty(exports, "InvalidationStrategy", { enumerable: true, get: function () { return cacheStrategies_1.InvalidationStrategy; } });
|
|
12
|
+
Object.defineProperty(exports, "CacheInvalidator", { enumerable: true, get: function () { return cacheStrategies_1.CacheInvalidator; } });
|
|
13
|
+
Object.defineProperty(exports, "TTLStrategy", { enumerable: true, get: function () { return cacheStrategies_1.TTLStrategy; } });
|
|
14
|
+
Object.defineProperty(exports, "LRUStrategy", { enumerable: true, get: function () { return cacheStrategies_1.LRUStrategy; } });
|
|
15
|
+
var cacheConfig_1 = require("./cacheConfig");
|
|
16
|
+
Object.defineProperty(exports, "CacheConfiguration", { enumerable: true, get: function () { return cacheConfig_1.CacheConfiguration; } });
|
|
17
|
+
Object.defineProperty(exports, "createDefaultConfig", { enumerable: true, get: function () { return cacheConfig_1.createDefaultConfig; } });
|
|
18
|
+
Object.defineProperty(exports, "createProductionConfig", { enumerable: true, get: function () { return cacheConfig_1.createProductionConfig; } });
|
|
19
|
+
Object.defineProperty(exports, "createDevelopmentConfig", { enumerable: true, get: function () { return cacheConfig_1.createDevelopmentConfig; } });
|
|
20
|
+
var cacheStats_1 = require("./cacheStats");
|
|
21
|
+
Object.defineProperty(exports, "CacheStatsCollector", { enumerable: true, get: function () { return cacheStats_1.CacheStatsCollector; } });
|
|
22
|
+
Object.defineProperty(exports, "CacheMonitor", { enumerable: true, get: function () { return cacheStats_1.CacheMonitor; } });
|
|
23
|
+
Object.defineProperty(exports, "getGlobalCacheMonitor", { enumerable: true, get: function () { return cacheStats_1.getGlobalCacheMonitor; } });
|
|
24
|
+
Object.defineProperty(exports, "resetGlobalCacheMonitor", { enumerable: true, get: function () { return cacheStats_1.resetGlobalCacheMonitor; } });
|
|
25
|
+
//# sourceMappingURL=index.js.map
|