@dofe/infra-redis 0.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.
Files changed (45) hide show
  1. package/dist/cache.service.d.ts +16 -0
  2. package/dist/cache.service.d.ts.map +1 -0
  3. package/dist/cache.service.js +69 -0
  4. package/dist/cache.service.js.map +1 -0
  5. package/dist/dto/redis.dto.d.ts +11 -0
  6. package/dist/dto/redis.dto.d.ts.map +1 -0
  7. package/dist/dto/redis.dto.js +5 -0
  8. package/dist/dto/redis.dto.js.map +1 -0
  9. package/dist/index.d.ts +10 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +26 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/redis-lock.module.d.ts +3 -0
  14. package/dist/redis-lock.module.d.ts.map +1 -0
  15. package/dist/redis-lock.module.js +25 -0
  16. package/dist/redis-lock.module.js.map +1 -0
  17. package/dist/redis-lock.service.d.ts +33 -0
  18. package/dist/redis-lock.service.d.ts.map +1 -0
  19. package/dist/redis-lock.service.js +159 -0
  20. package/dist/redis-lock.service.js.map +1 -0
  21. package/dist/redis-version-check.d.ts +6 -0
  22. package/dist/redis-version-check.d.ts.map +1 -0
  23. package/dist/redis-version-check.js +43 -0
  24. package/dist/redis-version-check.js.map +1 -0
  25. package/dist/redis.module.d.ts +3 -0
  26. package/dist/redis.module.d.ts.map +1 -0
  27. package/dist/redis.module.js +77 -0
  28. package/dist/redis.module.js.map +1 -0
  29. package/dist/redis.service.d.ts +70 -0
  30. package/dist/redis.service.d.ts.map +1 -0
  31. package/dist/redis.service.js +800 -0
  32. package/dist/redis.service.js.map +1 -0
  33. package/dist/redis.service.spec.d.ts +2 -0
  34. package/dist/redis.service.spec.d.ts.map +1 -0
  35. package/dist/redis.service.spec.js +17 -0
  36. package/dist/redis.service.spec.js.map +1 -0
  37. package/dist/tenant-redis.module.d.ts +3 -0
  38. package/dist/tenant-redis.module.d.ts.map +1 -0
  39. package/dist/tenant-redis.module.js +25 -0
  40. package/dist/tenant-redis.module.js.map +1 -0
  41. package/dist/tenant-redis.service.d.ts +16 -0
  42. package/dist/tenant-redis.service.d.ts.map +1 -0
  43. package/dist/tenant-redis.service.js +62 -0
  44. package/dist/tenant-redis.service.js.map +1 -0
  45. package/package.json +37 -0
