@nest-omni/core 3.1.1-11 → 3.1.1-13

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 (81) hide show
  1. package/cache/cache-metrics.service.d.ts +83 -0
  2. package/cache/cache-metrics.service.js +298 -0
  3. package/cache/cache-serialization.service.d.ts +29 -0
  4. package/cache/cache-serialization.service.js +217 -0
  5. package/cache/cache.health.d.ts +35 -0
  6. package/cache/cache.health.js +193 -0
  7. package/cache/cache.module.d.ts +24 -0
  8. package/cache/cache.module.js +105 -0
  9. package/cache/cache.service.d.ts +35 -0
  10. package/cache/cache.service.js +280 -0
  11. package/cache/cache.warmup.service.d.ts +34 -0
  12. package/cache/cache.warmup.service.js +199 -0
  13. package/cache/decorators/cache-evict.decorator.d.ts +2 -0
  14. package/cache/decorators/cache-evict.decorator.js +72 -0
  15. package/cache/decorators/cache-put.decorator.d.ts +2 -0
  16. package/cache/decorators/cache-put.decorator.js +48 -0
  17. package/cache/decorators/cacheable.decorator.d.ts +4 -0
  18. package/cache/decorators/cacheable.decorator.js +68 -0
  19. package/cache/decorators/index.d.ts +3 -0
  20. package/cache/decorators/index.js +11 -0
  21. package/cache/dependencies/callback.dependency.d.ts +11 -0
  22. package/cache/dependencies/callback.dependency.js +92 -0
  23. package/cache/dependencies/chain.dependency.d.ts +20 -0
  24. package/cache/dependencies/chain.dependency.js +113 -0
  25. package/cache/dependencies/db.dependency.d.ts +15 -0
  26. package/cache/dependencies/db.dependency.js +71 -0
  27. package/cache/dependencies/file.dependency.d.ts +17 -0
  28. package/cache/dependencies/file.dependency.js +63 -0
  29. package/cache/dependencies/index.d.ts +6 -0
  30. package/cache/dependencies/index.js +22 -0
  31. package/cache/dependencies/tag.dependency.d.ts +16 -0
  32. package/cache/dependencies/tag.dependency.js +75 -0
  33. package/cache/dependencies/time.dependency.d.ts +19 -0
  34. package/cache/dependencies/time.dependency.js +71 -0
  35. package/cache/examples/quick-start.d.ts +5 -0
  36. package/cache/examples/quick-start.js +341 -0
  37. package/cache/index.d.ts +14 -0
  38. package/cache/index.js +41 -0
  39. package/cache/interfaces/cache-dependency.interface.d.ts +11 -0
  40. package/cache/interfaces/cache-dependency.interface.js +2 -0
  41. package/cache/interfaces/cache-options.interface.d.ts +32 -0
  42. package/cache/interfaces/cache-options.interface.js +9 -0
  43. package/cache/interfaces/cache-provider.interface.d.ts +28 -0
  44. package/cache/interfaces/cache-provider.interface.js +2 -0
  45. package/cache/interfaces/index.d.ts +3 -0
  46. package/cache/interfaces/index.js +19 -0
  47. package/cache/providers/base-cache.provider.d.ts +16 -0
  48. package/cache/providers/base-cache.provider.js +32 -0
  49. package/cache/providers/cls-cache.provider.d.ts +16 -0
  50. package/cache/providers/cls-cache.provider.js +140 -0
  51. package/cache/providers/index.d.ts +4 -0
  52. package/cache/providers/index.js +23 -0
  53. package/cache/providers/memory-cache.provider.d.ts +23 -0
  54. package/cache/providers/memory-cache.provider.js +130 -0
  55. package/cache/providers/redis-cache.provider.d.ts +23 -0
  56. package/cache/providers/redis-cache.provider.js +215 -0
  57. package/cache/utils/dependency-manager.util.d.ts +15 -0
  58. package/cache/utils/dependency-manager.util.js +141 -0
  59. package/cache/utils/index.d.ts +2 -0
  60. package/cache/utils/index.js +18 -0
  61. package/cache/utils/key-generator.util.d.ts +13 -0
  62. package/cache/utils/key-generator.util.js +74 -0
  63. package/index.d.ts +1 -0
  64. package/index.js +1 -0
  65. package/package.json +4 -17
  66. package/redis-lock/index.d.ts +4 -0
  67. package/redis-lock/index.js +13 -0
  68. package/{setup → redis-lock}/redis-lock.decorator.d.ts +3 -0
  69. package/{setup → redis-lock}/redis-lock.decorator.js +25 -14
  70. package/redis-lock/redis-lock.examples.d.ts +13 -0
  71. package/redis-lock/redis-lock.examples.js +159 -0
  72. package/redis-lock/redis-lock.module.d.ts +23 -0
  73. package/redis-lock/redis-lock.module.js +117 -0
  74. package/{setup → redis-lock}/redis-lock.service.d.ts +9 -21
  75. package/{setup → redis-lock}/redis-lock.service.js +29 -103
  76. package/setup/index.d.ts +1 -2
  77. package/setup/index.js +1 -2
  78. package/setup/schedule.decorator.js +4 -4
  79. package/shared/serviceRegistryModule.js +63 -4
  80. package/shared/services/api-config.service.d.ts +0 -5
  81. package/shared/services/api-config.service.js +3 -27
