@aetherframework/database 1.0.9 → 1.1.1
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/package.json +1 -2
- package/src/DatabaseManager.js +0 -565
- package/src/core/ConnectionManager.js +0 -351
- package/src/core/DatabaseFactory.js +0 -188
- package/src/core/MongoQueryBuilder.js +0 -576
- package/src/core/PluginManager.js +0 -968
- package/src/core/QueryBuilder.js +0 -4398
- package/src/core/TransactionManager.js +0 -40
- package/src/drivers/clickhouse-driver.js +0 -272
- package/src/drivers/index.js +0 -273
- package/src/drivers/mongodb-driver.js +0 -87
- package/src/drivers/mssql-driver.js +0 -117
- package/src/drivers/mysql-driver.js +0 -169
- package/src/drivers/oracle-driver.js +0 -101
- package/src/drivers/postgres-driver.js +0 -234
- package/src/drivers/redis-driver.js +0 -52
- package/src/drivers/sqlite-driver.js +0 -67
- package/src/middleware/connection-pool.js +0 -455
- package/src/middleware/performance-monitor.js +0 -652
- package/src/middleware/query-cache.js +0 -500
- package/src/middleware/query-logger.js +0 -262
- package/src/plugins/AuditPlugin.js +0 -447
- package/src/plugins/BasePlugin.js +0 -418
- package/src/plugins/BatchOperationPlugin.js +0 -165
- package/src/plugins/CachePlugin.js +0 -407
- package/src/plugins/CtePlugin.js +0 -523
- package/src/plugins/DistributedPlugin.js +0 -543
- package/src/plugins/EncryptionPlugin.js +0 -211
- package/src/plugins/FullTextSearchPlugin.js +0 -164
- package/src/plugins/GeospatialPlugin.js +0 -219
- package/src/plugins/GraphQLPlugin.js +0 -162
- package/src/plugins/HookPlugin.js +0 -211
- package/src/plugins/JsonPlugin.js +0 -366
- package/src/plugins/OptimisticLockPlugin.js +0 -374
- package/src/plugins/PerformancePlugin.js +0 -175
- package/src/plugins/ResiliencePlugin.js +0 -114
- package/src/plugins/ShardingPlugin.js +0 -227
- package/src/plugins/SoftDeletePlugin.js +0 -258
- package/src/plugins/SyncPlugin.js +0 -373
- package/src/plugins/VersioningPlugin.js +0 -314
- package/src/plugins/WindowFunctionPlugin.js +0 -343
- package/src/utils/config-loader.js +0 -632
- package/src/utils/error-handler.js +0 -724
- package/src/utils/migration-runner.js +0 -1066
|
@@ -1,500 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license MIT
|
|
3
|
-
* Copyright (c) 2026-present AetherFramework Contributors.
|
|
4
|
-
* SPDX-License-Identifier: MIT
|
|
5
|
-
* @module @aetherframework/database/middleware/query-cache
|
|
6
|
-
*/
|
|
7
|
-
import { EventEmitter } from 'events';
|
|
8
|
-
|
|
9
|
-
class QueryCacheMiddleware extends EventEmitter {
|
|
10
|
-
constructor(options = {}) {
|
|
11
|
-
super();
|
|
12
|
-
this.options = {
|
|
13
|
-
enabled: options.enabled !== false,
|
|
14
|
-
ttl: options.ttl || 300000, // 5 minutes default
|
|
15
|
-
maxSize: options.maxSize || 1000,
|
|
16
|
-
strategy: options.strategy || 'lru', // lru, fifo, lfu
|
|
17
|
-
cacheNullResults: options.cacheNullResults !== false,
|
|
18
|
-
cacheErrors: options.cacheErrors || false,
|
|
19
|
-
...options
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
this.cache = new Map();
|
|
23
|
-
this.stats = {
|
|
24
|
-
hits: 0,
|
|
25
|
-
misses: 0,
|
|
26
|
-
sets: 0,
|
|
27
|
-
deletes: 0,
|
|
28
|
-
evictions: 0,
|
|
29
|
-
size: 0,
|
|
30
|
-
memoryUsage: 0
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
this.accessOrder = new Map(); // For LRU strategy
|
|
34
|
-
this.accessCount = new Map(); // For LFU strategy
|
|
35
|
-
|
|
36
|
-
this.startCleanupTimer();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Generate cache key from query
|
|
41
|
-
* @param {Object} query - Query object
|
|
42
|
-
* @returns {string} Cache key
|
|
43
|
-
*/
|
|
44
|
-
generateCacheKey(query) {
|
|
45
|
-
const { sql, params = [], connectionName, type = 'query' } = query;
|
|
46
|
-
|
|
47
|
-
// Create a deterministic key
|
|
48
|
-
const keyData = {
|
|
49
|
-
sql: sql.trim().toLowerCase(),
|
|
50
|
-
params: JSON.stringify(params),
|
|
51
|
-
connection: connectionName,
|
|
52
|
-
type
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
return JSON.stringify(keyData);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Check if query should be cached
|
|
60
|
-
* @param {Object} query - Query object
|
|
61
|
-
* @returns {boolean} True if query should be cached
|
|
62
|
-
*/
|
|
63
|
-
shouldCache(query) {
|
|
64
|
-
if (!this.options.enabled) {
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const { sql } = query;
|
|
69
|
-
|
|
70
|
-
// Don't cache INSERT, UPDATE, DELETE queries
|
|
71
|
-
const lowerSql = sql.toLowerCase().trim();
|
|
72
|
-
if (lowerSql.startsWith('insert ') ||
|
|
73
|
-
lowerSql.startsWith('update ') ||
|
|
74
|
-
lowerSql.startsWith('delete ') ||
|
|
75
|
-
lowerSql.startsWith('create ') ||
|
|
76
|
-
lowerSql.startsWith('alter ') ||
|
|
77
|
-
lowerSql.startsWith('drop ') ||
|
|
78
|
-
lowerSql.startsWith('truncate ')) {
|
|
79
|
-
return false;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Check for cache hints in SQL comments
|
|
83
|
-
if (sql.includes('/* no-cache */')) {
|
|
84
|
-
return false;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (sql.includes('/* cache */')) {
|
|
88
|
-
return true;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Default: cache SELECT queries
|
|
92
|
-
return lowerSql.startsWith('select ');
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Get cached result
|
|
97
|
-
* @param {Object} query - Query object
|
|
98
|
-
* @returns {Object|null} Cached result or null
|
|
99
|
-
*/
|
|
100
|
-
get(query) {
|
|
101
|
-
if (!this.options.enabled) {
|
|
102
|
-
return null;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const key = this.generateCacheKey(query);
|
|
106
|
-
|
|
107
|
-
if (!this.cache.has(key)) {
|
|
108
|
-
this.stats.misses++;
|
|
109
|
-
this.emit('cache-miss', { key, query });
|
|
110
|
-
return null;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const cached = this.cache.get(key);
|
|
114
|
-
|
|
115
|
-
// Check if cache entry has expired
|
|
116
|
-
if (cached.expiresAt && Date.now() > cached.expiresAt) {
|
|
117
|
-
this.cache.delete(key);
|
|
118
|
-
this.stats.evictions++;
|
|
119
|
-
this.stats.misses++;
|
|
120
|
-
this.stats.size--;
|
|
121
|
-
this.emit('cache-expired', { key, query });
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Update access order for LRU
|
|
126
|
-
if (this.options.strategy === 'lru') {
|
|
127
|
-
this.accessOrder.set(key, Date.now());
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Update access count for LFU
|
|
131
|
-
if (this.options.strategy === 'lfu') {
|
|
132
|
-
const count = this.accessCount.get(key) || 0;
|
|
133
|
-
this.accessCount.set(key, count + 1);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
this.stats.hits++;
|
|
137
|
-
this.emit('cache-hit', {
|
|
138
|
-
key,
|
|
139
|
-
query,
|
|
140
|
-
cachedAt: cached.cachedAt,
|
|
141
|
-
expiresAt: cached.expiresAt,
|
|
142
|
-
ttl: cached.ttl
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
return cached.result;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Set cache result
|
|
150
|
-
* @param {Object} query - Query object
|
|
151
|
-
* @param {Object} result - Query result
|
|
152
|
-
* @param {number} ttl - Time to live in milliseconds
|
|
153
|
-
*/
|
|
154
|
-
set(query, result, ttl = null) {
|
|
155
|
-
if (!this.options.enabled || !this.shouldCache(query)) {
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Don't cache null results if configured
|
|
160
|
-
if (!this.options.cacheNullResults && (result === null || result === undefined)) {
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// Don't cache errors if configured
|
|
165
|
-
if (!this.options.cacheErrors && result.error) {
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const key = this.generateCacheKey(query);
|
|
170
|
-
const actualTtl = ttl || this.options.ttl;
|
|
171
|
-
const expiresAt = Date.now() + actualTtl;
|
|
172
|
-
|
|
173
|
-
// Check cache size limit
|
|
174
|
-
if (this.cache.size >= this.options.maxSize) {
|
|
175
|
-
this.evict();
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const cacheEntry = {
|
|
179
|
-
result,
|
|
180
|
-
cachedAt: Date.now(),
|
|
181
|
-
expiresAt,
|
|
182
|
-
ttl: actualTtl,
|
|
183
|
-
query: {
|
|
184
|
-
sql: query.sql.substring(0, 100) + (query.sql.length > 100 ? '...' : ''),
|
|
185
|
-
params: query.params,
|
|
186
|
-
connection: query.connectionName,
|
|
187
|
-
type: query.type
|
|
188
|
-
}
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
this.cache.set(key, cacheEntry);
|
|
192
|
-
|
|
193
|
-
// Update access order for LRU
|
|
194
|
-
if (this.options.strategy === 'lru') {
|
|
195
|
-
this.accessOrder.set(key, Date.now());
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// Initialize access count for LFU
|
|
199
|
-
if (this.options.strategy === 'lfu') {
|
|
200
|
-
this.accessCount.set(key, 1);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
this.stats.sets++;
|
|
204
|
-
this.stats.size = this.cache.size;
|
|
205
|
-
this.stats.memoryUsage = this.estimateMemoryUsage();
|
|
206
|
-
|
|
207
|
-
this.emit('cache-set', {
|
|
208
|
-
key,
|
|
209
|
-
query: cacheEntry.query,
|
|
210
|
-
cachedAt: cacheEntry.cachedAt,
|
|
211
|
-
expiresAt: cacheEntry.expiresAt,
|
|
212
|
-
ttl: cacheEntry.ttl
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Delete cache entry
|
|
218
|
-
* @param {Object} query - Query object
|
|
219
|
-
*/
|
|
220
|
-
delete(query) {
|
|
221
|
-
const key = this.generateCacheKey(query);
|
|
222
|
-
if (this.cache.delete(key)) {
|
|
223
|
-
this.accessOrder.delete(key);
|
|
224
|
-
this.accessCount.delete(key);
|
|
225
|
-
this.stats.deletes++;
|
|
226
|
-
this.stats.size = this.cache.size;
|
|
227
|
-
this.stats.memoryUsage = this.estimateMemoryUsage();
|
|
228
|
-
this.emit('cache-delete', { key, query });
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/**
|
|
233
|
-
* Clear all cache entries
|
|
234
|
-
* @param {string} pattern - Pattern to match (optional)
|
|
235
|
-
*/
|
|
236
|
-
clear(pattern = null) {
|
|
237
|
-
if (pattern) {
|
|
238
|
-
const regex = new RegExp(pattern);
|
|
239
|
-
for (const [key] of this.cache.entries()) {
|
|
240
|
-
if (regex.test(key)) {
|
|
241
|
-
this.cache.delete(key);
|
|
242
|
-
this.accessOrder.delete(key);
|
|
243
|
-
this.accessCount.delete(key);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
} else {
|
|
247
|
-
this.cache.clear();
|
|
248
|
-
this.accessOrder.clear();
|
|
249
|
-
this.accessCount.clear();
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
this.stats.size = this.cache.size;
|
|
253
|
-
this.stats.memoryUsage = this.estimateMemoryUsage();
|
|
254
|
-
this.emit('cache-clear', { pattern });
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Evict entries based on strategy
|
|
259
|
-
*/
|
|
260
|
-
evict() {
|
|
261
|
-
const entriesToEvict = Math.max(1, Math.floor(this.options.maxSize * 0.1)); // Evict 10%
|
|
262
|
-
|
|
263
|
-
switch (this.options.strategy) {
|
|
264
|
-
case 'lru':
|
|
265
|
-
this.evictLRU(entriesToEvict);
|
|
266
|
-
break;
|
|
267
|
-
case 'lfu':
|
|
268
|
-
this.evictLFU(entriesToEvict);
|
|
269
|
-
break;
|
|
270
|
-
case 'fifo':
|
|
271
|
-
default:
|
|
272
|
-
this.evictFIFO(entriesToEvict);
|
|
273
|
-
break;
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
/**
|
|
278
|
-
* Evict using LRU (Least Recently Used) strategy
|
|
279
|
-
* @param {number} count - Number of entries to evict
|
|
280
|
-
*/
|
|
281
|
-
evictLRU(count) {
|
|
282
|
-
const entries = Array.from(this.accessOrder.entries())
|
|
283
|
-
.sort((a, b) => a - b) // Sort by access time (oldest first)
|
|
284
|
-
.slice(0, count);
|
|
285
|
-
|
|
286
|
-
for (const [key] of entries) {
|
|
287
|
-
this.cache.delete(key);
|
|
288
|
-
this.accessOrder.delete(key);
|
|
289
|
-
this.accessCount.delete(key);
|
|
290
|
-
this.stats.evictions++;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
this.stats.size = this.cache.size;
|
|
294
|
-
this.emit('cache-evicted', { strategy: 'lru', count: entries.length });
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
* Evict using LFU (Least Frequently Used) strategy
|
|
299
|
-
* @param {number} count - Number of entries to evict
|
|
300
|
-
*/
|
|
301
|
-
evictLFU(count) {
|
|
302
|
-
const entries = Array.from(this.accessCount.entries())
|
|
303
|
-
.sort((a, b) => a - b) // Sort by access count (least frequent first)
|
|
304
|
-
.slice(0, count);
|
|
305
|
-
|
|
306
|
-
for (const [key] of entries) {
|
|
307
|
-
this.cache.delete(key);
|
|
308
|
-
this.accessOrder.delete(key);
|
|
309
|
-
this.accessCount.delete(key);
|
|
310
|
-
this.stats.evictions++;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
this.stats.size = this.cache.size;
|
|
314
|
-
this.emit('cache-evicted', { strategy: 'lfu', count: entries.length });
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
/**
|
|
318
|
-
* Evict using FIFO (First In First Out) strategy
|
|
319
|
-
* @param {number} count - Number of entries to evict
|
|
320
|
-
*/
|
|
321
|
-
evictFIFO(count) {
|
|
322
|
-
const entries = Array.from(this.cache.entries())
|
|
323
|
-
.sort((a, b) => a.cachedAt - b.cachedAt) // Sort by cache time (oldest first)
|
|
324
|
-
.slice(0, count);
|
|
325
|
-
|
|
326
|
-
for (const [key] of entries) {
|
|
327
|
-
this.cache.delete(key);
|
|
328
|
-
this.accessOrder.delete(key);
|
|
329
|
-
this.accessCount.delete(key);
|
|
330
|
-
this.stats.evictions++;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
this.stats.size = this.cache.size;
|
|
334
|
-
this.emit('cache-evicted', { strategy: 'fifo', count: entries.length });
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
/**
|
|
338
|
-
* Start cleanup timer
|
|
339
|
-
*/
|
|
340
|
-
startCleanupTimer() {
|
|
341
|
-
setInterval(() => {
|
|
342
|
-
this.cleanupExpired();
|
|
343
|
-
}, 60000); // Cleanup every minute
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
/**
|
|
347
|
-
* Cleanup expired cache entries
|
|
348
|
-
*/
|
|
349
|
-
cleanupExpired() {
|
|
350
|
-
const now = Date.now();
|
|
351
|
-
let expiredCount = 0;
|
|
352
|
-
|
|
353
|
-
for (const [key, entry] of this.cache.entries()) {
|
|
354
|
-
if (entry.expiresAt && now > entry.expiresAt) {
|
|
355
|
-
this.cache.delete(key);
|
|
356
|
-
this.accessOrder.delete(key);
|
|
357
|
-
this.accessCount.delete(key);
|
|
358
|
-
expiredCount++;
|
|
359
|
-
this.stats.evictions++;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
if (expiredCount > 0) {
|
|
364
|
-
this.stats.size = this.cache.size;
|
|
365
|
-
this.stats.memoryUsage = this.estimateMemoryUsage();
|
|
366
|
-
this.emit('cache-cleanup', { expiredCount });
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
/**
|
|
371
|
-
* Estimate memory usage
|
|
372
|
-
* @returns {number} Estimated memory usage in bytes
|
|
373
|
-
*/
|
|
374
|
-
estimateMemoryUsage() {
|
|
375
|
-
let total = 0;
|
|
376
|
-
for (const [key, value] of this.cache.entries()) {
|
|
377
|
-
total += key.length * 2; // UTF-16 string
|
|
378
|
-
total += JSON.stringify(value).length * 2;
|
|
379
|
-
}
|
|
380
|
-
return total;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
/**
|
|
384
|
-
* Get cache statistics
|
|
385
|
-
* @returns {Object} Cache statistics
|
|
386
|
-
*/
|
|
387
|
-
getStats() {
|
|
388
|
-
const hitRate = this.stats.hits + this.stats.misses > 0
|
|
389
|
-
? (this.stats.hits / (this.stats.hits + this.stats.misses) * 100).toFixed(2) + '%'
|
|
390
|
-
: '0%';
|
|
391
|
-
|
|
392
|
-
return {
|
|
393
|
-
...this.stats,
|
|
394
|
-
hitRate,
|
|
395
|
-
strategy: this.options.strategy,
|
|
396
|
-
ttl: this.options.ttl,
|
|
397
|
-
maxSize: this.options.maxSize,
|
|
398
|
-
enabled: this.options.enabled,
|
|
399
|
-
cacheNullResults: this.options.cacheNullResults,
|
|
400
|
-
cacheErrors: this.options.cacheErrors,
|
|
401
|
-
timestamp: new Date().toISOString()
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
/**
|
|
406
|
-
* Get cache entries
|
|
407
|
-
* @param {number} limit - Maximum number of entries to return
|
|
408
|
-
* @returns {Array} Cache entries
|
|
409
|
-
*/
|
|
410
|
-
getEntries(limit = 100) {
|
|
411
|
-
const entries = [];
|
|
412
|
-
let count = 0;
|
|
413
|
-
|
|
414
|
-
for (const [key, entry] of this.cache.entries()) {
|
|
415
|
-
if (count >= limit) break;
|
|
416
|
-
|
|
417
|
-
entries.push({
|
|
418
|
-
key: key.substring(0, 100) + (key.length > 100 ? '...' : ''),
|
|
419
|
-
query: entry.query,
|
|
420
|
-
cachedAt: new Date(entry.cachedAt).toISOString(),
|
|
421
|
-
expiresAt: entry.expiresAt ? new Date(entry.expiresAt).toISOString() : null,
|
|
422
|
-
ttl: entry.ttl,
|
|
423
|
-
age: Date.now() - entry.cachedAt,
|
|
424
|
-
expiresIn: entry.expiresAt ? entry.expiresAt - Date.now() : null
|
|
425
|
-
});
|
|
426
|
-
|
|
427
|
-
count++;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
return entries;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
/**
|
|
434
|
-
* Invalidate cache by pattern
|
|
435
|
-
* @param {string} pattern - Pattern to match
|
|
436
|
-
* @returns {number} Number of invalidated entries
|
|
437
|
-
*/
|
|
438
|
-
invalidate(pattern) {
|
|
439
|
-
const regex = new RegExp(pattern);
|
|
440
|
-
let invalidated = 0;
|
|
441
|
-
|
|
442
|
-
for (const [key] of this.cache.entries()) {
|
|
443
|
-
if (regex.test(key)) {
|
|
444
|
-
this.cache.delete(key);
|
|
445
|
-
this.accessOrder.delete(key);
|
|
446
|
-
this.accessCount.delete(key);
|
|
447
|
-
invalidated++;
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
if (invalidated > 0) {
|
|
452
|
-
this.stats.size = this.cache.size;
|
|
453
|
-
this.stats.memoryUsage = this.estimateMemoryUsage();
|
|
454
|
-
this.emit('cache-invalidated', { pattern, count: invalidated });
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
return invalidated;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
/**
|
|
461
|
-
* Pre-warm cache with queries
|
|
462
|
-
* @param {Array} queries - Array of queries to pre-warm
|
|
463
|
-
* @param {Function} executeQuery - Function to execute query
|
|
464
|
-
* @returns {Promise<Array>} Pre-warm results
|
|
465
|
-
*/
|
|
466
|
-
async prewarm(queries, executeQuery) {
|
|
467
|
-
const results = [];
|
|
468
|
-
|
|
469
|
-
for (const query of queries) {
|
|
470
|
-
try {
|
|
471
|
-
const result = await executeQuery(query);
|
|
472
|
-
this.set(query, result);
|
|
473
|
-
results.push({ query, success: true });
|
|
474
|
-
} catch (error) {
|
|
475
|
-
results.push({ query, success: false, error: error.message });
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
this.emit('cache-prewarmed', { count: queries.length, results });
|
|
480
|
-
return results;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
/**
|
|
484
|
-
* Reset cache statistics
|
|
485
|
-
*/
|
|
486
|
-
resetStats() {
|
|
487
|
-
this.stats = {
|
|
488
|
-
hits: 0,
|
|
489
|
-
misses: 0,
|
|
490
|
-
sets: 0,
|
|
491
|
-
deletes: 0,
|
|
492
|
-
evictions: 0,
|
|
493
|
-
size: this.cache.size,
|
|
494
|
-
memoryUsage: this.estimateMemoryUsage()
|
|
495
|
-
};
|
|
496
|
-
this.emit('stats-reset');
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
export default QueryCacheMiddleware;
|