@@ -0,0 +1,800 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.RedisService = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const ioredis_1 = require("ioredis");
18
+ const redis_dto_1 = require("./dto/redis.dto");
19
+ const uuid_1 = require("uuid");
20
+ const config_1 = require("@nestjs/config");
21
+ /**
22
+ * Check if running in production environment
23
+ */
24
+ function isProduction() {
25
+ return process.env.NODE_ENV === 'production';
26
+ }
27
+ /**
28
+ * Simple console logger fallback when Winston is not available
29
+ */
30
+ const consoleLogger = {
31
+ error: (message, meta) => console.error(message, meta),
32
+ warn: (message, meta) => console.warn(message, meta),
33
+ info: (message, meta) => console.info(message, meta),
34
+ debug: (message, meta) => {
35
+ if (!isProduction())
36
+ console.debug(message, meta);
37
+ },
38
+ };
39
+ let RedisService = class RedisService {
40
+ configService;
41
+ redisClient;
42
+ redisConfigs = {};
43
+ lastClosedLogTime = 0;
44
+ CLOSED_LOG_THROTTLE_MS = 5000;
45
+ logger;
46
+ constructor(configService, redisClient, winstonLogger) {
47
+ this.configService = configService;
48
+ this.redisClient = redisClient;
49
+ this.logger = winstonLogger ?? consoleLogger;
50
+ const configs = this.configService.get('redis') ?? [];
51
+ configs.forEach((config) => {
52
+ this.redisConfigs[config.name] = config;
53
+ });
54
+ }
55
+ isConnectionAvailable() {
56
+ if (!this.redisClient) {
57
+ return false;
58
+ }
59
+ const status = this.redisClient.status;
60
+ return status === 'ready' || status === 'connect';
61
+ }
62
+ shouldLogClosedError() {
63
+ const now = Date.now();
64
+ if (now - this.lastClosedLogTime > this.CLOSED_LOG_THROTTLE_MS) {
65
+ this.lastClosedLogTime = now;
66
+ return true;
67
+ }
68
+ return false;
69
+ }
70
+ async onModuleDestroy() {
71
+ if (this.redisClient) {
72
+ try {
73
+ if (this.redisClient.status !== 'end' &&
74
+ this.redisClient.status !== 'close') {
75
+ await this.redisClient.quit();
76
+ }
77
+ }
78
+ catch (error) {
79
+ if (!(error instanceof Error) || !error.message.includes('closed')) {
80
+ if (isProduction()) {
81
+ this.logger.error('Error closing Redis connection', { error });
82
+ }
83
+ else {
84
+ this.logger.debug('Error closing Redis connection', { error });
85
+ }
86
+ }
87
+ }
88
+ }
89
+ if (isProduction()) {
90
+ this.logger.info('Redis service destroyed');
91
+ }
92
+ else {
93
+ this.logger.debug('Redis service destroyed');
94
+ }
95
+ }
96
+ get redis() {
97
+ return this.redisClient;
98
+ }
99
+ getExpireIn(name) {
100
+ return this.redisConfigs[name]?.expireIn ?? -1;
101
+ }
102
+ getRedisKey(name, key) {
103
+ return this.redisConfigs[name]?.key + key;
104
+ }
105
+ async saveDataToList(name, key, value) {
106
+ const redisKey = this.redisConfigs[name]?.key + key;
107
+ if (!this.isConnectionAvailable()) {
108
+ return;
109
+ }
110
+ try {
111
+ await this.redis.rpush(redisKey, JSON.stringify(value));
112
+ }
113
+ catch (error) {
114
+ if (error instanceof Error && error.message.includes('closed')) {
115
+ if (this.shouldLogClosedError()) {
116
+ if (isProduction()) {
117
+ this.logger.warn('Redis connection closed, saveDataToList failed');
118
+ }
119
+ else {
120
+ this.logger.debug('Redis connection closed, saveDataToList failed', { error });
121
+ }
122
+ }
123
+ }
124
+ else {
125
+ if (isProduction()) {
126
+ this.logger.error('Redis saveDataToList error:', { error });
127
+ }
128
+ else {
129
+ this.logger.debug('Redis saveDataToList error:', { error });
130
+ }
131
+ }
132
+ }
133
+ }
134
+ async getListData(name, key) {
135
+ const redisKey = this.redisConfigs[name]?.key + key;
136
+ if (!this.isConnectionAvailable()) {
137
+ return [];
138
+ }
139
+ try {
140
+ const data = await this.redis.lrange(redisKey, 0, -1);
141
+ return data.length > 0 ? data.map((item) => JSON.parse(item)) : [];
142
+ }
143
+ catch (error) {
144
+ if (error instanceof Error && error.message.includes('closed')) {
145
+ if (this.shouldLogClosedError()) {
146
+ if (isProduction()) {
147
+ this.logger.warn('Redis connection closed, getListData failed');
148
+ }
149
+ else {
150
+ this.logger.debug('Redis connection closed, getListData failed', { error });
151
+ }
152
+ }
153
+ }
154
+ else {
155
+ if (isProduction()) {
156
+ this.logger.error('Redis getListData error:', { error });
157
+ }
158
+ else {
159
+ this.logger.debug('Redis getListData error:', { error });
160
+ }
161
+ }
162
+ return [];
163
+ }
164
+ }
165
+ async pushDataToList(name, key, value, expireIn) {
166
+ const redisKey = this.redisConfigs[name]?.key + key;
167
+ expireIn = expireIn ?? this.redisConfigs[name]?.expireIn ?? -1;
168
+ if (!this.isConnectionAvailable()) {
169
+ return;
170
+ }
171
+ try {
172
+ await this.redis.lpush(redisKey, JSON.stringify(value));
173
+ if (expireIn > 0) {
174
+ await this.expire(redisKey, expireIn);
175
+ }
176
+ }
177
+ catch (error) {
178
+ if (error instanceof Error && error.message.includes('closed')) {
179
+ if (this.shouldLogClosedError()) {
180
+ if (isProduction()) {
181
+ this.logger.warn('Redis connection closed, pushDataToList failed');
182
+ }
183
+ else {
184
+ this.logger.debug('Redis connection closed, pushDataToList failed', { error });
185
+ }
186
+ }
187
+ }
188
+ else {
189
+ if (isProduction()) {
190
+ this.logger.error('Redis pushDataToList error:', { error });
191
+ }
192
+ else {
193
+ this.logger.debug('Redis pushDataToList error:', { error });
194
+ }
195
+ }
196
+ }
197
+ }
198
+ async pushDatasToList(name, key, values, expireIn) {
199
+ const redisKey = this.redisConfigs[name]?.key + key;
200
+ const stringifiedValues = values.map((v) => JSON.stringify(v));
201
+ expireIn = expireIn ?? this.redisConfigs[name]?.expireIn ?? -1;
202
+ if (!this.isConnectionAvailable()) {
203
+ return;
204
+ }
205
+ try {
206
+ await this.redis.lpush(redisKey, ...stringifiedValues);
207
+ if (expireIn > 0) {
208
+ await this.expire(redisKey, expireIn);
209
+ }
210
+ }
211
+ catch (error) {
212
+ if (error instanceof Error && error.message.includes('closed')) {
213
+ if (this.shouldLogClosedError()) {
214
+ if (isProduction()) {
215
+ this.logger.warn('Redis connection closed, pushDatasToList failed');
216
+ }
217
+ else {
218
+ this.logger.debug('Redis connection closed, pushDatasToList failed', { error });
219
+ }
220
+ }
221
+ }
222
+ else {
223
+ if (isProduction()) {
224
+ this.logger.error('Redis pushDatasToList error:', { error });
225
+ }
226
+ else {
227
+ this.logger.debug('Redis pushDatasToList error:', { error });
228
+ }
229
+ }
230
+ }
231
+ }
232
+ async saveData(name, key, value, expireIn) {
233
+ const redisKey = this.redisConfigs[name]?.key + key;
234
+ expireIn = expireIn ?? this.redisConfigs[name]?.expireIn ?? -1;
235
+ return await this.set(redisKey, value, { EX: expireIn });
236
+ }
237
+ async getData(name, key) {
238
+ const redisKey = this.redisConfigs[name]?.key + key;
239
+ return await this.get(redisKey);
240
+ }
241
+ async deleteData(name, key) {
242
+ const redisKey = this.redisConfigs[name]?.key + key;
243
+ return await this.del(redisKey);
244
+ }
245
+ async incrData(name, key) {
246
+ const redisKey = this.redisConfigs[name]?.key + key;
247
+ return await this.incr(redisKey);
248
+ }
249
+ async decrData(name, key) {
250
+ const redisKey = this.redisConfigs[name]?.key + key;
251
+ return await this.decr(redisKey);
252
+ }
253
+ async incrbyData(name, key, increment) {
254
+ const redisKey = this.redisConfigs[name]?.key + key;
255
+ return await this.incrby(redisKey, increment);
256
+ }
257
+ async decrbyData(name, key, decrement) {
258
+ const redisKey = this.redisConfigs[name]?.key + key;
259
+ return await this.decrby(redisKey, decrement);
260
+ }
261
+ async saveKeyFirstFileId(key, fileId) {
262
+ return await this.saveData('fileSystemFildId', key, fileId);
263
+ }
264
+ async getKeyFirstFileId(key) {
265
+ return await this.getData('fileSystemFildId', key);
266
+ }
267
+ async saveQiniuUploadAuthKey(key) {
268
+ const traceID = (0, uuid_1.v4)();
269
+ await this.saveData('fileSystemCallbackAuth', key, traceID);
270
+ return traceID;
271
+ }
272
+ async checkQiniuUploadAuthKey(key, authToken) {
273
+ const token = await this.getData('fileSystemCallbackAuth', key);
274
+ return token === authToken;
275
+ }
276
+ async setShortCode(key, value) {
277
+ return await this.saveData('shortCode', key, value);
278
+ }
279
+ async getShortCode(key) {
280
+ return await this.getData('shortCode', key);
281
+ }
282
+ async saveProviderOauthNonce(name, state, nonce, expiresIn) {
283
+ const redisKey = 'dofe:oauth:' + name + ':nonce-' + state;
284
+ await this.set(redisKey, nonce, { EX: expiresIn });
285
+ }
286
+ async getProviderOauthNonce(name, state) {
287
+ const redisKey = 'dofe:oauth:' + name + ':nonce-' + state;
288
+ return await this.get(redisKey);
289
+ }
290
+ async deleteProviderOauthNonce(name, state) {
291
+ const redisKey = 'dofe:oauth:' + name + ':nonce-' + state;
292
+ await this.del(redisKey);
293
+ }
294
+ async saveProviderState(provider, state, expiresIn) {
295
+ const redisKey = 'dofe:oauth:' + provider + ':state';
296
+ await this.set(redisKey, state, { EX: expiresIn });
297
+ }
298
+ async getProviderState(provider, state) {
299
+ const redisKey = 'dofe:oauth:' + provider + ':state';
300
+ return await this.get(redisKey);
301
+ }
302
+ async deleteProviderState(provider) {
303
+ const redisKey = 'dofe:oauth:' + provider + ':state';
304
+ await this.del(redisKey);
305
+ }
306
+ async set(key, value, options) {
307
+ if (!this.redisClient || !this.isConnectionAvailable()) {
308
+ return null;
309
+ }
310
+ try {
311
+ const args = [
312
+ key,
313
+ typeof value === 'number' ? value.toString() : JSON.stringify(value),
314
+ ];
315
+ if (options?.EX && options.EX > 0) {
316
+ return await this.redisClient.set(key, args[1], 'EX', options.EX.toString());
317
+ }
318
+ else {
319
+ return await this.redisClient.set(key, args[1]);
320
+ }
321
+ }
322
+ catch (error) {
323
+ if (error instanceof Error && error.message.includes('closed')) {
324
+ if (this.shouldLogClosedError()) {
325
+ if (isProduction()) {
326
+ this.logger.warn('Redis connection closed, set operation failed');
327
+ }
328
+ else {
329
+ this.logger.debug('Redis connection closed, set operation failed', { error });
330
+ }
331
+ }
332
+ }
333
+ else {
334
+ if (isProduction()) {
335
+ this.logger.error('Redis set error:', { error });
336
+ }
337
+ else {
338
+ this.logger.debug('Redis set error:', { error });
339
+ }
340
+ }
341
+ return null;
342
+ }
343
+ }
344
+ async setNX(key, value, options) {
345
+ if (!this.redisClient || !this.isConnectionAvailable()) {
346
+ return null;
347
+ }
348
+ try {
349
+ const result = await this.redisClient.set(key, typeof value === 'number' ? value.toString() : JSON.stringify(value), 'NX', 'EX', options.EX);
350
+ return result;
351
+ }
352
+ catch (error) {
353
+ if (error instanceof Error && error.message.includes('closed')) {
354
+ if (this.shouldLogClosedError()) {
355
+ if (isProduction()) {
356
+ this.logger.warn('Redis connection closed, setNX operation failed');
357
+ }
358
+ else {
359
+ this.logger.debug('Redis connection closed, setNX operation failed', { error });
360
+ }
361
+ }
362
+ }
363
+ else {
364
+ if (isProduction()) {
365
+ this.logger.error('Redis setNX error:', { error });
366
+ }
367
+ else {
368
+ this.logger.debug('Redis setNX error:', { error });
369
+ }
370
+ }
371
+ return null;
372
+ }
373
+ }
374
+ async get(key) {
375
+ if (!this.redisClient || !this.isConnectionAvailable()) {
376
+ return null;
377
+ }
378
+ try {
379
+ const value = await this.redisClient.get(key);
380
+ if (value === null)
381
+ return null;
382
+ if (typeof value === 'number')
383
+ return value;
384
+ try {
385
+ return JSON.parse(value);
386
+ }
387
+ catch (e) {
388
+ return value;
389
+ }
390
+ }
391
+ catch (error) {
392
+ if (error instanceof Error && error.message.includes('closed')) {
393
+ if (this.shouldLogClosedError()) {
394
+ if (isProduction()) {
395
+ this.logger.warn('Redis connection closed, returning null');
396
+ }
397
+ else {
398
+ this.logger.debug('Redis connection closed, returning null', { error });
399
+ }
400
+ }
401
+ }
402
+ else {
403
+ if (isProduction()) {
404
+ this.logger.error('Redis get error:', { error });
405
+ }
406
+ else {
407
+ this.logger.debug('Redis get error:', { error });
408
+ }
409
+ }
410
+ return null;
411
+ }
412
+ }
413
+ async del(key) {
414
+ if (!this.redisClient || !this.isConnectionAvailable()) {
415
+ return null;
416
+ }
417
+ try {
418
+ return await this.redisClient.del(key);
419
+ }
420
+ catch (error) {
421
+ if (error instanceof Error && error.message.includes('closed')) {
422
+ if (this.shouldLogClosedError()) {
423
+ if (isProduction()) {
424
+ this.logger.warn('Redis connection closed, del operation failed');
425
+ }
426
+ else {
427
+ this.logger.debug('Redis connection closed, del operation failed', { error });
428
+ }
429
+ }
430
+ }
431
+ else {
432
+ if (isProduction()) {
433
+ this.logger.error('Redis del error:', { error });
434
+ }
435
+ else {
436
+ this.logger.debug('Redis del error:', { error });
437
+ }
438
+ }
439
+ return null;
440
+ }
441
+ }
442
+ async incr(key) {
443
+ if (!this.redisClient || !this.isConnectionAvailable()) {
444
+ return null;
445
+ }
446
+ try {
447
+ return await this.redisClient.incr(key);
448
+ }
449
+ catch (error) {
450
+ if (error instanceof Error && error.message.includes('closed')) {
451
+ if (this.shouldLogClosedError()) {
452
+ if (isProduction()) {
453
+ this.logger.warn('Redis connection closed, incr operation failed');
454
+ }
455
+ else {
456
+ this.logger.debug('Redis connection closed, incr operation failed', { error });
457
+ }
458
+ }
459
+ }
460
+ else {
461
+ if (isProduction()) {
462
+ this.logger.error('Redis incr error:', { error });
463
+ }
464
+ else {
465
+ this.logger.debug('Redis incr error:', { error });
466
+ }
467
+ }
468
+ return null;
469
+ }
470
+ }
471
+ async incrby(key, increment) {
472
+ if (!this.redisClient || !this.isConnectionAvailable()) {
473
+ return null;
474
+ }
475
+ try {
476
+ return await this.redisClient.incrby(key, increment);
477
+ }
478
+ catch (error) {
479
+ if (error instanceof Error && error.message.includes('closed')) {
480
+ if (this.shouldLogClosedError()) {
481
+ if (isProduction()) {
482
+ this.logger.warn('Redis connection closed, incrby operation failed');
483
+ }
484
+ else {
485
+ this.logger.debug('Redis connection closed, incrby operation failed', { error });
486
+ }
487
+ }
488
+ }
489
+ else {
490
+ if (isProduction()) {
491
+ this.logger.error('Redis incrby error:', { error });
492
+ }
493
+ else {
494
+ this.logger.debug('Redis incrby error:', { error });
495
+ }
496
+ }
497
+ return null;
498
+ }
499
+ }
500
+ async decr(key) {
501
+ if (!this.redisClient || !this.isConnectionAvailable()) {
502
+ return null;
503
+ }
504
+ try {
505
+ return await this.redisClient.decr(key);
506
+ }
507
+ catch (error) {
508
+ if (error instanceof Error && error.message.includes('closed')) {
509
+ if (this.shouldLogClosedError()) {
510
+ if (isProduction()) {
511
+ this.logger.warn('Redis connection closed, decr operation failed');
512
+ }
513
+ else {
514
+ this.logger.debug('Redis connection closed, decr operation failed', { error });
515
+ }
516
+ }
517
+ }
518
+ else {
519
+ if (isProduction()) {
520
+ this.logger.error('Redis decr error:', { error });
521
+ }
522
+ else {
523
+ this.logger.debug('Redis decr error:', { error });
524
+ }
525
+ }
526
+ return null;
527
+ }
528
+ }
529
+ async decrby(key, decrement) {
530
+ if (!this.redisClient || !this.isConnectionAvailable()) {
531
+ return null;
532
+ }
533
+ try {
534
+ return await this.redisClient.decrby(key, decrement);
535
+ }
536
+ catch (error) {
537
+ if (error instanceof Error && error.message.includes('closed')) {
538
+ if (this.shouldLogClosedError()) {
539
+ if (isProduction()) {
540
+ this.logger.warn('Redis connection closed, decrby operation failed');
541
+ }
542
+ else {
543
+ this.logger.debug('Redis connection closed, decrby operation failed', { error });
544
+ }
545
+ }
546
+ }
547
+ else {
548
+ if (isProduction()) {
549
+ this.logger.error('Redis decrby error:', { error });
550
+ }
551
+ else {
552
+ this.logger.debug('Redis decrby error:', { error });
553
+ }
554
+ }
555
+ return null;
556
+ }
557
+ }
558
+ async expire(key, seconds) {
559
+ if (!this.redisClient || !this.isConnectionAvailable()) {
560
+ return null;
561
+ }
562
+ try {
563
+ return await this.redisClient.expire(key, seconds);
564
+ }
565
+ catch (error) {
566
+ if (error instanceof Error && error.message.includes('closed')) {
567
+ if (this.shouldLogClosedError()) {
568
+ if (isProduction()) {
569
+ this.logger.warn('Redis connection closed, expire operation failed');
570
+ }
571
+ else {
572
+ this.logger.debug('Redis connection closed, expire operation failed', { error });
573
+ }
574
+ }
575
+ }
576
+ else {
577
+ if (isProduction()) {
578
+ this.logger.error('Redis expire error:', { error });
579
+ }
580
+ else {
581
+ this.logger.debug('Redis expire error:', { error });
582
+ }
583
+ }
584
+ return null;
585
+ }
586
+ }
587
+ async ttl(key) {
588
+ if (!this.redisClient || !this.isConnectionAvailable()) {
589
+ return null;
590
+ }
591
+ try {
592
+ return await this.redisClient.ttl(key);
593
+ }
594
+ catch (error) {
595
+ if (error instanceof Error && error.message.includes('closed')) {
596
+ if (this.shouldLogClosedError()) {
597
+ if (isProduction()) {
598
+ this.logger.warn('Redis connection closed, ttl operation failed');
599
+ }
600
+ else {
601
+ this.logger.debug('Redis connection closed, ttl operation failed', { error });
602
+ }
603
+ }
604
+ }
605
+ else {
606
+ if (isProduction()) {
607
+ this.logger.error('Redis ttl error:', { error });
608
+ }
609
+ else {
610
+ this.logger.debug('Redis ttl error:', { error });
611
+ }
612
+ }
613
+ return null;
614
+ }
615
+ }
616
+ async exists(key) {
617
+ if (!this.redisClient || !this.isConnectionAvailable()) {
618
+ return null;
619
+ }
620
+ try {
621
+ return await this.redisClient.exists(key);
622
+ }
623
+ catch (error) {
624
+ if (error instanceof Error && error.message.includes('closed')) {
625
+ if (this.shouldLogClosedError()) {
626
+ if (isProduction()) {
627
+ this.logger.warn('Redis connection closed, exists operation failed');
628
+ }
629
+ else {
630
+ this.logger.debug('Redis connection closed, exists operation failed', { error });
631
+ }
632
+ }
633
+ }
634
+ else {
635
+ if (isProduction()) {
636
+ this.logger.error('Redis exists error:', { error });
637
+ }
638
+ else {
639
+ this.logger.debug('Redis exists error:', { error });
640
+ }
641
+ }
642
+ return null;
643
+ }
644
+ }
645
+ async deleteByPattern(pattern) {
646
+ if (!this.redisClient || !this.isConnectionAvailable()) {
647
+ return 0;
648
+ }
649
+ try {
650
+ let cursor = '0';
651
+ let deletedCount = 0;
652
+ const batchSize = 100;
653
+ do {
654
+ const [newCursor, keys] = await this.redisClient.scan(cursor, 'MATCH', pattern, 'COUNT', batchSize);
655
+ cursor = newCursor;
656
+ if (keys.length > 0) {
657
+ const deleted = await this.redisClient.del(...keys);
658
+ deletedCount += deleted;
659
+ }
660
+ } while (cursor !== '0');
661
+ if (deletedCount > 0) {
662
+ this.logger.info(`Deleted ${deletedCount} keys matching pattern: ${pattern}`);
663
+ }
664
+ return deletedCount;
665
+ }
666
+ catch (error) {
667
+ if (error instanceof Error && error.message.includes('closed')) {
668
+ if (this.shouldLogClosedError()) {
669
+ if (isProduction()) {
670
+ this.logger.warn('Redis connection closed, deleteByPattern operation failed');
671
+ }
672
+ else {
673
+ this.logger.debug('Redis connection closed, deleteByPattern operation failed', { error });
674
+ }
675
+ }
676
+ }
677
+ else {
678
+ if (isProduction()) {
679
+ this.logger.error('Redis deleteByPattern error:', { error, pattern });
680
+ }
681
+ else {
682
+ this.logger.debug('Redis deleteByPattern error:', { error, pattern });
683
+ }
684
+ }
685
+ return 0;
686
+ }
687
+ }
688
+ async pipeline(commands) {
689
+ if (!this.redisClient || !this.isConnectionAvailable()) {
690
+ return [];
691
+ }
692
+ try {
693
+ const pipeline = this.redisClient.pipeline();
694
+ commands(pipeline);
695
+ const results = await pipeline.exec();
696
+ if (!results) {
697
+ return [];
698
+ }
699
+ return results.map(([error, result]) => {
700
+ if (error) {
701
+ this.logger.error('Pipeline command error:', { error });
702
+ return null;
703
+ }
704
+ return result;
705
+ });
706
+ }
707
+ catch (error) {
708
+ if (isProduction()) {
709
+ this.logger.error('Redis pipeline error:', { error });
710
+ }
711
+ else {
712
+ this.logger.debug('Redis pipeline error:', { error });
713
+ }
714
+ return [];
715
+ }
716
+ }
717
+ async pipelineSave(items) {
718
+ if (!this.redisClient || !this.isConnectionAvailable() || items.length === 0) {
719
+ return;
720
+ }
721
+ try {
722
+ const pipeline = this.redisClient.pipeline();
723
+ for (const item of items) {
724
+ const redisKey = this.redisConfigs[item.name]?.key + item.key;
725
+ const expireIn = item.expireIn ?? this.redisConfigs[item.name]?.expireIn ?? -1;
726
+ const value = typeof item.value === 'number'
727
+ ? item.value.toString()
728
+ : JSON.stringify(item.value);
729
+ if (expireIn > 0) {
730
+ pipeline.set(redisKey, value, 'EX', expireIn);
731
+ }
732
+ else {
733
+ pipeline.set(redisKey, value);
734
+ }
735
+ }
736
+ await pipeline.exec();
737
+ }
738
+ catch (error) {
739
+ if (isProduction()) {
740
+ this.logger.error('Redis pipelineSave error:', { error });
741
+ }
742
+ else {
743
+ this.logger.debug('Redis pipelineSave error:', { error });
744
+ }
745
+ }
746
+ }
747
+ async pipelineGet(items) {
748
+ const result = new Map();
749
+ if (!this.redisClient || !this.isConnectionAvailable() || items.length === 0) {
750
+ return result;
751
+ }
752
+ try {
753
+ const pipeline = this.redisClient.pipeline();
754
+ const keys = [];
755
+ for (const item of items) {
756
+ const redisKey = this.redisConfigs[item.name]?.key + item.key;
757
+ keys.push(`${item.name}:${item.key}`);
758
+ pipeline.get(redisKey);
759
+ }
760
+ const results = await pipeline.exec();
761
+ if (!results) {
762
+ return result;
763
+ }
764
+ results.forEach(([error, value], index) => {
765
+ if (error) {
766
+ this.logger.debug(`Pipeline get error for key ${keys[index]}:`, { error });
767
+ return;
768
+ }
769
+ if (value === null)
770
+ return;
771
+ try {
772
+ result.set(keys[index], JSON.parse(value));
773
+ }
774
+ catch {
775
+ result.set(keys[index], value);
776
+ }
777
+ });
778
+ return result;
779
+ }
780
+ catch (error) {
781
+ if (isProduction()) {
782
+ this.logger.error('Redis pipelineGet error:', { error });
783
+ }
784
+ else {
785
+ this.logger.debug('Redis pipelineGet error:', { error });
786
+ }
787
+ return result;
788
+ }
789
+ }
790
+ };
791
+ exports.RedisService = RedisService;
792
+ exports.RedisService = RedisService = __decorate([
793
+ (0, common_1.Injectable)(),
794
+ __param(1, (0, common_1.Inject)(redis_dto_1.REDIS_AUTH)),
795
+ __param(2, (0, common_1.Optional)()),
796
+ __param(2, (0, common_1.Inject)('WINSTON_LOGGER')),
797
+ __metadata("design:paramtypes", [config_1.ConfigService,
798
+ ioredis_1.Redis, Function])
799
+ ], RedisService);
800
+ //# sourceMappingURL=redis.service.js.map