@onurege3467/zerohelper 7.1.0 → 8.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.
@@ -61,6 +61,24 @@ class IDatabase {
61
61
  */
62
62
  bulkInsert(table, dataArray) {}
63
63
 
64
+ /**
65
+ * Numerik alanları artırır (increment).
66
+ * @param {string} table - Verinin güncelleneceği tablo veya koleksiyonun adı.
67
+ * @param {object} increments - Artırılacak alanlar ve miktarları (örn: { views: 1, likes: 2 }).
68
+ * @param {object} where - Hangi kayıtların güncelleneceğini belirleyen koşul nesnesi.
69
+ * @returns {Promise<number>} Etkilenen kayıt sayısını içeren bir Promise.
70
+ */
71
+ increment(table, increments, where) {}
72
+
73
+ /**
74
+ * Numerik alanları azaltır (decrement).
75
+ * @param {string} table - Verinin güncelleneceği tablo veya koleksiyonun adı.
76
+ * @param {object} decrements - Azaltılacak alanlar ve miktarları (örn: { stock: 1, count: 5 }).
77
+ * @param {object} where - Hangi kayıtların güncelleneceğini belirleyen koşul nesnesi.
78
+ * @returns {Promise<number>} Etkilenen kayıt sayısını içeren bir Promise.
79
+ */
80
+ decrement(table, decrements, where) {}
81
+
64
82
  /**
65
83
  * Veritabanı bağlantısını güvenli bir şekilde sonlandırır.
66
84
  * @returns {Promise<void>}
@@ -1,120 +1,584 @@
1
+ // cacheWrapper.js - Redis@4 ve Memory Cache Uyumlu (Düzeltilmiş)
1
2
  const { LRUCache } = require('lru-cache');
3
+ const { createClient } = require('redis');
2
4
 
3
5
  class CacheWrapper {
4
6
  constructor(databaseInstance, options = {}) {
5
7
  this.db = databaseInstance;
8
+ this.cacheType = options.type || 'memory'; // 'memory' or 'redis'
9
+ this.tableCaches = {};
10
+
11
+ // Redis client için başlangıç değerleri
12
+ this.redisClient = null;
13
+ this.redisAvailable = false;
14
+
15
+ if (this.cacheType === 'redis') {
16
+ this._initRedisCache(options);
17
+ } else {
18
+ this._initMemoryCache(options);
19
+ }
20
+ }
21
+
22
+ _initMemoryCache(options) {
6
23
  this.cache = new LRUCache({
7
- max: options.max || 500, // Maximum number of items in cache
8
- ttl: options.ttl || 1000 * 60 * 5, // Time to live in ms (5 minutes)
9
- updateAgeOnGet: options.updateAgeOnGet !== undefined ? options.updateAgeOnGet : false, // Update item age on get
24
+ max: options.max || 500,
25
+ ttl: options.ttl || 1000 * 60 * 5, // milliseconds
26
+ updateAgeOnGet: options.updateAgeOnGet || false,
10
27
  });
11
- this.tableCaches = {}; // Cache for each table
28
+ this.redisAvailable = false;
29
+ this.redisClient = null;
30
+ }
31
+
32
+ async _initRedisCache(options) {
33
+ const redisConfig = {
34
+ socket: {
35
+ host: options.host || '127.0.0.1',
36
+ port: options.port || 6379,
37
+ connectTimeout: options.connectTimeout || 5000,
38
+ },
39
+ password: options.password,
40
+ database: options.db || 0,
41
+ };
42
+
43
+ this.redisClient = createClient(redisConfig);
44
+ this.ttl = options.ttl || 300; // 5 dakika (saniye cinsinden)
45
+ this.keyPrefix = options.keyPrefix || 'db_cache:';
46
+ this.redisAvailable = false;
47
+
48
+ this.redisClient.on('error', (err) => {
49
+ console.warn('Redis Cache Error, memory cache fallback:', err.message);
50
+ this.redisAvailable = false;
51
+ });
52
+
53
+ this.redisClient.on('connect', () => {
54
+ console.log('Redis Cache Connected');
55
+ });
56
+
57
+ this.redisClient.on('ready', () => {
58
+ console.log('Redis Cache Ready');
59
+ this.redisAvailable = true;
60
+ });
61
+
62
+ this.redisClient.on('end', () => {
63
+ console.log('Redis Cache Disconnected');
64
+ this.redisAvailable = false;
65
+ });
66
+
67
+ try {
68
+ await Promise.race([
69
+ this.redisClient.connect(),
70
+ new Promise((_, reject) =>
71
+ setTimeout(() => reject(new Error('Redis connection timeout')), 5000)
72
+ ),
73
+ ]);
74
+ this.redisAvailable = true;
75
+ } catch (error) {
76
+ console.warn('Redis bağlantısı başarısız, memory cache kullanılacak:', error.message);
77
+ this._initMemoryCache(options);
78
+ if (this.redisClient) {
79
+ this.redisClient.removeAllListeners();
80
+ this.redisClient = null;
81
+ }
82
+ this.redisAvailable = false;
83
+ }
12
84
  }
13
85
 
14
86
  _getCache(table) {
87
+ if (this.cacheType === 'redis' && this.redisAvailable && this.redisClient) {
88
+ return this.redisClient;
89
+ }
90
+
91
+ // Memory fallback - tablo bazlı cache oluştur
15
92
  if (!this.tableCaches[table]) {
16
93
  this.tableCaches[table] = new LRUCache({
17
- max: this.cache.max,
18
- ttl: this.cache.ttl,
19
- updateAgeOnGet: this.cache.updateAgeOnGet,
94
+ max: this.cache ? this.cache.max : 500,
95
+ ttl: this.cache ? this.cache.ttl : 300000,
96
+ updateAgeOnGet: this.cache ? this.cache.updateAgeOnGet : false,
20
97
  });
21
98
  }
22
99
  return this.tableCaches[table];
23
100
  }
24
101
 
25
102
  _generateKey(table, where) {
26
- return `${table}:${JSON.stringify(where || {})}`;
103
+ const sortedWhere = where ? this._sortObject(where) : {};
104
+ const key = `${table}:${JSON.stringify(sortedWhere)}`;
105
+ return this.cacheType === 'redis' ? `${this.keyPrefix}${key}` : key;
27
106
  }
28
107
 
29
- // Read operations
30
- async select(table, where) {
108
+ // Where objelerini sıralama (tutarlı key oluşturma için)
109
+ _sortObject(obj) {
110
+ if (!obj || typeof obj !== 'object') return obj;
111
+ return Object.keys(obj)
112
+ .sort()
113
+ .reduce((sorted, key) => {
114
+ sorted[key] = obj[key];
115
+ return sorted;
116
+ }, {});
117
+ }
118
+
119
+ async _getCacheValue(cache, key, table) {
120
+ if (this.cacheType === 'redis' && this.redisAvailable && this.redisClient) {
121
+ try {
122
+ const value = await cache.get(key);
123
+ return value ? JSON.parse(value) : null;
124
+ } catch (err) {
125
+ console.warn('Redis get error, memory fallback:', err.message);
126
+ this.redisAvailable = false;
127
+ // Memory cache'e geçiş yap
128
+ const memoryCache = this._getCache(table);
129
+ return memoryCache.get(key);
130
+ }
131
+ } else {
132
+ return cache.get(key);
133
+ }
134
+ }
135
+
136
+ async _setCacheValue(cache, key, value, table) {
137
+ if (this.cacheType === 'redis' && this.redisAvailable && this.redisClient) {
138
+ try {
139
+ await cache.setEx(key, this.ttl, JSON.stringify(value));
140
+ } catch (err) {
141
+ console.warn('Redis set error, memory fallback:', err.message);
142
+ this.redisAvailable = false;
143
+ // Memory cache'e geçiş yap
144
+ const memoryCache = this._getCache(table);
145
+ memoryCache.set(key, value);
146
+ }
147
+ } else {
148
+ cache.set(key, value);
149
+ }
150
+ }
151
+
152
+ async _clearCache(table) {
153
+ if (this.cacheType === 'redis' && this.redisAvailable && this.redisClient) {
154
+ try {
155
+ const keys = await this.redisClient.keys(`${this.keyPrefix}${table}:*`);
156
+ if (keys.length) await this.redisClient.del(keys);
157
+ } catch (err) {
158
+ console.warn('Redis clear error, memory fallback:', err.message);
159
+ this.redisAvailable = false;
160
+ }
161
+ }
162
+
163
+ // Memory cache'i de temizle
164
+ if (this.tableCaches[table]) {
165
+ this.tableCaches[table].clear();
166
+ }
167
+ }
168
+
169
+ // Belirli bir cache key'i sil
170
+ async _deleteCacheKey(table, key) {
171
+ if (this.cacheType === 'redis' && this.redisAvailable && this.redisClient) {
172
+ try {
173
+ await this.redisClient.del(`${this.keyPrefix}${table}:${key}`);
174
+ } catch (err) {
175
+ console.warn('Redis delete key error:', err.message);
176
+ }
177
+ }
178
+
179
+ // Memory cache'ten de sil
31
180
  const cache = this._getCache(table);
32
- const key = this._generateKey(table, where);
33
- let data = cache.get(key);
181
+ if (cache && cache.delete) {
182
+ cache.delete(key);
183
+ }
184
+ }
34
185
 
35
- if (data) {
36
- // console.log(`Cache hit for select: ${key}`);
37
- return data;
186
+ // Cache'teki veriyi güncelle
187
+ async _updateCacheValue(table, key, newData) {
188
+ const cache = this._getCache(table);
189
+ if (newData !== null && newData !== undefined) {
190
+ await this._setCacheValue(cache, key, newData, table);
191
+ } else {
192
+ await this._deleteCacheKey(table, key);
38
193
  }
194
+ }
39
195
 
40
- // console.log(`Cache miss for select: ${key}`);
41
- data = await this.db.select(table, where);
42
- cache.set(key, data);
43
- return data;
196
+ // Where koşuluna uyan tüm cache key'lerini bul ve güncelle/sil
197
+ async _updateCacheByWhere(table, where, newData = null) {
198
+ // Eğer where boşsa veya çok karmaşıksa, cache'i tamamen temizle
199
+ if (!where || Object.keys(where).length === 0) {
200
+ await this._clearCache(table);
201
+ return;
202
+ }
203
+
204
+ // Redis için
205
+ if (this.cacheType === 'redis' && this.redisAvailable && this.redisClient) {
206
+ try {
207
+ const keys = await this.redisClient.keys(`${this.keyPrefix}${table}:*`);
208
+ for (const fullKey of keys) {
209
+ const cacheData = await this.redisClient.get(fullKey);
210
+ if (cacheData) {
211
+ try {
212
+ const parsedData = JSON.parse(cacheData);
213
+ // Eğer cached data where koşuluna uyuyorsa güncelle/sil
214
+ if (this._matchesWhere(parsedData, where)) {
215
+ if (newData) {
216
+ await this.redisClient.setEx(fullKey, this.ttl, JSON.stringify(newData));
217
+ } else {
218
+ await this.redisClient.del(fullKey);
219
+ }
220
+ }
221
+ } catch (parseErr) {
222
+ // Parse edilemeyen veriyi sil
223
+ await this.redisClient.del(fullKey);
224
+ }
225
+ }
226
+ }
227
+ } catch (err) {
228
+ console.warn('Redis update by where error:', err.message);
229
+ // Hata durumunda cache'i temizle
230
+ await this._clearCache(table);
231
+ }
232
+ }
233
+
234
+ // Memory cache için
235
+ const cache = this._getCache(table);
236
+ if (cache && cache.forEach) {
237
+ const keysToUpdate = [];
238
+ const keysToDelete = [];
239
+
240
+ cache.forEach((value, key) => {
241
+ try {
242
+ if (this._matchesWhere(value, where)) {
243
+ if (newData) {
244
+ keysToUpdate.push({ key, data: newData });
245
+ } else {
246
+ keysToDelete.push(key);
247
+ }
248
+ }
249
+ } catch (err) {
250
+ // Hatalı veriyi sil
251
+ keysToDelete.push(key);
252
+ }
253
+ });
254
+
255
+ // Güncellemeleri uygula
256
+ keysToUpdate.forEach(({ key, data }) => {
257
+ cache.set(key, data);
258
+ });
259
+
260
+ keysToDelete.forEach(key => {
261
+ cache.delete(key);
262
+ });
263
+ }
44
264
  }
45
265
 
46
- async selectOne(table, where) {
266
+ // Basit where matching (nested object desteği ile)
267
+ _matchesWhere(data, where) {
268
+ if (!data || !where) return false;
269
+
270
+ for (const [key, value] of Object.entries(where)) {
271
+ if (data[key] !== value) {
272
+ return false;
273
+ }
274
+ }
275
+ return true;
276
+ }
277
+
278
+ // Read Operations
279
+ async select(table, where) {
47
280
  const cache = this._getCache(table);
48
281
  const key = this._generateKey(table, where);
49
- let data = cache.get(key);
282
+ let data = await this._getCacheValue(cache, key, table);
283
+ if (data !== null && data !== undefined) return data;
50
284
 
51
- if (data) {
52
- // console.log(`Cache hit for selectOne: ${key}`);
53
- return data;
285
+ data = await this.db.select(table, where);
286
+ if (data !== null && data !== undefined) {
287
+ await this._setCacheValue(cache, key, data, table);
54
288
  }
289
+ return data;
290
+ }
291
+
292
+ async selectOne(table, where) {
293
+ const cache = this._getCache(table);
294
+ const key = this._generateKey(table + '_one', where); // selectOne için farklı key
295
+ let data = await this._getCacheValue(cache, key, table);
296
+ if (data !== null && data !== undefined) return data;
55
297
 
56
- // console.log(`Cache miss for selectOne: ${key}`);
57
298
  data = await this.db.selectOne(table, where);
58
- cache.set(key, data);
299
+ if (data !== null && data !== undefined) {
300
+ await this._setCacheValue(cache, key, data, table);
301
+ }
59
302
  return data;
60
303
  }
61
304
 
62
- // Write operations (invalidate cache)
305
+ // Write Operations (smart cache management)
63
306
  async insert(table, data) {
64
- this._getCache(table).clear();
65
- return this.db.insert(table, data);
307
+ const result = await this.db.insert(table, data);
308
+
309
+ // Insert için cache'i tamamen temizlemek yerine, sadece genel sorguları temizle
310
+ // Çünkü yeni veri eklendiğinde select() sonuçları değişebilir
311
+ await this._clearCache(table);
312
+
313
+ return result;
66
314
  }
67
315
 
68
316
  async update(table, data, where) {
69
- this._getCache(table).clear();
70
- return this.db.update(table, data, where);
317
+ const result = await this.db.update(table, data, where);
318
+
319
+ if (result > 0) {
320
+ // Güncellenen verileri cache'te de güncelle
321
+ await this._updateCacheByWhere(table, where, null); // Önce sil
322
+
323
+ // Güncellenen veriyi cache'e eklemek için fresh data'yı al
324
+ try {
325
+ const updatedData = await this.db.selectOne(table, where);
326
+ if (updatedData) {
327
+ // selectOne cache'ine ekle
328
+ const cache = this._getCache(table);
329
+ const key = this._generateKey(table + '_one', where);
330
+ await this._setCacheValue(cache, key, updatedData, table);
331
+ }
332
+ } catch (err) {
333
+ // Hata durumunda cache'i temizle
334
+ await this._clearCache(table);
335
+ }
336
+ }
337
+
338
+ return result;
71
339
  }
72
340
 
73
341
  async set(table, data, where) {
74
- this._getCache(table).clear();
75
- return this.db.set(table, data, where);
342
+ const result = await this.db.set(table, data, where);
343
+
344
+ // Set operasyonu için güncellenmiş/eklenen veriyi cache'e al
345
+ try {
346
+ const newData = await this.db.selectOne(table, where);
347
+ if (newData) {
348
+ // Cache'teki eski veriyi güncelle
349
+ const cache = this._getCache(table);
350
+ const key = this._generateKey(table + '_one', where);
351
+ await this._setCacheValue(cache, key, newData, table);
352
+
353
+ // Select cache'lerini de güncelle (where koşuluna uyarsa)
354
+ await this._updateCacheByWhere(table, where, null); // Eski cache'leri temizle
355
+ }
356
+ } catch (err) {
357
+ // Hata durumunda cache'i temizle
358
+ await this._clearCache(table);
359
+ }
360
+
361
+ return result;
76
362
  }
77
363
 
78
364
  async delete(table, where) {
79
- this._getCache(table).clear();
80
- return this.db.delete(table, where);
81
- }
82
-
83
- async bulkInsert(table, dataArray) {
84
- this._getCache(table).clear();
85
- return this.db.bulkInsert(table, dataArray);
365
+ const result = await this.db.delete(table, where);
366
+
367
+ if (result > 0) {
368
+ // Silinen verileri cache'ten de sil
369
+ await this._updateCacheByWhere(table, where, null);
370
+ }
371
+
372
+ return result;
86
373
  }
87
374
 
88
375
  async deleteOne(table, where) {
89
- this._getCache(table).clear();
90
- return this.db.deleteOne(table, where);
376
+ const result = await this.db.deleteOne(table, where);
377
+
378
+ if (result > 0) {
379
+ // Silinen veriyi cache'ten de sil
380
+ await this._updateCacheByWhere(table, where, null);
381
+ }
382
+
383
+ return result;
91
384
  }
92
385
 
93
386
  async updateOne(table, data, where) {
94
- this._getCache(table).clear();
95
- return this.db.updateOne(table, data, where);
387
+ const result = await this.db.updateOne(table, data, where);
388
+
389
+ if (result > 0) {
390
+ // Güncellenen veriyi cache'te de güncelle
391
+ try {
392
+ const updatedData = await this.db.selectOne(table, where);
393
+ if (updatedData) {
394
+ const cache = this._getCache(table);
395
+ const key = this._generateKey(table + '_one', where);
396
+ await this._setCacheValue(cache, key, updatedData, table);
397
+ }
398
+ } catch (err) {
399
+ // Hata durumunda ilgili cache'leri temizle
400
+ await this._updateCacheByWhere(table, where, null);
401
+ }
402
+ }
403
+
404
+ return result;
405
+ }
406
+
407
+ async bulkInsert(table, dataArray) {
408
+ const result = await this.db.bulkInsert(table, dataArray);
409
+
410
+ // Bulk insert için cache'i tamamen temizle
411
+ // Çünkü çok sayıda yeni veri eklendiğinde select sonuçları değişir
412
+ await this._clearCache(table);
413
+
414
+ return result;
415
+ }
416
+
417
+ async clearAllCache() {
418
+ if (this.cacheType === 'redis' && this.redisAvailable && this.redisClient) {
419
+ try {
420
+ const keys = await this.redisClient.keys(`${this.keyPrefix}*`);
421
+ if (keys.length) await this.redisClient.del(keys);
422
+ } catch (err) {
423
+ console.warn('Redis clearAll error:', err.message);
424
+ }
425
+ }
426
+
427
+ // Tüm memory cache'leri temizle
428
+ Object.values(this.tableCaches).forEach(c => c.clear());
429
+ if (this.cache) this.cache.clear();
430
+ this.tableCaches = {}; // Referansları da temizle
96
431
  }
97
432
 
98
- // Pass-through for other methods (e.g., close, ensureTable, query for MySQL/SQLite)
99
433
  async close() {
100
- // Clear all caches before closing
101
- Object.values(this.tableCaches).forEach(cache => cache.clear());
102
- this.cache.clear();
103
- return this.db.close();
104
- }
105
-
106
- // Dynamically pass through any other methods not explicitly defined here
107
- // This ensures compatibility with specific adapter methods (e.g., MySQL's connect, ping)
108
- // Note: This is a simplified approach. A more robust solution might involve checking
109
- // if the underlying db instance has the method before calling.
110
- get(target, prop) {
111
- if (typeof this[prop] !== 'undefined') {
112
- return this[prop];
113
- } else if (typeof this.db[prop] === 'function') {
114
- return this.db[prop].bind(this.db);
115
- } else {
116
- return this.db[prop];
434
+ await this.clearAllCache();
435
+ if (this.redisClient) {
436
+ try {
437
+ this.redisClient.removeAllListeners();
438
+ if (this.redisAvailable && this.redisClient.isOpen) {
439
+ await this.redisClient.quit();
440
+ } else if (this.redisClient.isOpen) {
441
+ await this.redisClient.disconnect();
442
+ }
443
+ } catch (err) {
444
+ console.warn('Redis close error:', err.message);
445
+ }
446
+ this.redisClient = null;
447
+ this.redisAvailable = false;
448
+ }
449
+
450
+ // Database bağlantısını kapat
451
+ if (this.db && typeof this.db.close === 'function') {
452
+ return this.db.close();
117
453
  }
454
+ return Promise.resolve();
455
+ }
456
+
457
+ /**
458
+ * Numerik alanları artırır (increment) ve cache'i akıllıca günceller.
459
+ * @param {string} table - Verinin güncelleneceği tablo adı.
460
+ * @param {object} increments - Artırılacak alanlar ve miktarları.
461
+ * @param {object} where - Güncelleme koşulları.
462
+ * @returns {Promise<number>} Etkilenen kayıt sayısı.
463
+ */
464
+ async increment(table, increments, where = {}) {
465
+ const result = await this.db.increment(table, increments, where);
466
+
467
+ if (result > 0) {
468
+ // Cache'teki değerleri de increment et
469
+ await this._incrementCacheValues(table, increments, where);
470
+ }
471
+
472
+ return result;
473
+ }
474
+
475
+ /**
476
+ * Numerik alanları azaltır (decrement) ve cache'i akıllıca günceller.
477
+ * @param {string} table - Verinin güncelleneceği tablo adı.
478
+ * @param {object} decrements - Azaltılacak alanlar ve miktarları.
479
+ * @param {object} where - Güncelleme koşulları.
480
+ * @returns {Promise<number>} Etkilenen kayıt sayısı.
481
+ */
482
+ async decrement(table, decrements, where = {}) {
483
+ const result = await this.db.decrement(table, decrements, where);
484
+
485
+ if (result > 0) {
486
+ // Cache'teki değerleri de decrement et
487
+ const negativeIncrements = {};
488
+ for (const [key, value] of Object.entries(decrements)) {
489
+ negativeIncrements[key] = -value;
490
+ }
491
+ await this._incrementCacheValues(table, negativeIncrements, where);
492
+ }
493
+
494
+ return result;
495
+ }
496
+
497
+ // Cache'teki numerik değerleri increment/decrement et
498
+ async _incrementCacheValues(table, increments, where) {
499
+ // Redis için
500
+ if (this.cacheType === 'redis' && this.redisAvailable && this.redisClient) {
501
+ try {
502
+ const keys = await this.redisClient.keys(`${this.keyPrefix}${table}:*`);
503
+ for (const fullKey of keys) {
504
+ const cacheData = await this.redisClient.get(fullKey);
505
+ if (cacheData) {
506
+ try {
507
+ const parsedData = JSON.parse(cacheData);
508
+ if (this._matchesWhere(parsedData, where)) {
509
+ // Cache'teki değerleri increment et
510
+ const updatedData = { ...parsedData };
511
+ for (const [field, increment] of Object.entries(increments)) {
512
+ if (typeof updatedData[field] === 'number') {
513
+ updatedData[field] += increment;
514
+ }
515
+ }
516
+ await this.redisClient.setEx(fullKey, this.ttl, JSON.stringify(updatedData));
517
+ }
518
+ } catch (parseErr) {
519
+ // Parse edilemeyen veriyi sil
520
+ await this.redisClient.del(fullKey);
521
+ }
522
+ }
523
+ }
524
+ } catch (err) {
525
+ console.warn('Redis increment cache error:', err.message);
526
+ // Hata durumunda cache'i temizle
527
+ await this._clearCache(table);
528
+ }
529
+ }
530
+
531
+ // Memory cache için
532
+ const cache = this._getCache(table);
533
+ if (cache && cache.forEach) {
534
+ const keysToUpdate = [];
535
+
536
+ cache.forEach((value, key) => {
537
+ try {
538
+ if (this._matchesWhere(value, where)) {
539
+ const updatedData = { ...value };
540
+ for (const [field, increment] of Object.entries(increments)) {
541
+ if (typeof updatedData[field] === 'number') {
542
+ updatedData[field] += increment;
543
+ }
544
+ }
545
+ keysToUpdate.push({ key, data: updatedData });
546
+ }
547
+ } catch (err) {
548
+ // Hatalı veriyi sil
549
+ cache.delete(key);
550
+ }
551
+ });
552
+
553
+ // Güncellemeleri uygula
554
+ keysToUpdate.forEach(({ key, data }) => {
555
+ cache.set(key, data);
556
+ });
557
+ }
558
+ }
559
+
560
+ // Utility methods
561
+ getCacheStats() {
562
+ const stats = {
563
+ type: this.cacheType,
564
+ redisAvailable: this.redisAvailable,
565
+ memoryTables: Object.keys(this.tableCaches),
566
+ };
567
+
568
+ if (this.cacheType === 'memory') {
569
+ stats.mainCache = {
570
+ size: this.cache ? this.cache.size : 0,
571
+ max: this.cache ? this.cache.max : 0,
572
+ };
573
+ stats.tableCaches = Object.fromEntries(
574
+ Object.entries(this.tableCaches).map(([table, cache]) => [
575
+ table,
576
+ { size: cache.size, max: cache.max }
577
+ ])
578
+ );
579
+ }
580
+
581
+ return stats;
118
582
  }
119
583
  }
120
584