@@ -0,0 +1,193 @@
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 __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
12
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
13
+ return new (P || (P = Promise))(function (resolve, reject) {
14
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
15
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
16
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
17
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
18
+ });
19
+ };
20
+ var CacheHealthChecker_1;
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.CacheHealthChecker = void 0;
23
+ const common_1 = require("@nestjs/common");
24
+ const cache_service_1 = require("./cache.service");
25
+ const cache_options_interface_1 = require("./interfaces/cache-options.interface");
26
+ let CacheHealthChecker = CacheHealthChecker_1 = class CacheHealthChecker {
27
+ constructor(cacheService) {
28
+ this.cacheService = cacheService;
29
+ this.logger = new common_1.Logger(CacheHealthChecker_1.name);
30
+ }
31
+ checkHealth() {
32
+ return __awaiter(this, void 0, void 0, function* () {
33
+ const startTime = Date.now();
34
+ const results = {
35
+ cls: yield this.checkClsHealth(),
36
+ memory: yield this.checkMemoryHealth(),
37
+ redis: yield this.checkRedisHealth(),
38
+ };
39
+ const overallLatency = Date.now() - startTime;
40
+ const layerStatuses = Object.values(results);
41
+ const healthyCount = layerStatuses.filter((layer) => layer.available).length;
42
+ const totalCount = layerStatuses.length;
43
+ let status;
44
+ if (healthyCount === totalCount) {
45
+ status = 'healthy';
46
+ }
47
+ else if (healthyCount > 0) {
48
+ status = 'degraded';
49
+ }
50
+ else {
51
+ status = 'unhealthy';
52
+ }
53
+ return {
54
+ status,
55
+ layers: results,
56
+ timestamp: new Date(),
57
+ overallLatency,
58
+ };
59
+ });
60
+ }
61
+ getDetailedStats() {
62
+ return __awaiter(this, void 0, void 0, function* () {
63
+ const stats = this.cacheService.getStats();
64
+ const health = yield this.checkHealth();
65
+ return {
66
+ statistics: stats,
67
+ health,
68
+ recommendations: this.generateRecommendations(health, stats),
69
+ };
70
+ });
71
+ }
72
+ checkClsHealth() {
73
+ return __awaiter(this, void 0, void 0, function* () {
74
+ const startTime = Date.now();
75
+ try {
76
+ yield this.cacheService.set('health:cls:test', 'test-value', {
77
+ layers: [cache_options_interface_1.CacheLayer.CLS],
78
+ });
79
+ const result = yield this.cacheService.get('health:cls:test', {
80
+ layers: [cache_options_interface_1.CacheLayer.CLS],
81
+ });
82
+ const latency = Date.now() - startTime;
83
+ if (result === 'test-value') {
84
+ return { available: true, latency };
85
+ }
86
+ else {
87
+ return {
88
+ available: false,
89
+ latency,
90
+ error: 'CLS cache not returning expected value',
91
+ };
92
+ }
93
+ }
94
+ catch (error) {
95
+ const latency = Date.now() - startTime;
96
+ return {
97
+ available: false,
98
+ latency,
99
+ error: error instanceof Error ? error.message : String(error),
100
+ };
101
+ }
102
+ });
103
+ }
104
+ checkMemoryHealth() {
105
+ return __awaiter(this, void 0, void 0, function* () {
106
+ const startTime = Date.now();
107
+ try {
108
+ yield this.cacheService.set('health:memory:test', 'test-value', {
109
+ layers: [cache_options_interface_1.CacheLayer.MEMORY],
110
+ });
111
+ const result = yield this.cacheService.get('health:memory:test', {
112
+ layers: [cache_options_interface_1.CacheLayer.MEMORY],
113
+ });
114
+ const latency = Date.now() - startTime;
115
+ if (result === 'test-value') {
116
+ const stats = this.cacheService.getStats();
117
+ return { available: true, latency, size: stats.totalSets };
118
+ }
119
+ else {
120
+ return {
121
+ available: false,
122
+ latency,
123
+ error: 'Memory cache not returning expected value',
124
+ };
125
+ }
126
+ }
127
+ catch (error) {
128
+ const latency = Date.now() - startTime;
129
+ return {
130
+ available: false,
131
+ latency,
132
+ error: error instanceof Error ? error.message : String(error),
133
+ };
134
+ }
135
+ });
136
+ }
137
+ checkRedisHealth() {
138
+ return __awaiter(this, void 0, void 0, function* () {
139
+ const startTime = Date.now();
140
+ try {
141
+ yield this.cacheService.set('health:redis:test', 'test-value', {
142
+ layers: [cache_options_interface_1.CacheLayer.REDIS],
143
+ });
144
+ const result = yield this.cacheService.get('health:redis:test', {
145
+ layers: [cache_options_interface_1.CacheLayer.REDIS],
146
+ });
147
+ const latency = Date.now() - startTime;
148
+ if (result === 'test-value') {
149
+ return { available: true, latency };
150
+ }
151
+ else {
152
+ return {
153
+ available: false,
154
+ latency,
155
+ error: 'Redis not returning expected value',
156
+ };
157
+ }
158
+ }
159
+ catch (error) {
160
+ const latency = Date.now() - startTime;
161
+ return {
162
+ available: false,
163
+ latency,
164
+ error: error instanceof Error ? error.message : String(error),
165
+ };
166
+ }
167
+ });
168
+ }
169
+ generateRecommendations(health, stats) {
170
+ const recommendations = [];
171
+ if (!health.layers.redis.available) {
172
+ recommendations.push('Redis is unavailable. Check Redis connection and configuration.');
173
+ }
174
+ if (!health.layers.memory.available) {
175
+ recommendations.push('Memory cache is unavailable. This may indicate memory pressure.');
176
+ }
177
+ if (health.overallLatency > 100) {
178
+ recommendations.push('Cache latency is high. Consider optimizing cache operations or increasing resources.');
179
+ }
180
+ if (stats.hitRate < 0.5) {
181
+ recommendations.push('Cache hit rate is low. Review cache TTL and key patterns.');
182
+ }
183
+ if (stats.totalSets > 10000 && stats.hits / stats.totalGets < 0.8) {
184
+ recommendations.push('High cache churn detected. Consider longer TTL or cache warming.');
185
+ }
186
+ return recommendations;
187
+ }
188
+ };
189
+ exports.CacheHealthChecker = CacheHealthChecker;
190
+ exports.CacheHealthChecker = CacheHealthChecker = CacheHealthChecker_1 = __decorate([
191
+ (0, common_1.Injectable)(),
192
+ __metadata("design:paramtypes", [cache_service_1.CacheService])
193
+ ], CacheHealthChecker);
@@ -0,0 +1,24 @@
1
+ import { DynamicModule, OnModuleInit } from '@nestjs/common';
2
+ import type { DataSource } from 'typeorm';
3
+ import type { Redis } from 'ioredis';
4
+ import { CacheService } from './cache.service';
5
+ export declare const CACHE_SERVICE: unique symbol;
6
+ export interface CacheModuleOptions {
7
+ isGlobal?: boolean;
8
+ redisClient?: Redis;
9
+ dataSource?: DataSource;
10
+ memoryTtl?: number;
11
+ memoryNamespace?: string;
12
+ }
13
+ export declare class CacheModule implements OnModuleInit {
14
+ private readonly cacheService;
15
+ constructor(cacheService: CacheService);
16
+ static forRoot(options?: CacheModuleOptions): DynamicModule;
17
+ static forRootAsync(options: {
18
+ imports?: any[];
19
+ inject?: any[];
20
+ useFactory: (...args: any[]) => Promise<CacheModuleOptions> | CacheModuleOptions;
21
+ isGlobal?: boolean;
22
+ }): DynamicModule;
23
+ onModuleInit(): void;
24
+ }
@@ -0,0 +1,105 @@
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 CacheModule_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.CacheModule = exports.CACHE_SERVICE = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const cache_service_1 = require("./cache.service");
16
+ const dependencies_1 = require("./dependencies");
17
+ const decorators_1 = require("./decorators");
18
+ const providers_1 = require("./providers");
19
+ exports.CACHE_SERVICE = Symbol('CACHE_SERVICE');
20
+ let CacheModule = CacheModule_1 = class CacheModule {
21
+ constructor(cacheService) {
22
+ this.cacheService = cacheService;
23
+ }
24
+ static forRoot(options = {}) {
25
+ const { isGlobal = true, redisClient, dataSource, memoryTtl, memoryNamespace, } = options;
26
+ if (dataSource) {
27
+ dependencies_1.DbDependency.setDataSource(dataSource);
28
+ }
29
+ return {
30
+ module: CacheModule_1,
31
+ global: isGlobal,
32
+ providers: [
33
+ providers_1.ClsCacheProvider,
34
+ {
35
+ provide: providers_1.MemoryCacheProvider,
36
+ useValue: new providers_1.MemoryCacheProvider({
37
+ ttl: memoryTtl,
38
+ namespace: memoryNamespace,
39
+ }),
40
+ },
41
+ ...(redisClient
42
+ ? [
43
+ {
44
+ provide: providers_1.REDIS_CLIENT,
45
+ useValue: redisClient,
46
+ },
47
+ ]
48
+ : []),
49
+ providers_1.RedisCacheProvider,
50
+ {
51
+ provide: exports.CACHE_SERVICE,
52
+ useClass: cache_service_1.CacheService,
53
+ },
54
+ cache_service_1.CacheService,
55
+ ],
56
+ exports: [cache_service_1.CacheService, exports.CACHE_SERVICE],
57
+ };
58
+ }
59
+ static forRootAsync(options) {
60
+ var _a;
61
+ return {
62
+ module: CacheModule_1,
63
+ global: (_a = options.isGlobal) !== null && _a !== void 0 ? _a : true,
64
+ imports: options.imports || [],
65
+ providers: [
66
+ {
67
+ provide: 'CACHE_MODULE_OPTIONS',
68
+ useFactory: options.useFactory,
69
+ inject: options.inject || [],
70
+ },
71
+ providers_1.ClsCacheProvider,
72
+ {
73
+ provide: providers_1.MemoryCacheProvider,
74
+ useFactory: (moduleOptions) => {
75
+ if (moduleOptions.dataSource) {
76
+ dependencies_1.DbDependency.setDataSource(moduleOptions.dataSource);
77
+ }
78
+ return new providers_1.MemoryCacheProvider({
79
+ ttl: moduleOptions.memoryTtl,
80
+ namespace: moduleOptions.memoryNamespace,
81
+ });
82
+ },
83
+ inject: ['CACHE_MODULE_OPTIONS'],
84
+ },
85
+ {
86
+ provide: providers_1.REDIS_CLIENT,
87
+ useFactory: (moduleOptions) => moduleOptions.redisClient,
88
+ inject: ['CACHE_MODULE_OPTIONS'],
89
+ },
90
+ providers_1.RedisCacheProvider,
91
+ cache_service_1.CacheService,
92
+ ],
93
+ exports: [cache_service_1.CacheService],
94
+ };
95
+ }
96
+ onModuleInit() {
97
+ (0, decorators_1.setCacheService)(this.cacheService);
98
+ }
99
+ };
100
+ exports.CacheModule = CacheModule;
101
+ exports.CacheModule = CacheModule = CacheModule_1 = __decorate([
102
+ (0, common_1.Global)(),
103
+ (0, common_1.Module)({}),
104
+ __metadata("design:paramtypes", [cache_service_1.CacheService])
105
+ ], CacheModule);
@@ -0,0 +1,35 @@
1
+ import type { CacheOptions, CacheStats } from './interfaces';
2
+ import { CacheLayer } from './interfaces';
3
+ import { ClsCacheProvider, MemoryCacheProvider, RedisCacheProvider } from './providers';
4
+ export declare class CacheService {
5
+ private readonly clsProvider;
6
+ private readonly memoryProvider;
7
+ private readonly redisProvider;
8
+ private readonly logger;
9
+ private readonly providers;
10
+ private readonly stats;
11
+ constructor(clsProvider: ClsCacheProvider, memoryProvider: MemoryCacheProvider, redisProvider: RedisCacheProvider);
12
+ getOrSet<T>(key: string, factory: () => Promise<T>, options?: CacheOptions): Promise<T>;
13
+ get<T>(key: string, options?: CacheOptions): Promise<T | null>;
14
+ set<T>(key: string, value: T, options?: CacheOptions | number): Promise<void>;
15
+ del(key: string | string[], layers?: CacheLayer[]): Promise<void>;
16
+ deletePattern(pattern: string, layers?: CacheLayer[]): Promise<void>;
17
+ clear(layers?: CacheLayer[]): Promise<void>;
18
+ invalidateTags(tags: string[]): Promise<void>;
19
+ mget<T>(keys: string[], options?: CacheOptions): Promise<(T | null)[]>;
20
+ mset(items: Array<{
21
+ key: string;
22
+ value: any;
23
+ }>, options?: CacheOptions): Promise<void>;
24
+ getStats(): CacheStats;
25
+ resetStats(): void;
26
+ private setWithOptions;
27
+ private resolveLayers;
28
+ private getDefaultLayers;
29
+ private buildKey;
30
+ private backfillUpperLayers;
31
+ private recordHit;
32
+ private recordMiss;
33
+ private updateLayerHitRate;
34
+ private initializeStats;
35
+ }
@@ -0,0 +1,280 @@
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 __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
12
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
13
+ return new (P || (P = Promise))(function (resolve, reject) {
14
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
15
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
16
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
17
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
18
+ });
19
+ };
20
+ var CacheService_1;
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.CacheService = void 0;
23
+ const common_1 = require("@nestjs/common");
24
+ const dependencies_1 = require("./dependencies");
25
+ const interfaces_1 = require("./interfaces");
26
+ const providers_1 = require("./providers");
27
+ const utils_1 = require("./utils");
28
+ let CacheService = CacheService_1 = class CacheService {
29
+ constructor(clsProvider, memoryProvider, redisProvider) {
30
+ this.clsProvider = clsProvider;
31
+ this.memoryProvider = memoryProvider;
32
+ this.redisProvider = redisProvider;
33
+ this.logger = new common_1.Logger(CacheService_1.name);
34
+ this.providers = new Map();
35
+ this.stats = {
36
+ totalGets: 0,
37
+ hits: 0,
38
+ misses: 0,
39
+ hitRate: 0,
40
+ byLayer: {},
41
+ totalSets: 0,
42
+ totalDeletes: 0,
43
+ totalClears: 0,
44
+ };
45
+ this.providers.set(interfaces_1.CacheLayer.CLS, clsProvider);
46
+ this.providers.set(interfaces_1.CacheLayer.MEMORY, memoryProvider);
47
+ this.providers.set(interfaces_1.CacheLayer.REDIS, redisProvider);
48
+ this.initializeStats();
49
+ }
50
+ getOrSet(key, factory, options) {
51
+ return __awaiter(this, void 0, void 0, function* () {
52
+ const cached = yield this.get(key, options);
53
+ if (cached !== null) {
54
+ return cached;
55
+ }
56
+ const value = yield factory();
57
+ yield this.set(key, value, options);
58
+ return value;
59
+ });
60
+ }
61
+ get(key, options) {
62
+ return __awaiter(this, void 0, void 0, function* () {
63
+ this.stats.totalGets++;
64
+ const layers = this.resolveLayers(options === null || options === void 0 ? void 0 : options.layers);
65
+ const fullKey = this.buildKey(key, options === null || options === void 0 ? void 0 : options.namespace);
66
+ for (let i = 0; i < layers.length; i++) {
67
+ const layer = layers[i];
68
+ const provider = this.providers.get(layer);
69
+ if (!provider) {
70
+ continue;
71
+ }
72
+ try {
73
+ const wrapped = yield provider.get(fullKey);
74
+ if (wrapped !== null) {
75
+ const value = yield utils_1.DependencyManager.unwrapAndValidate(wrapped, options === null || options === void 0 ? void 0 : options.dependencies);
76
+ if (value !== null) {
77
+ this.recordHit(layer);
78
+ if ((options === null || options === void 0 ? void 0 : options.backfill) !== false && i > 0) {
79
+ yield this.backfillUpperLayers(fullKey, wrapped, layers.slice(0, i), options === null || options === void 0 ? void 0 : options.ttl);
80
+ }
81
+ return value;
82
+ }
83
+ yield provider.delete(fullKey);
84
+ }
85
+ }
86
+ catch (error) {
87
+ this.logger.warn(`Failed to get from ${layer} cache: ${error instanceof Error ? error.message : String(error)}`);
88
+ }
89
+ }
90
+ this.recordMiss();
91
+ return null;
92
+ });
93
+ }
94
+ set(key, value, options) {
95
+ return __awaiter(this, void 0, void 0, function* () {
96
+ if (typeof options === 'number') {
97
+ return this.setWithOptions(key, value, { ttl: options });
98
+ }
99
+ else {
100
+ return this.setWithOptions(key, value, options);
101
+ }
102
+ });
103
+ }
104
+ del(key, layers) {
105
+ return __awaiter(this, void 0, void 0, function* () {
106
+ this.stats.totalDeletes++;
107
+ const targetLayers = layers || this.getDefaultLayers();
108
+ const keys = Array.isArray(key) ? key : [key];
109
+ const promises = targetLayers.map((layer) => __awaiter(this, void 0, void 0, function* () {
110
+ const provider = this.providers.get(layer);
111
+ if (!provider) {
112
+ return;
113
+ }
114
+ try {
115
+ yield provider.delete(keys);
116
+ }
117
+ catch (error) {
118
+ this.logger.warn(`Failed to delete from ${layer} cache: ${error instanceof Error ? error.message : String(error)}`);
119
+ }
120
+ }));
121
+ yield Promise.all(promises);
122
+ });
123
+ }
124
+ deletePattern(pattern, layers) {
125
+ return __awaiter(this, void 0, void 0, function* () {
126
+ const targetLayers = layers || [interfaces_1.CacheLayer.MEMORY, interfaces_1.CacheLayer.REDIS];
127
+ const promises = targetLayers.map((layer) => __awaiter(this, void 0, void 0, function* () {
128
+ const provider = this.providers.get(layer);
129
+ if (!provider || !provider.deletePattern) {
130
+ return;
131
+ }
132
+ try {
133
+ yield provider.deletePattern(pattern);
134
+ }
135
+ catch (error) {
136
+ this.logger.warn(`Failed to delete pattern from ${layer} cache: ${error instanceof Error ? error.message : String(error)}`);
137
+ }
138
+ }));
139
+ yield Promise.all(promises);
140
+ });
141
+ }
142
+ clear(layers) {
143
+ return __awaiter(this, void 0, void 0, function* () {
144
+ this.stats.totalClears++;
145
+ const targetLayers = layers || this.getDefaultLayers();
146
+ const promises = targetLayers.map((layer) => __awaiter(this, void 0, void 0, function* () {
147
+ const provider = this.providers.get(layer);
148
+ if (!provider) {
149
+ return;
150
+ }
151
+ try {
152
+ yield provider.clear();
153
+ }
154
+ catch (error) {
155
+ this.logger.warn(`Failed to clear ${layer} cache: ${error instanceof Error ? error.message : String(error)}`);
156
+ }
157
+ }));
158
+ yield Promise.all(promises);
159
+ });
160
+ }
161
+ invalidateTags(tags) {
162
+ return __awaiter(this, void 0, void 0, function* () {
163
+ dependencies_1.TagDependency.invalidateTags(tags);
164
+ this.logger.debug(`Invalidated tags: ${tags.join(', ')}`);
165
+ });
166
+ }
167
+ mget(keys, options) {
168
+ return __awaiter(this, void 0, void 0, function* () {
169
+ const promises = keys.map((key) => this.get(key, options));
170
+ return Promise.all(promises);
171
+ });
172
+ }
173
+ mset(items, options) {
174
+ return __awaiter(this, void 0, void 0, function* () {
175
+ const promises = items.map((item) => this.set(item.key, item.value, options));
176
+ yield Promise.all(promises);
177
+ });
178
+ }
179
+ getStats() {
180
+ return Object.assign(Object.assign({}, this.stats), { hitRate: this.stats.totalGets > 0 ? this.stats.hits / this.stats.totalGets : 0 });
181
+ }
182
+ resetStats() {
183
+ this.stats.totalGets = 0;
184
+ this.stats.hits = 0;
185
+ this.stats.misses = 0;
186
+ this.stats.hitRate = 0;
187
+ this.stats.totalSets = 0;
188
+ this.stats.totalDeletes = 0;
189
+ this.stats.totalClears = 0;
190
+ this.initializeStats();
191
+ }
192
+ setWithOptions(key, value, options) {
193
+ return __awaiter(this, void 0, void 0, function* () {
194
+ this.stats.totalSets++;
195
+ if ((options === null || options === void 0 ? void 0 : options.condition) && !(yield Promise.resolve(options.condition()))) {
196
+ return;
197
+ }
198
+ const layers = this.resolveLayers(options === null || options === void 0 ? void 0 : options.layers);
199
+ const fullKey = this.buildKey(key, options === null || options === void 0 ? void 0 : options.namespace);
200
+ const wrapped = yield utils_1.DependencyManager.wrapWithDependencies(value, options === null || options === void 0 ? void 0 : options.dependencies);
201
+ const promises = layers.map((layer) => __awaiter(this, void 0, void 0, function* () {
202
+ const provider = this.providers.get(layer);
203
+ if (!provider) {
204
+ return;
205
+ }
206
+ try {
207
+ yield provider.set(fullKey, wrapped, options === null || options === void 0 ? void 0 : options.ttl);
208
+ }
209
+ catch (error) {
210
+ this.logger.warn(`Failed to set in ${layer} cache: ${error instanceof Error ? error.message : String(error)}`);
211
+ }
212
+ }));
213
+ yield Promise.all(promises);
214
+ });
215
+ }
216
+ resolveLayers(layers) {
217
+ if (layers && layers.length > 0) {
218
+ return layers;
219
+ }
220
+ return this.getDefaultLayers();
221
+ }
222
+ getDefaultLayers() {
223
+ return [interfaces_1.CacheLayer.CLS, interfaces_1.CacheLayer.MEMORY, interfaces_1.CacheLayer.REDIS];
224
+ }
225
+ buildKey(key, namespace) {
226
+ if (namespace) {
227
+ return `${namespace}:${key}`;
228
+ }
229
+ return key;
230
+ }
231
+ backfillUpperLayers(key, value, layers, ttl) {
232
+ return __awaiter(this, void 0, void 0, function* () {
233
+ const promises = layers.map((layer) => __awaiter(this, void 0, void 0, function* () {
234
+ const provider = this.providers.get(layer);
235
+ if (!provider) {
236
+ return;
237
+ }
238
+ try {
239
+ yield provider.set(key, value, ttl);
240
+ }
241
+ catch (error) {
242
+ this.logger.debug(`Failed to backfill ${layer} cache: ${error instanceof Error ? error.message : String(error)}`);
243
+ }
244
+ }));
245
+ yield Promise.all(promises);
246
+ });
247
+ }
248
+ recordHit(layer) {
249
+ this.stats.hits++;
250
+ if (!this.stats.byLayer[layer]) {
251
+ this.stats.byLayer[layer] = { hits: 0, misses: 0, hitRate: 0 };
252
+ }
253
+ this.stats.byLayer[layer].hits++;
254
+ this.updateLayerHitRate(layer);
255
+ }
256
+ recordMiss() {
257
+ this.stats.misses++;
258
+ }
259
+ updateLayerHitRate(layer) {
260
+ const layerStats = this.stats.byLayer[layer];
261
+ if (layerStats) {
262
+ const total = layerStats.hits + layerStats.misses;
263
+ layerStats.hitRate = total > 0 ? layerStats.hits / total : 0;
264
+ }
265
+ }
266
+ initializeStats() {
267
+ for (const layer of [interfaces_1.CacheLayer.CLS, interfaces_1.CacheLayer.MEMORY, interfaces_1.CacheLayer.REDIS]) {
268
+ if (!this.stats.byLayer[layer]) {
269
+ this.stats.byLayer[layer] = { hits: 0, misses: 0, hitRate: 0 };
270
+ }
271
+ }
272
+ }
273
+ };
274
+ exports.CacheService = CacheService;
275
+ exports.CacheService = CacheService = CacheService_1 = __decorate([
276
+ (0, common_1.Injectable)(),
277
+ __metadata("design:paramtypes", [providers_1.ClsCacheProvider,
278
+ providers_1.MemoryCacheProvider,
279
+ providers_1.RedisCacheProvider])
280
+ ], CacheService);
@@ -0,0 +1,34 @@
1
+ import { CacheService } from './cache.service';
2
+ export interface CacheWarmupConfig {
3
+ name: string;
4
+ dataProvider: () => Promise<any> | any;
5
+ key: string | ((data: any) => string);
6
+ ttl?: number;
7
+ layers?: string[];
8
+ batchSize?: number;
9
+ critical?: boolean;
10
+ }
11
+ export interface CacheWarmupResult {
12
+ name: string;
13
+ success: boolean;
14
+ itemCount: number;
15
+ duration: number;
16
+ errors: string[];
17
+ }
18
+ export declare class CacheWarmupService {
19
+ private readonly cacheService;
20
+ private readonly logger;
21
+ private warmupConfigs;
22
+ constructor(cacheService: CacheService);
23
+ registerWarmup(groupName: string, configs: CacheWarmupConfig[]): void;
24
+ warmupGroup(groupName: string): Promise<CacheWarmupResult[]>;
25
+ warmupAll(): Promise<Map<string, CacheWarmupResult[]>>;
26
+ getWarmupStats(): {
27
+ totalGroups: number;
28
+ totalTasks: number;
29
+ taskDetails: any[];
30
+ };
31
+ removeWarmupGroup(groupName: string): boolean;
32
+ clearWarmupConfigs(): void;
33
+ private executeWarmupTask;
34
+ }