kythia-core 0.9.3-beta → 0.9.4-beta.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 +18 -0
- package/package.json +1 -1
- package/src/Kythia.js +1 -1
- package/src/database/KythiaModel.js +169 -74
- package/src/database/KythiaORM.js +1 -1
- package/src/database/KythiaSequelize.js +1 -1
- package/src/managers/AddonManager.js +1 -1
- package/src/managers/EventManager.js +1 -1
- package/src/managers/InteractionManager.js +1 -1
- package/src/managers/ShutdownManager.js +1 -1
package/changelog.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
|
+
|
|
5
|
+
### 0.9.4-beta.0 (2025-11-04)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### 🔧 Changed
|
|
9
|
+
|
|
10
|
+
* Kythia core library structure and update version to 0.9.1-beta. Simplified index.js exports, improved README with installation instructions, and enhanced documentation across various modules. Updated license to CC BY NC 4.0. Cleaned up unnecessary comments and improved code readability. ([1967b65](https://github.com/kenndeclouv/kythia-core/commit/1967b651d49b4c2a85403c2e5d7a58d95ba1d1ed))
|
|
11
|
+
* Update package name to "kythia-core", adjust LRUCache import, and ensure logger availability in InteractionManager for command execution context. ([9e90cf6](https://github.com/kenndeclouv/kythia-core/commit/9e90cf6e04c4655ffbf71813e173de8b8d074b79))
|
|
12
|
+
* Update version to 0.9.2-beta, enhance caching layer with LRU cache support, and improve sharding awareness in KythiaModel. ([6cfb275](https://github.com/kenndeclouv/kythia-core/commit/6cfb275543410aee6e5df429036be9571134618b))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### ✨ Added
|
|
16
|
+
|
|
17
|
+
* Enhance KythiaModel with multi-Redis fallback support, allowing connection to multiple Redis URLs for improved failover handling. Updated dependency injection to accept various Redis options and refined error handling for Redis connections. ([9eac22b](https://github.com/kenndeclouv/kythia-core/commit/9eac22b299b06842514e9576cdf1c08c09944a50))
|
|
18
|
+
* Introduce failover cache flushing in KythiaModel during Redis connection recovery, enhancing error handling and connection management. Added a flag to track failover state and updated event handlers for improved logging and cache management. ([bb30d36](https://github.com/kenndeclouv/kythia-core/commit/bb30d36a845086675fd35774d773fc04d213bc0b))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kythia-core",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.4-beta.0",
|
|
4
4
|
"description": "Core library for the Kythia main Discord bot: extensible, modular, and scalable foundation for commands, components, and event management.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
package/src/Kythia.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @file src/database/KythiaModel.js
|
|
5
5
|
* @copyright © 2025 kenndeclouv
|
|
6
6
|
* @assistant chaa & graa
|
|
7
|
-
* @version 0.9.
|
|
7
|
+
* @version 0.9.4-beta
|
|
8
8
|
*
|
|
9
9
|
* @description
|
|
10
10
|
* Caching layer for Sequelize Models, now sharding-aware. When config.db.redis.shard === true,
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* - Shard Mode: If using Redis sharding, disables Map fallback for strict consistency.
|
|
17
17
|
* - Hybrid Fallback: For non-shard setups, automatic fallback is preserved.
|
|
18
18
|
* - Fast, consistent, safe cache busting.
|
|
19
|
+
* - Multi-Redis Fallback: Support multiple Redis URLs for failover/fallback. Will try connect to next Redis if one fails.
|
|
19
20
|
*/
|
|
20
21
|
|
|
21
22
|
const jsonStringify = require('json-stable-stringify');
|
|
@@ -68,7 +69,12 @@ class KythiaModel extends Model {
|
|
|
68
69
|
|
|
69
70
|
static redisErrorTimestamps = [];
|
|
70
71
|
|
|
71
|
-
static isShardMode = false;
|
|
72
|
+
static isShardMode = false;
|
|
73
|
+
|
|
74
|
+
static _redisFallbackURLs = [];
|
|
75
|
+
static _redisCurrentIndex = 0;
|
|
76
|
+
static _redisFailedIndexes = new Set();
|
|
77
|
+
static _justFailedOver = false;
|
|
72
78
|
|
|
73
79
|
/**
|
|
74
80
|
* 💉 Injects core dependencies into the KythiaModel class.
|
|
@@ -77,7 +83,8 @@ class KythiaModel extends Model {
|
|
|
77
83
|
* @param {Object} dependencies.logger - The logger instance
|
|
78
84
|
* @param {Object} dependencies.config - The application config object
|
|
79
85
|
* @param {Object} [dependencies.redis] - Optional Redis client instance
|
|
80
|
-
* @param {Object} [dependencies.redisOptions] - Redis connection options if not providing a client
|
|
86
|
+
* @param {Object|Array|string} [dependencies.redisOptions] - Redis connection options if not providing a client.
|
|
87
|
+
* Can now be string (URL), object (ioredis options), or array of URLs/options for fallback.
|
|
81
88
|
*/
|
|
82
89
|
static setDependencies({ logger, config, redis, redisOptions }) {
|
|
83
90
|
if (!logger || !config) {
|
|
@@ -88,18 +95,30 @@ class KythiaModel extends Model {
|
|
|
88
95
|
this.config = config;
|
|
89
96
|
this.CACHE_VERSION = config.db?.redisCacheVersion || '1.0.0';
|
|
90
97
|
|
|
91
|
-
// Check for sharding
|
|
92
98
|
this.isShardMode = !!config?.db?.redis?.shard || false;
|
|
93
|
-
|
|
94
99
|
if (this.isShardMode) {
|
|
95
100
|
this.logger.info('🟣 [REDIS][SHARD] Detected redis sharding mode (shard: true). Local fallback cache DISABLED!');
|
|
96
101
|
}
|
|
97
102
|
|
|
103
|
+
if (Array.isArray(redisOptions)) {
|
|
104
|
+
this._redisFallbackURLs = redisOptions.slice();
|
|
105
|
+
} else if (typeof redisOptions === 'string') {
|
|
106
|
+
this._redisFallbackURLs = redisOptions.split(',').map((url) => url.trim());
|
|
107
|
+
} else if (redisOptions && typeof redisOptions === 'object' && Array.isArray(redisOptions.urls)) {
|
|
108
|
+
this._redisFallbackURLs = redisOptions.urls.slice();
|
|
109
|
+
} else if (redisOptions) {
|
|
110
|
+
this._redisFallbackURLs = [redisOptions];
|
|
111
|
+
} else {
|
|
112
|
+
this._redisFallbackURLs = [];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
this._redisCurrentIndex = 0;
|
|
116
|
+
|
|
98
117
|
if (redis) {
|
|
99
118
|
this.redis = redis;
|
|
100
119
|
this.isRedisConnected = redis.status === 'ready';
|
|
101
|
-
} else if (
|
|
102
|
-
this.initializeRedis(
|
|
120
|
+
} else if (this._redisFallbackURLs.length > 0) {
|
|
121
|
+
this.initializeRedis();
|
|
103
122
|
} else {
|
|
104
123
|
if (this.isShardMode) {
|
|
105
124
|
this.logger.error('❌ [REDIS][SHARD] No Redis client/options, but shard:true. Application will work WITHOUT caching!');
|
|
@@ -114,7 +133,8 @@ class KythiaModel extends Model {
|
|
|
114
133
|
/**
|
|
115
134
|
* Helper: Track redis error timestamp, and check if error count in interval exceeds tolerance.
|
|
116
135
|
* Jika error yang terjadi >= REDIS_ERROR_TOLERANCE_COUNT dalam REDIS_ERROR_TOLERANCE_INTERVAL_MS,
|
|
117
|
-
* barulah fallback ke In-Memory (isRedisConnected = false)
|
|
136
|
+
* barulah coba connect ke redis berikutnya (multi redis), jika tidak ada, baru fallback ke In-Memory (isRedisConnected = false)
|
|
137
|
+
* -- KECUALI jika shard: true.
|
|
118
138
|
*/
|
|
119
139
|
static _trackRedisError(err) {
|
|
120
140
|
const now = Date.now();
|
|
@@ -124,21 +144,22 @@ class KythiaModel extends Model {
|
|
|
124
144
|
|
|
125
145
|
if (this.redisErrorTimestamps.length >= REDIS_ERROR_TOLERANCE_COUNT) {
|
|
126
146
|
if (this.isRedisConnected) {
|
|
127
|
-
|
|
128
|
-
if (
|
|
147
|
+
const triedFallback = this._tryRedisFailover();
|
|
148
|
+
if (triedFallback) {
|
|
149
|
+
this.logger.warn(`[REDIS] Error tolerance reached, switching to NEXT Redis failover...`);
|
|
150
|
+
} else if (this.isShardMode) {
|
|
129
151
|
this.logger.error(
|
|
130
152
|
`❌ [REDIS][SHARD] ${this.redisErrorTimestamps.length} consecutive errors in ${
|
|
131
153
|
REDIS_ERROR_TOLERANCE_INTERVAL_MS / 1000
|
|
132
154
|
}s. SHARD MODE: Disabling cache (NO fallback), all queries go to DB. (Last error: ${err?.message})`
|
|
133
155
|
);
|
|
134
156
|
this.isRedisConnected = false;
|
|
135
|
-
// Do not schedule reconnect if redis is not supposed to fallback. Reconnect logic is fine.
|
|
136
157
|
this._scheduleReconnect();
|
|
137
158
|
} else {
|
|
138
159
|
this.logger.error(
|
|
139
160
|
`❌ [REDIS] ${this.redisErrorTimestamps.length} consecutive errors in ${
|
|
140
161
|
REDIS_ERROR_TOLERANCE_INTERVAL_MS / 1000
|
|
141
|
-
}s.
|
|
162
|
+
}s. All Redis exhausted, fallback to In-Memory Cache! (Last error: ${err?.message})`
|
|
142
163
|
);
|
|
143
164
|
this.isRedisConnected = false;
|
|
144
165
|
this._scheduleReconnect();
|
|
@@ -154,94 +175,162 @@ class KythiaModel extends Model {
|
|
|
154
175
|
}
|
|
155
176
|
|
|
156
177
|
/**
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
* @returns {Object} The Redis client instance
|
|
178
|
+
* Coba switch ke redis URL berikutnya jika ada. Return true jika switching, false jika tidak ada lagi.
|
|
179
|
+
* PRIVATE.
|
|
160
180
|
*/
|
|
161
|
-
static
|
|
162
|
-
if (this.
|
|
181
|
+
static _tryRedisFailover() {
|
|
182
|
+
if (!Array.isArray(this._redisFallbackURLs) || this._redisFallbackURLs.length < 2) {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
const prevIndex = this._redisCurrentIndex;
|
|
186
|
+
if (this._redisCurrentIndex + 1 < this._redisFallbackURLs.length) {
|
|
187
|
+
this._redisCurrentIndex++;
|
|
188
|
+
this.logger.warn(
|
|
189
|
+
`[REDIS][FAILOVER] Trying to switch Redis connection from url index ${prevIndex} to ${this._redisCurrentIndex}`
|
|
190
|
+
);
|
|
163
191
|
|
|
164
|
-
|
|
165
|
-
this.lastRedisOpts = redisOptions;
|
|
192
|
+
this._justFailedOver = true;
|
|
166
193
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
194
|
+
this._closeCurrentRedis();
|
|
195
|
+
this.initializeRedis();
|
|
196
|
+
return true;
|
|
170
197
|
}
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
171
200
|
|
|
172
|
-
|
|
201
|
+
/**
|
|
202
|
+
* Close the current Redis (if exists).
|
|
203
|
+
* PRIVATE.
|
|
204
|
+
*/
|
|
205
|
+
static _closeCurrentRedis() {
|
|
206
|
+
if (this.redis && typeof this.redis.quit === 'function') {
|
|
207
|
+
try {
|
|
208
|
+
this.redis.quit();
|
|
209
|
+
} catch (e) {}
|
|
210
|
+
}
|
|
211
|
+
this.redis = undefined;
|
|
212
|
+
this.isRedisConnected = false;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* 🔌 Initializes the Redis connection if not already initialized.
|
|
217
|
+
* (Versi ini MENGHAPUS lazyConnect dan _attemptConnection untuk fix race condition)
|
|
218
|
+
*/
|
|
219
|
+
static initializeRedis(redisOptions) {
|
|
220
|
+
if (redisOptions) {
|
|
221
|
+
if (Array.isArray(redisOptions)) {
|
|
222
|
+
this._redisFallbackURLs = redisOptions.slice();
|
|
223
|
+
this._redisCurrentIndex = 0;
|
|
224
|
+
} else if (redisOptions && typeof redisOptions === 'object' && Array.isArray(redisOptions.urls)) {
|
|
225
|
+
this._redisFallbackURLs = redisOptions.urls.slice();
|
|
226
|
+
this._redisCurrentIndex = 0;
|
|
227
|
+
} else {
|
|
228
|
+
this._redisFallbackURLs = [redisOptions];
|
|
229
|
+
this._redisCurrentIndex = 0;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (!Array.isArray(this._redisFallbackURLs) || this._redisFallbackURLs.length === 0) {
|
|
173
234
|
if (this.isShardMode) {
|
|
174
235
|
this.logger.error('❌ [REDIS][SHARD] No Redis URL/options provided but shard:true. Will run without caching!');
|
|
175
236
|
this.isRedisConnected = false;
|
|
176
237
|
} else {
|
|
177
|
-
this.logger.warn('🟠 [REDIS] No Redis
|
|
238
|
+
this.logger.warn('🟠 [REDIS] No Redis client or options provided. Operating in In-Memory Cache mode only.');
|
|
178
239
|
this.isRedisConnected = false;
|
|
179
240
|
}
|
|
180
241
|
return null;
|
|
181
242
|
}
|
|
182
243
|
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
if (this.isShardMode) {
|
|
186
|
-
this.logger.error(`❌ [REDIS][SHARD] Could not connect after ${times - 1} retries. Disabling cache (no fallback)!`);
|
|
187
|
-
} else {
|
|
188
|
-
this.logger.error(`❌ [REDIS] Could not connect after ${times - 1} retries. Falling back to In-Memory Cache.`);
|
|
189
|
-
}
|
|
190
|
-
return null;
|
|
191
|
-
}
|
|
192
|
-
const delay = Math.min(times * 500, 2000);
|
|
193
|
-
this.logger.warn(`🟠 [REDIS] Connection failed. Retrying in ${delay}ms (Attempt ${times})...`);
|
|
194
|
-
return delay;
|
|
195
|
-
};
|
|
244
|
+
const Redis = require('ioredis');
|
|
245
|
+
this.lastRedisOpts = Array.isArray(this._redisFallbackURLs) ? this._redisFallbackURLs.slice() : [this._redisFallbackURLs];
|
|
196
246
|
|
|
197
|
-
|
|
198
|
-
typeof redisOptions === 'string'
|
|
199
|
-
? { url: redisOptions, retryStrategy, lazyConnect: true }
|
|
200
|
-
: { maxRetriesPerRequest: 2, enableReadyCheck: true, retryStrategy, lazyConnect: true, ...redisOptions };
|
|
247
|
+
if (this.redis) return this.redis;
|
|
201
248
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
249
|
+
const opt = this._redisFallbackURLs[this._redisCurrentIndex];
|
|
250
|
+
|
|
251
|
+
if (opt && typeof opt === 'object' && opt.shard) {
|
|
252
|
+
this.isShardMode = true;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
let redisOpt;
|
|
256
|
+
if (typeof opt === 'string') {
|
|
257
|
+
redisOpt = { url: opt, retryStrategy: this._makeRetryStrategy() };
|
|
258
|
+
} else if (opt && typeof opt === 'object') {
|
|
259
|
+
redisOpt = {
|
|
260
|
+
maxRetriesPerRequest: 2,
|
|
261
|
+
enableReadyCheck: true,
|
|
262
|
+
retryStrategy: this._makeRetryStrategy(),
|
|
263
|
+
...opt,
|
|
264
|
+
};
|
|
265
|
+
} else {
|
|
266
|
+
this.logger.error('❌ [REDIS] Invalid redis config detected in list');
|
|
267
|
+
this.isRedisConnected = false;
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
this.logger.info(
|
|
272
|
+
`[REDIS][INIT] Connecting to Redis fallback #${this._redisCurrentIndex + 1}/${this._redisFallbackURLs.length}: ${
|
|
273
|
+
typeof opt === 'string' ? opt : redisOpt.url || '(object)'
|
|
274
|
+
}`
|
|
205
275
|
);
|
|
206
276
|
|
|
207
|
-
this.redis
|
|
208
|
-
if (this.isShardMode) {
|
|
209
|
-
this.logger.error('❌ [REDIS][SHARD] Initial connection failed: ' + err.message);
|
|
210
|
-
} else {
|
|
211
|
-
this.logger.error('❌ [REDIS] Initial connection failed:', err.message);
|
|
212
|
-
}
|
|
213
|
-
});
|
|
277
|
+
this.redis = new Redis(redisOpt.url || redisOpt);
|
|
214
278
|
|
|
215
279
|
this._setupRedisEventHandlers();
|
|
280
|
+
|
|
216
281
|
return this.redis;
|
|
217
282
|
}
|
|
218
283
|
|
|
284
|
+
/**
|
|
285
|
+
* Internal: Makes retry strategy function which wraps the fallback failover logic if all failed.
|
|
286
|
+
* Used by initializeRedis.
|
|
287
|
+
*/
|
|
288
|
+
static _makeRetryStrategy() {
|
|
289
|
+
return (times) => {
|
|
290
|
+
if (times > 5) {
|
|
291
|
+
this.logger.error(`❌ [REDIS] Could not connect after ${times - 1} retries for Redis #${this._redisCurrentIndex + 1}.`);
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
const delay = Math.min(times * 500, 2000);
|
|
295
|
+
this.logger.warn(
|
|
296
|
+
`🟠 [REDIS] Connection failed for Redis #${this._redisCurrentIndex + 1}. Retrying in ${delay}ms (Attempt ${times})...`
|
|
297
|
+
);
|
|
298
|
+
return delay;
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
219
302
|
/**
|
|
220
303
|
* 🔌 Sets up Redis event handlers
|
|
221
304
|
* @private
|
|
222
305
|
*/
|
|
223
306
|
static _setupRedisEventHandlers() {
|
|
224
|
-
this.redis.on('connect', () => {
|
|
307
|
+
this.redis.on('connect', async () => {
|
|
225
308
|
if (!this.isRedisConnected) {
|
|
226
309
|
this.logger.info('✅ [REDIS] Connection established. Switching to Redis Cache mode.');
|
|
227
310
|
}
|
|
228
311
|
this.isRedisConnected = true;
|
|
229
|
-
|
|
230
312
|
this.redisErrorTimestamps = [];
|
|
231
|
-
|
|
232
313
|
if (this.reconnectTimeout) {
|
|
233
314
|
clearTimeout(this.reconnectTimeout);
|
|
234
315
|
this.reconnectTimeout = null;
|
|
235
316
|
}
|
|
317
|
+
this._redisFailedIndexes.delete(this._redisCurrentIndex);
|
|
318
|
+
|
|
319
|
+
if (this._justFailedOver) {
|
|
320
|
+
this.logger.warn(`[REDIS][FAILOVER] Connected to new server, flushing potentially stale cache...`);
|
|
321
|
+
try {
|
|
322
|
+
await this.redis.flushdb();
|
|
323
|
+
this.logger.info(`[REDIS][FAILOVER] Stale cache flushed successfully.`);
|
|
324
|
+
} catch (err) {
|
|
325
|
+
this.logger.error(`[REDIS][FAILOVER] FAILED TO FLUSH CACHE:`, err);
|
|
326
|
+
}
|
|
327
|
+
this._justFailedOver = false;
|
|
328
|
+
}
|
|
236
329
|
});
|
|
237
330
|
|
|
238
331
|
this.redis.on('error', (err) => {
|
|
239
332
|
if (err && (err.code === 'ECONNREFUSED' || err.message)) {
|
|
240
|
-
|
|
241
|
-
this.logger.warn(`🟠 [REDIS][SHARD] Error: ${err.message}`);
|
|
242
|
-
} else {
|
|
243
|
-
this.logger.warn(`🟠 [REDIS] Error: ${err.message}`);
|
|
244
|
-
}
|
|
333
|
+
this.logger.warn(`🟠 [REDIS] Connection error: ${err.message}`);
|
|
245
334
|
}
|
|
246
335
|
});
|
|
247
336
|
|
|
@@ -250,11 +339,20 @@ class KythiaModel extends Model {
|
|
|
250
339
|
if (this.isShardMode) {
|
|
251
340
|
this.logger.error('❌ [REDIS][SHARD] Connection closed. Cache DISABLED (no fallback).');
|
|
252
341
|
} else {
|
|
253
|
-
this.logger.error('❌ [REDIS] Connection closed.
|
|
342
|
+
this.logger.error('❌ [REDIS] Connection closed. Fallback/failover will be attempted.');
|
|
254
343
|
}
|
|
255
344
|
}
|
|
256
345
|
this.isRedisConnected = false;
|
|
257
|
-
|
|
346
|
+
|
|
347
|
+
this._redisFailedIndexes.add(this._redisCurrentIndex);
|
|
348
|
+
|
|
349
|
+
this.logger.warn(`[REDIS] Connection #${this._redisCurrentIndex + 1} closed. Attempting immediate failover...`);
|
|
350
|
+
const triedFailover = this._tryRedisFailover();
|
|
351
|
+
|
|
352
|
+
if (!triedFailover) {
|
|
353
|
+
this.logger.warn(`[REDIS] Failover exhausted. Scheduling full reconnect...`);
|
|
354
|
+
this._scheduleReconnect();
|
|
355
|
+
}
|
|
258
356
|
});
|
|
259
357
|
}
|
|
260
358
|
|
|
@@ -277,7 +375,11 @@ class KythiaModel extends Model {
|
|
|
277
375
|
|
|
278
376
|
this.reconnectTimeout = setTimeout(() => {
|
|
279
377
|
this.reconnectTimeout = null;
|
|
280
|
-
|
|
378
|
+
|
|
379
|
+
this._redisCurrentIndex = 0;
|
|
380
|
+
this._redisFailedIndexes.clear();
|
|
381
|
+
this._closeCurrentRedis();
|
|
382
|
+
this.initializeRedis();
|
|
281
383
|
}, RECONNECT_DELAY_MINUTES * 60 * 1000);
|
|
282
384
|
}
|
|
283
385
|
|
|
@@ -329,9 +431,8 @@ class KythiaModel extends Model {
|
|
|
329
431
|
if (this.isRedisConnected) {
|
|
330
432
|
await this._redisSetCacheEntry(cacheKey, data, finalTtl, tags);
|
|
331
433
|
} else if (!this.isShardMode) {
|
|
332
|
-
// NON-shard only
|
|
333
434
|
this._mapSetCacheEntry(cacheKey, data, finalTtl);
|
|
334
|
-
}
|
|
435
|
+
}
|
|
335
436
|
}
|
|
336
437
|
|
|
337
438
|
/**
|
|
@@ -345,10 +446,9 @@ class KythiaModel extends Model {
|
|
|
345
446
|
if (this.isRedisConnected) {
|
|
346
447
|
return this._redisGetCachedEntry(cacheKey, includeOptions);
|
|
347
448
|
} else if (!this.isShardMode) {
|
|
348
|
-
// fallback only if not sharding
|
|
349
449
|
return this._mapGetCachedEntry(cacheKey, includeOptions);
|
|
350
450
|
}
|
|
351
|
-
|
|
451
|
+
|
|
352
452
|
return { hit: false, data: undefined };
|
|
353
453
|
}
|
|
354
454
|
|
|
@@ -494,7 +594,7 @@ class KythiaModel extends Model {
|
|
|
494
594
|
* DISABLED in shard mode.
|
|
495
595
|
*/
|
|
496
596
|
static _mapGetCachedEntry(cacheKey, includeOptions) {
|
|
497
|
-
if (this.isShardMode) return { hit: false, data: undefined };
|
|
597
|
+
if (this.isShardMode) return { hit: false, data: undefined };
|
|
498
598
|
|
|
499
599
|
if (this.localNegativeCache.has(cacheKey)) {
|
|
500
600
|
this.cacheStats.mapHits++;
|
|
@@ -544,7 +644,7 @@ class KythiaModel extends Model {
|
|
|
544
644
|
* DISABLED in shard mode.
|
|
545
645
|
*/
|
|
546
646
|
static _mapClearCache(cacheKey) {
|
|
547
|
-
if (this.isShardMode) return;
|
|
647
|
+
if (this.isShardMode) return;
|
|
548
648
|
this.localCache.delete(cacheKey);
|
|
549
649
|
this.localNegativeCache.delete(cacheKey);
|
|
550
650
|
this.cacheStats.clears++;
|
|
@@ -556,7 +656,7 @@ class KythiaModel extends Model {
|
|
|
556
656
|
* DISABLED in shard mode.
|
|
557
657
|
*/
|
|
558
658
|
static _mapClearAllModelCache() {
|
|
559
|
-
if (this.isShardMode) return;
|
|
659
|
+
if (this.isShardMode) return;
|
|
560
660
|
const prefix = `${this.CACHE_VERSION}:${this.name}:`;
|
|
561
661
|
let cleared = 0;
|
|
562
662
|
|
|
@@ -639,7 +739,6 @@ class KythiaModel extends Model {
|
|
|
639
739
|
|
|
640
740
|
const queryPromise = this.findOne(normalizedOptions)
|
|
641
741
|
.then((record) => {
|
|
642
|
-
// Only cache if allowed (no cache in shard/failover unless redis is up)
|
|
643
742
|
if (this.isRedisConnected || !this.isShardMode) {
|
|
644
743
|
const tags = [`${this.name}`];
|
|
645
744
|
if (record) {
|
|
@@ -683,7 +782,6 @@ class KythiaModel extends Model {
|
|
|
683
782
|
|
|
684
783
|
const queryPromise = this.findAll(normalizedOptions)
|
|
685
784
|
.then((records) => {
|
|
686
|
-
// Only cache if allowed
|
|
687
785
|
if (this.isRedisConnected || !this.isShardMode) {
|
|
688
786
|
const tags = [`${this.name}`];
|
|
689
787
|
|
|
@@ -723,7 +821,6 @@ class KythiaModel extends Model {
|
|
|
723
821
|
}
|
|
724
822
|
const findOrCreatePromise = this.findOrCreate(findOrCreateOptions)
|
|
725
823
|
.then(([instance, created]) => {
|
|
726
|
-
// Only cache if allowed
|
|
727
824
|
if (this.isRedisConnected || !this.isShardMode) {
|
|
728
825
|
const tags = [`${this.name}`];
|
|
729
826
|
if (instance) {
|
|
@@ -757,7 +854,6 @@ class KythiaModel extends Model {
|
|
|
757
854
|
this.cacheStats.misses++;
|
|
758
855
|
const count = await this.count(countOptions);
|
|
759
856
|
|
|
760
|
-
// Only cache if allowed
|
|
761
857
|
if (this.isRedisConnected || !this.isShardMode) {
|
|
762
858
|
const tags = [`${this.name}`];
|
|
763
859
|
this.setCacheEntry(cacheKey, count, ttl, tags);
|
|
@@ -807,7 +903,6 @@ class KythiaModel extends Model {
|
|
|
807
903
|
|
|
808
904
|
const result = await this.findAll(queryOptions);
|
|
809
905
|
|
|
810
|
-
// Only cache if allowed
|
|
811
906
|
if (this.isRedisConnected || !this.isShardMode) {
|
|
812
907
|
const tags = [`${this.name}`];
|
|
813
908
|
if (Array.isArray(cacheTags)) tags.push(...cacheTags);
|