@nest-omni/core 4.1.3-1 → 4.1.3-11
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/audit/audit.module.d.ts +10 -0
- package/audit/audit.module.js +39 -1
- package/audit/controllers/audit.controller.d.ts +24 -0
- package/audit/controllers/audit.controller.js +24 -0
- package/audit/decorators/audit-controller.decorator.d.ts +9 -1
- package/audit/decorators/audit-controller.decorator.js +11 -2
- package/audit/decorators/audit-operation.decorator.d.ts +45 -0
- package/audit/decorators/audit-operation.decorator.js +49 -0
- package/audit/decorators/entity-audit.decorator.d.ts +76 -1
- package/audit/decorators/entity-audit.decorator.js +135 -3
- package/audit/decorators/index.d.ts +1 -0
- package/audit/decorators/index.js +1 -0
- package/audit/dto/audit-log-query.dto.d.ts +3 -0
- package/audit/dto/audit-log-query.dto.js +3 -0
- package/audit/dto/begin-transaction.dto.d.ts +3 -0
- package/audit/dto/begin-transaction.dto.js +3 -0
- package/audit/dto/compare-entities.dto.d.ts +3 -0
- package/audit/dto/compare-entities.dto.js +3 -0
- package/audit/dto/pre-check-restore.dto.d.ts +3 -0
- package/audit/dto/pre-check-restore.dto.js +3 -0
- package/audit/dto/restore-entity.dto.d.ts +3 -0
- package/audit/dto/restore-entity.dto.js +3 -0
- package/audit/entities/entity-audit-log.entity.d.ts +8 -0
- package/audit/entities/entity-audit-log.entity.js +33 -1
- package/audit/entities/entity-transaction.entity.d.ts +10 -0
- package/audit/entities/entity-transaction.entity.js +33 -1
- package/audit/entities/index.d.ts +2 -0
- package/audit/entities/index.js +2 -0
- package/audit/entities/manual-operation-log.entity.d.ts +4 -0
- package/audit/entities/manual-operation-log.entity.js +4 -0
- package/audit/entities/operation-template.entity.d.ts +4 -0
- package/audit/entities/operation-template.entity.js +4 -0
- package/audit/enums/audit.enums.d.ts +45 -5
- package/audit/enums/audit.enums.js +47 -4
- package/audit/index.d.ts +3 -1
- package/audit/index.js +30 -1
- package/audit/interceptors/audit.interceptor.d.ts +15 -0
- package/audit/interceptors/audit.interceptor.js +23 -1
- package/audit/interfaces/audit.interfaces.d.ts +182 -2
- package/audit/services/audit-context.service.d.ts +15 -0
- package/audit/services/audit-context.service.js +15 -0
- package/audit/services/audit-strategy.service.d.ts +6 -0
- package/audit/services/audit-strategy.service.js +13 -0
- package/audit/services/entity-audit.service.d.ts +129 -3
- package/audit/services/entity-audit.service.js +301 -6
- package/audit/services/index.d.ts +2 -0
- package/audit/services/index.js +2 -0
- package/audit/services/manual-audit-log.service.d.ts +124 -0
- package/audit/services/manual-audit-log.service.js +138 -0
- package/audit/services/multi-database.service.d.ts +12 -0
- package/audit/services/multi-database.service.js +12 -0
- package/audit/services/operation-description.service.d.ts +59 -0
- package/audit/services/operation-description.service.js +76 -2
- package/audit/services/transaction-audit.service.d.ts +30 -0
- package/audit/services/transaction-audit.service.js +47 -0
- package/audit/subscribers/entity-audit.subscriber.d.ts +15 -0
- package/audit/subscribers/entity-audit.subscriber.js +29 -1
- package/cache/cache-metrics.service.d.ts +67 -0
- package/cache/cache-metrics.service.js +68 -4
- package/cache/cache-serialization.service.d.ts +31 -0
- package/cache/cache-serialization.service.js +25 -0
- package/cache/cache.constants.d.ts +9 -0
- package/cache/cache.constants.js +9 -0
- package/cache/cache.health.d.ts +26 -0
- package/cache/cache.health.js +30 -0
- package/cache/cache.module.d.ts +86 -0
- package/cache/cache.module.js +71 -0
- package/cache/cache.service.d.ts +140 -0
- package/cache/cache.service.js +157 -0
- package/cache/cache.warmup.service.d.ts +39 -0
- package/cache/cache.warmup.service.js +32 -0
- package/cache/decorators/cache-evict.decorator.d.ts +47 -0
- package/cache/decorators/cache-evict.decorator.js +56 -0
- package/cache/decorators/cache-put.decorator.d.ts +34 -0
- package/cache/decorators/cache-put.decorator.js +39 -0
- package/cache/decorators/cacheable.decorator.d.ts +40 -0
- package/cache/decorators/cacheable.decorator.js +55 -0
- package/cache/dependencies/callback.dependency.d.ts +33 -0
- package/cache/dependencies/callback.dependency.js +39 -1
- package/cache/dependencies/chain.dependency.d.ts +28 -0
- package/cache/dependencies/chain.dependency.js +34 -0
- package/cache/dependencies/db.dependency.d.ts +45 -0
- package/cache/dependencies/db.dependency.js +48 -1
- package/cache/dependencies/file.dependency.d.ts +32 -0
- package/cache/dependencies/file.dependency.js +34 -0
- package/cache/dependencies/tag.dependency.d.ts +36 -0
- package/cache/dependencies/tag.dependency.js +36 -0
- package/cache/dependencies/time.dependency.d.ts +43 -0
- package/cache/dependencies/time.dependency.js +43 -0
- package/cache/examples/basic-usage.d.ts +15 -0
- package/cache/examples/basic-usage.js +62 -8
- package/cache/index.js +9 -0
- package/cache/interfaces/cache-dependency.interface.d.ts +53 -0
- package/cache/interfaces/cache-options.interface.d.ts +81 -0
- package/cache/interfaces/cache-options.interface.js +6 -0
- package/cache/interfaces/cache-provider.interface.d.ts +78 -0
- package/cache/providers/base-cache.provider.d.ts +14 -0
- package/cache/providers/base-cache.provider.js +16 -0
- package/cache/providers/cls-cache.provider.d.ts +20 -0
- package/cache/providers/cls-cache.provider.js +28 -0
- package/cache/providers/memory-cache.provider.d.ts +23 -0
- package/cache/providers/memory-cache.provider.js +26 -0
- package/cache/providers/redis-cache.provider.d.ts +26 -0
- package/cache/providers/redis-cache.provider.js +29 -0
- package/cache/utils/dependency-manager.util.d.ts +52 -0
- package/cache/utils/dependency-manager.util.js +59 -0
- package/cache/utils/key-generator.util.d.ts +42 -0
- package/cache/utils/key-generator.util.js +53 -1
- package/common/abstract.entity.d.ts +14 -0
- package/common/abstract.entity.js +14 -0
- package/common/boilerplate.polyfill.d.ts +142 -4
- package/common/boilerplate.polyfill.js +24 -100
- package/common/dto/dto-container.d.ts +16 -0
- package/common/dto/dto-container.js +20 -0
- package/common/dto/dto-decorators.d.ts +18 -0
- package/common/dto/dto-decorators.js +14 -0
- package/common/dto/dto-extensions.d.ts +11 -0
- package/common/dto/dto-extensions.js +9 -0
- package/common/dto/dto-service-accessor.d.ts +17 -0
- package/common/dto/dto-service-accessor.js +18 -0
- package/common/dto/dto-transformer.d.ts +12 -0
- package/common/dto/dto-transformer.js +9 -0
- package/common/dto/index.js +2 -0
- package/common/examples/paginate-and-map.example.d.ts +6 -0
- package/common/examples/paginate-and-map.example.js +26 -0
- package/common/utils.d.ts +15 -0
- package/common/utils.js +15 -0
- package/constants/language-code.js +1 -0
- package/decorators/field.decorators.js +8 -1
- package/decorators/property.decorators.js +1 -0
- package/decorators/public-route.decorator.js +1 -0
- package/decorators/transform.decorators.d.ts +27 -0
- package/decorators/transform.decorators.js +29 -0
- package/decorators/translate.decorator.js +1 -0
- package/decorators/user.decorator.js +1 -0
- package/decorators/validator.decorators.d.ts +8 -18
- package/decorators/validator.decorators.js +22 -190
- package/filters/constraint-errors.js +1 -0
- package/helpers/common.helper.d.ts +13 -0
- package/helpers/common.helper.js +13 -0
- package/http-client/config/http-client.config.d.ts +15 -0
- package/http-client/config/http-client.config.js +25 -9
- package/http-client/decorators/http-client.decorators.d.ts +63 -0
- package/http-client/decorators/http-client.decorators.js +71 -3
- package/http-client/entities/http-log.entity.d.ts +229 -0
- package/http-client/entities/http-log.entity.js +6 -1
- package/http-client/errors/http-client.errors.d.ts +57 -0
- package/http-client/errors/http-client.errors.js +58 -0
- package/http-client/examples/advanced-usage.example.d.ts +41 -0
- package/http-client/examples/advanced-usage.example.js +68 -24
- package/http-client/examples/auth-with-waiting-lock.example.d.ts +31 -0
- package/http-client/examples/auth-with-waiting-lock.example.js +52 -5
- package/http-client/examples/basic-usage.example.d.ts +60 -0
- package/http-client/examples/basic-usage.example.js +60 -0
- package/http-client/examples/multi-api-configuration.example.d.ts +60 -0
- package/http-client/examples/multi-api-configuration.example.js +76 -5
- package/http-client/http-client.module.d.ts +13 -0
- package/http-client/http-client.module.js +20 -5
- package/http-client/index.js +8 -0
- package/http-client/interfaces/api-client-config.interface.d.ts +125 -0
- package/http-client/interfaces/api-client-config.interface.js +3 -0
- package/http-client/interfaces/http-client-config.interface.d.ts +60 -0
- package/http-client/services/api-client-registry.service.d.ts +57 -0
- package/http-client/services/api-client-registry.service.js +84 -1
- package/http-client/services/cache.service.d.ts +52 -0
- package/http-client/services/cache.service.js +72 -3
- package/http-client/services/circuit-breaker.service.d.ts +46 -0
- package/http-client/services/circuit-breaker.service.js +52 -0
- package/http-client/services/http-client.service.d.ts +67 -0
- package/http-client/services/http-client.service.js +105 -4
- package/http-client/services/http-log-query.service.d.ts +83 -0
- package/http-client/services/http-log-query.service.js +122 -1
- package/http-client/services/http-replay.service.d.ts +101 -0
- package/http-client/services/http-replay.service.js +86 -0
- package/http-client/services/log-cleanup.service.d.ts +63 -0
- package/http-client/services/log-cleanup.service.js +54 -2
- package/http-client/services/logging.service.d.ts +40 -0
- package/http-client/services/logging.service.js +53 -0
- package/http-client/utils/call-stack-extractor.util.d.ts +37 -0
- package/http-client/utils/call-stack-extractor.util.js +48 -0
- package/http-client/utils/context-extractor.util.d.ts +49 -0
- package/http-client/utils/context-extractor.util.js +52 -0
- package/http-client/utils/curl-generator.util.d.ts +21 -0
- package/http-client/utils/curl-generator.util.js +44 -3
- package/http-client/utils/request-id.util.d.ts +18 -0
- package/http-client/utils/request-id.util.js +20 -0
- package/http-client/utils/retry-recorder.util.d.ts +42 -0
- package/http-client/utils/retry-recorder.util.js +44 -0
- package/i18n/en_US/validation.json +2 -1
- package/i18n/zh_CN/validation.json +2 -1
- package/index.js +8 -0
- package/interceptors/translation-interceptor.service.js +5 -0
- package/package.json +1 -1
- package/providers/context.provider.js +2 -0
- package/providers/generator.provider.d.ts +4 -0
- package/providers/generator.provider.js +4 -0
- package/redis-lock/comprehensive-lock-cleanup.service.d.ts +94 -0
- package/redis-lock/comprehensive-lock-cleanup.service.js +253 -0
- package/redis-lock/examples/lock-strategy.examples.d.ts +89 -0
- package/redis-lock/examples/lock-strategy.examples.js +130 -15
- package/redis-lock/index.d.ts +2 -0
- package/redis-lock/index.js +8 -1
- package/redis-lock/lock-heartbeat.service.d.ts +78 -0
- package/redis-lock/lock-heartbeat.service.js +222 -0
- package/redis-lock/redis-lock.decorator.d.ts +101 -0
- package/redis-lock/redis-lock.decorator.js +120 -0
- package/redis-lock/redis-lock.module.d.ts +66 -0
- package/redis-lock/redis-lock.module.js +175 -70
- package/redis-lock/redis-lock.service.d.ts +278 -0
- package/redis-lock/redis-lock.service.js +282 -12
- package/setup/bootstrap.setup.js +20 -0
- package/setup/mode.setup.d.ts +44 -0
- package/setup/mode.setup.js +44 -0
- package/setup/schedule.decorator.d.ts +227 -0
- package/setup/schedule.decorator.js +235 -12
- package/setup/worker.decorator.d.ts +86 -0
- package/setup/worker.decorator.js +88 -0
- package/shared/serviceRegistryModule.js +27 -14
- package/shared/services/api-config.service.d.ts +3 -0
- package/shared/services/api-config.service.js +20 -9
- package/validator-json/decorators.d.ts +17 -0
- package/validator-json/decorators.js +17 -2
- package/validator-json/default.d.ts +6 -0
- package/validator-json/default.js +30 -2
- package/validator-json/defaultConverters.js +1 -0
- package/validator-json/options.d.ts +23 -0
- package/validators/common-validators.d.ts +143 -0
- package/validators/common-validators.js +249 -0
- package/validators/custom-validate.examples.d.ts +96 -0
- package/validators/custom-validate.examples.js +400 -0
- package/validators/custom-validate.validator.d.ts +134 -0
- package/validators/custom-validate.validator.js +214 -0
- package/validators/index.d.ts +2 -0
- package/validators/index.js +2 -0
- package/validators/is-exists.validator.d.ts +18 -4
- package/validators/is-exists.validator.js +67 -6
- package/validators/is-unique.validator.d.ts +32 -5
- package/validators/is-unique.validator.js +99 -17
- package/validators/skip-empty.validator.d.ts +5 -0
- package/validators/skip-empty.validator.js +5 -0
- package/vault/interfaces/vault-options.interface.d.ts +9 -0
- package/vault/vault-config.loader.d.ts +30 -0
- package/vault/vault-config.loader.js +48 -1
- package/vault/vault-config.service.d.ts +53 -0
- package/vault/vault-config.service.js +57 -0
- package/vault/vault.module.d.ts +4 -0
- package/vault/vault.module.js +4 -0
- package/decorators/examples/validation-decorators.example.d.ts +0 -69
- package/decorators/examples/validation-decorators.example.js +0 -331
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { EventEmitter } from 'events';
|
|
2
|
+
/**
|
|
3
|
+
* Individual cache operation record
|
|
4
|
+
*/
|
|
2
5
|
export interface CacheOperationRecord {
|
|
3
6
|
type: 'get' | 'set' | 'delete' | 'clear';
|
|
4
7
|
layer: string;
|
|
@@ -8,24 +11,34 @@ export interface CacheOperationRecord {
|
|
|
8
11
|
key?: string;
|
|
9
12
|
timestamp: Date;
|
|
10
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Cache operation metrics
|
|
16
|
+
*/
|
|
11
17
|
export interface CacheMetrics {
|
|
18
|
+
/** Total number of operations */
|
|
12
19
|
totalOperations: number;
|
|
20
|
+
/** Hit/miss statistics */
|
|
13
21
|
hits: number;
|
|
14
22
|
misses: number;
|
|
15
23
|
hitRate: number;
|
|
24
|
+
/** Latency metrics (ms) */
|
|
16
25
|
avgLatency: number;
|
|
17
26
|
minLatency: number;
|
|
18
27
|
maxLatency: number;
|
|
19
28
|
p95Latency: number;
|
|
20
29
|
p99Latency: number;
|
|
30
|
+
/** Operation counts by type */
|
|
21
31
|
gets: number;
|
|
22
32
|
sets: number;
|
|
23
33
|
deletes: number;
|
|
24
34
|
clears: number;
|
|
35
|
+
/** Size metrics */
|
|
25
36
|
totalKeys: number;
|
|
26
37
|
totalSize: number;
|
|
38
|
+
/** Error metrics */
|
|
27
39
|
errors: number;
|
|
28
40
|
errorRate: number;
|
|
41
|
+
/** Layer-specific metrics */
|
|
29
42
|
layerMetrics: {
|
|
30
43
|
cls: {
|
|
31
44
|
hits: number;
|
|
@@ -44,40 +57,94 @@ export interface CacheMetrics {
|
|
|
44
57
|
avgLatency: number;
|
|
45
58
|
};
|
|
46
59
|
};
|
|
60
|
+
/** Time window for these metrics */
|
|
47
61
|
timeWindow: {
|
|
48
62
|
start: Date;
|
|
49
63
|
end: Date;
|
|
50
64
|
duration: number;
|
|
51
65
|
};
|
|
52
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Cache metrics service
|
|
69
|
+
*
|
|
70
|
+
* Collects and analyzes cache performance metrics
|
|
71
|
+
*/
|
|
53
72
|
export declare class CacheMetricsService extends EventEmitter {
|
|
54
73
|
private readonly logger;
|
|
55
74
|
private readonly operations;
|
|
56
75
|
private readonly maxOperations;
|
|
57
76
|
private readonly maxAge;
|
|
58
77
|
constructor();
|
|
78
|
+
/**
|
|
79
|
+
* Record a cache operation
|
|
80
|
+
*/
|
|
59
81
|
recordOperation(type: 'get' | 'set' | 'delete' | 'clear', layer: string, hit: boolean, latency: number, error?: string, key?: string): void;
|
|
82
|
+
/**
|
|
83
|
+
* Get metrics for a time window
|
|
84
|
+
*/
|
|
60
85
|
getMetrics(timeWindowMs?: number): CacheMetrics;
|
|
86
|
+
/**
|
|
87
|
+
* Get real-time metrics snapshot
|
|
88
|
+
*/
|
|
61
89
|
getSnapshot(): Partial<CacheMetrics>;
|
|
90
|
+
/**
|
|
91
|
+
* Get top slow operations
|
|
92
|
+
*/
|
|
62
93
|
getSlowOperations(limit?: number): CacheOperationRecord[];
|
|
94
|
+
/**
|
|
95
|
+
* Get most accessed keys
|
|
96
|
+
*/
|
|
63
97
|
getMostAccessedKeys(limit?: number): {
|
|
64
98
|
key: string;
|
|
65
99
|
count: number;
|
|
66
100
|
avgLatency: number;
|
|
67
101
|
}[];
|
|
102
|
+
/**
|
|
103
|
+
* Get error breakdown
|
|
104
|
+
*/
|
|
68
105
|
getErrorBreakdown(): {
|
|
69
106
|
error: string;
|
|
70
107
|
count: number;
|
|
71
108
|
lastOccurrence: Date;
|
|
72
109
|
}[];
|
|
110
|
+
/**
|
|
111
|
+
* Reset all metrics
|
|
112
|
+
*/
|
|
73
113
|
resetMetrics(): void;
|
|
114
|
+
/**
|
|
115
|
+
* Export metrics for external monitoring systems
|
|
116
|
+
*/
|
|
74
117
|
exportMetrics(format?: 'prometheus' | 'json'): string;
|
|
118
|
+
/**
|
|
119
|
+
* Clean up old operation records
|
|
120
|
+
*/
|
|
75
121
|
private cleanupOldRecords;
|
|
122
|
+
/**
|
|
123
|
+
* Create empty metrics object
|
|
124
|
+
*/
|
|
76
125
|
private createEmptyMetrics;
|
|
126
|
+
/**
|
|
127
|
+
* Calculate layer-specific metrics
|
|
128
|
+
*/
|
|
77
129
|
private calculateLayerMetrics;
|
|
130
|
+
/**
|
|
131
|
+
* Calculate average of array
|
|
132
|
+
*/
|
|
78
133
|
private average;
|
|
134
|
+
/**
|
|
135
|
+
* Calculate percentile
|
|
136
|
+
*/
|
|
79
137
|
private percentile;
|
|
138
|
+
/**
|
|
139
|
+
* Get unique key count
|
|
140
|
+
*/
|
|
80
141
|
private getUniqueKeyCount;
|
|
142
|
+
/**
|
|
143
|
+
* Estimate total cache size
|
|
144
|
+
*/
|
|
81
145
|
private estimateTotalSize;
|
|
146
|
+
/**
|
|
147
|
+
* Convert metrics to Prometheus format
|
|
148
|
+
*/
|
|
82
149
|
private toPrometheusFormat;
|
|
83
150
|
}
|
|
@@ -13,15 +13,24 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
13
13
|
exports.CacheMetricsService = void 0;
|
|
14
14
|
const common_1 = require("@nestjs/common");
|
|
15
15
|
const events_1 = require("events");
|
|
16
|
+
/**
|
|
17
|
+
* Cache metrics service
|
|
18
|
+
*
|
|
19
|
+
* Collects and analyzes cache performance metrics
|
|
20
|
+
*/
|
|
16
21
|
let CacheMetricsService = CacheMetricsService_1 = class CacheMetricsService extends events_1.EventEmitter {
|
|
17
22
|
constructor() {
|
|
18
23
|
super();
|
|
19
24
|
this.logger = new common_1.Logger(CacheMetricsService_1.name);
|
|
20
25
|
this.operations = [];
|
|
21
|
-
this.maxOperations = 10000;
|
|
22
|
-
this.maxAge = 3600000;
|
|
23
|
-
|
|
26
|
+
this.maxOperations = 10000; // Keep last 10k operations
|
|
27
|
+
this.maxAge = 3600000; // 1 hour
|
|
28
|
+
// Clean up old records periodically
|
|
29
|
+
setInterval(() => this.cleanupOldRecords(), 60000); // Every minute
|
|
24
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Record a cache operation
|
|
33
|
+
*/
|
|
25
34
|
recordOperation(type, layer, hit, latency, error, key) {
|
|
26
35
|
const record = {
|
|
27
36
|
type,
|
|
@@ -33,14 +42,20 @@ let CacheMetricsService = CacheMetricsService_1 = class CacheMetricsService exte
|
|
|
33
42
|
timestamp: new Date(),
|
|
34
43
|
};
|
|
35
44
|
this.operations.push(record);
|
|
45
|
+
// Maintain maximum operations limit
|
|
36
46
|
if (this.operations.length > this.maxOperations) {
|
|
37
47
|
this.operations.splice(0, this.operations.length - this.maxOperations);
|
|
38
48
|
}
|
|
49
|
+
// Emit event for real-time monitoring
|
|
39
50
|
this.emit('operation', record);
|
|
51
|
+
// Log errors
|
|
40
52
|
if (error) {
|
|
41
53
|
this.logger.warn(`Cache operation error: ${type} on ${layer} - ${error}`);
|
|
42
54
|
}
|
|
43
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* Get metrics for a time window
|
|
58
|
+
*/
|
|
44
59
|
getMetrics(timeWindowMs = 300000) {
|
|
45
60
|
const endTime = new Date();
|
|
46
61
|
const startTime = new Date(endTime.getTime() - timeWindowMs);
|
|
@@ -58,6 +73,7 @@ let CacheMetricsService = CacheMetricsService_1 = class CacheMetricsService exte
|
|
|
58
73
|
const sets = recentOperations.filter((op) => op.type === 'set').length;
|
|
59
74
|
const deletes = recentOperations.filter((op) => op.type === 'delete').length;
|
|
60
75
|
const clears = recentOperations.filter((op) => op.type === 'clear').length;
|
|
76
|
+
// Calculate layer-specific metrics
|
|
61
77
|
const layerOperations = {
|
|
62
78
|
cls: recentOperations.filter((op) => op.layer === 'cls'),
|
|
63
79
|
memory: recentOperations.filter((op) => op.layer === 'memory'),
|
|
@@ -94,6 +110,9 @@ let CacheMetricsService = CacheMetricsService_1 = class CacheMetricsService exte
|
|
|
94
110
|
},
|
|
95
111
|
};
|
|
96
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* Get real-time metrics snapshot
|
|
115
|
+
*/
|
|
97
116
|
getSnapshot() {
|
|
98
117
|
const now = new Date();
|
|
99
118
|
const oneMinuteAgo = new Date(now.getTime() - 60000);
|
|
@@ -124,12 +143,18 @@ let CacheMetricsService = CacheMetricsService_1 = class CacheMetricsService exte
|
|
|
124
143
|
errorRate: errors / recentOperations.length,
|
|
125
144
|
};
|
|
126
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* Get top slow operations
|
|
148
|
+
*/
|
|
127
149
|
getSlowOperations(limit = 10) {
|
|
128
150
|
return this.operations
|
|
129
151
|
.filter((op) => op.error === undefined)
|
|
130
152
|
.sort((a, b) => b.latency - a.latency)
|
|
131
153
|
.slice(0, limit);
|
|
132
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* Get most accessed keys
|
|
157
|
+
*/
|
|
133
158
|
getMostAccessedKeys(limit = 10) {
|
|
134
159
|
const keyStats = new Map();
|
|
135
160
|
this.operations.forEach((op) => {
|
|
@@ -149,6 +174,9 @@ let CacheMetricsService = CacheMetricsService_1 = class CacheMetricsService exte
|
|
|
149
174
|
.sort((a, b) => b.count - a.count)
|
|
150
175
|
.slice(0, limit);
|
|
151
176
|
}
|
|
177
|
+
/**
|
|
178
|
+
* Get error breakdown
|
|
179
|
+
*/
|
|
152
180
|
getErrorBreakdown() {
|
|
153
181
|
const errorStats = new Map();
|
|
154
182
|
this.operations.forEach((op) => {
|
|
@@ -173,11 +201,17 @@ let CacheMetricsService = CacheMetricsService_1 = class CacheMetricsService exte
|
|
|
173
201
|
}))
|
|
174
202
|
.sort((a, b) => b.count - a.count);
|
|
175
203
|
}
|
|
204
|
+
/**
|
|
205
|
+
* Reset all metrics
|
|
206
|
+
*/
|
|
176
207
|
resetMetrics() {
|
|
177
208
|
this.operations.length = 0;
|
|
178
209
|
this.logger.log('Cache metrics reset');
|
|
179
210
|
this.emit('reset');
|
|
180
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* Export metrics for external monitoring systems
|
|
214
|
+
*/
|
|
181
215
|
exportMetrics(format = 'json') {
|
|
182
216
|
const metrics = this.getMetrics();
|
|
183
217
|
if (format === 'prometheus') {
|
|
@@ -185,9 +219,13 @@ let CacheMetricsService = CacheMetricsService_1 = class CacheMetricsService exte
|
|
|
185
219
|
}
|
|
186
220
|
return JSON.stringify(metrics, null, 2);
|
|
187
221
|
}
|
|
222
|
+
/**
|
|
223
|
+
* Clean up old operation records
|
|
224
|
+
*/
|
|
188
225
|
cleanupOldRecords() {
|
|
189
226
|
const cutoff = new Date(Date.now() - this.maxAge);
|
|
190
227
|
const initialLength = this.operations.length;
|
|
228
|
+
// Remove old records
|
|
191
229
|
for (let i = this.operations.length - 1; i >= 0; i--) {
|
|
192
230
|
if (this.operations[i].timestamp < cutoff) {
|
|
193
231
|
this.operations.splice(0, i + 1);
|
|
@@ -199,6 +237,9 @@ let CacheMetricsService = CacheMetricsService_1 = class CacheMetricsService exte
|
|
|
199
237
|
this.logger.debug(`Cleaned up ${removed} old cache operation records`);
|
|
200
238
|
}
|
|
201
239
|
}
|
|
240
|
+
/**
|
|
241
|
+
* Create empty metrics object
|
|
242
|
+
*/
|
|
202
243
|
createEmptyMetrics(start, end) {
|
|
203
244
|
return {
|
|
204
245
|
totalOperations: 0,
|
|
@@ -230,6 +271,9 @@ let CacheMetricsService = CacheMetricsService_1 = class CacheMetricsService exte
|
|
|
230
271
|
},
|
|
231
272
|
};
|
|
232
273
|
}
|
|
274
|
+
/**
|
|
275
|
+
* Calculate layer-specific metrics
|
|
276
|
+
*/
|
|
233
277
|
calculateLayerMetrics(operations) {
|
|
234
278
|
const hits = operations.filter((op) => op.hit).length;
|
|
235
279
|
const misses = operations.filter((op) => !op.hit).length;
|
|
@@ -238,20 +282,29 @@ let CacheMetricsService = CacheMetricsService_1 = class CacheMetricsService exte
|
|
|
238
282
|
hits,
|
|
239
283
|
misses,
|
|
240
284
|
avgLatency: latencies.length > 0 ? this.average(latencies) : 0,
|
|
241
|
-
size: operations.length,
|
|
285
|
+
size: operations.length, // Approximation
|
|
242
286
|
};
|
|
243
287
|
}
|
|
288
|
+
/**
|
|
289
|
+
* Calculate average of array
|
|
290
|
+
*/
|
|
244
291
|
average(numbers) {
|
|
245
292
|
return numbers.length > 0
|
|
246
293
|
? numbers.reduce((sum, num) => sum + num, 0) / numbers.length
|
|
247
294
|
: 0;
|
|
248
295
|
}
|
|
296
|
+
/**
|
|
297
|
+
* Calculate percentile
|
|
298
|
+
*/
|
|
249
299
|
percentile(sortedNumbers, p) {
|
|
250
300
|
if (sortedNumbers.length === 0)
|
|
251
301
|
return 0;
|
|
252
302
|
const index = Math.ceil(sortedNumbers.length * p) - 1;
|
|
253
303
|
return sortedNumbers[Math.max(0, Math.min(index, sortedNumbers.length - 1))];
|
|
254
304
|
}
|
|
305
|
+
/**
|
|
306
|
+
* Get unique key count
|
|
307
|
+
*/
|
|
255
308
|
getUniqueKeyCount(operations) {
|
|
256
309
|
const keys = new Set();
|
|
257
310
|
operations.forEach((op) => {
|
|
@@ -260,29 +313,40 @@ let CacheMetricsService = CacheMetricsService_1 = class CacheMetricsService exte
|
|
|
260
313
|
});
|
|
261
314
|
return keys.size;
|
|
262
315
|
}
|
|
316
|
+
/**
|
|
317
|
+
* Estimate total cache size
|
|
318
|
+
*/
|
|
263
319
|
estimateTotalSize(operations) {
|
|
320
|
+
// Rough estimation: average key size (20 bytes) + average value size (100 bytes)
|
|
264
321
|
const avgValueSize = 120;
|
|
265
322
|
return this.getUniqueKeyCount(operations) * avgValueSize;
|
|
266
323
|
}
|
|
324
|
+
/**
|
|
325
|
+
* Convert metrics to Prometheus format
|
|
326
|
+
*/
|
|
267
327
|
toPrometheusFormat(metrics) {
|
|
268
328
|
const labels = {
|
|
269
329
|
layer: 'cls|memory|redis',
|
|
270
330
|
};
|
|
271
331
|
let output = '';
|
|
332
|
+
// Hit rate
|
|
272
333
|
output += `# HELP cache_hit_rate Cache hit rate\n`;
|
|
273
334
|
output += `# TYPE cache_hit_rate gauge\n`;
|
|
274
335
|
output += `cache_hit_rate ${metrics.hitRate}\n`;
|
|
336
|
+
// Operations
|
|
275
337
|
output += `# HELP cache_operations_total Total cache operations\n`;
|
|
276
338
|
output += `# TYPE cache_operations_total counter\n`;
|
|
277
339
|
output += `cache_operations_total{type="get"} ${metrics.gets}\n`;
|
|
278
340
|
output += `cache_operations_total{type="set"} ${metrics.sets}\n`;
|
|
279
341
|
output += `cache_operations_total{type="delete"} ${metrics.deletes}\n`;
|
|
280
342
|
output += `cache_operations_total{type="clear"} ${metrics.clears}\n`;
|
|
343
|
+
// Latency
|
|
281
344
|
output += `# HELP cache_latency_ms Cache operation latency\n`;
|
|
282
345
|
output += `# TYPE cache_latency_ms histogram\n`;
|
|
283
346
|
output += `cache_latency_ms{quantile="0.5"} ${metrics.avgLatency}\n`;
|
|
284
347
|
output += `cache_latency_ms{quantile="0.95"} ${metrics.p95Latency}\n`;
|
|
285
348
|
output += `cache_latency_ms{quantile="0.99"} ${metrics.p99Latency}\n`;
|
|
349
|
+
// Layer metrics
|
|
286
350
|
Object.entries(metrics.layerMetrics).forEach(([layer, layerMetrics]) => {
|
|
287
351
|
output += `cache_layer_hits_total{layer="${layer}"} ${layerMetrics.hits}\n`;
|
|
288
352
|
output += `cache_layer_misses_total{layer="${layer}"} ${layerMetrics.misses}\n`;
|
|
@@ -1,22 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache serialization options
|
|
3
|
+
*/
|
|
1
4
|
export interface CacheSerializationOptions {
|
|
5
|
+
/** Whether to compress large values */
|
|
2
6
|
compress?: boolean;
|
|
7
|
+
/** Compression threshold (bytes) */
|
|
3
8
|
compressThreshold?: number;
|
|
4
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Serialization result
|
|
12
|
+
*/
|
|
5
13
|
export interface SerializationResult {
|
|
6
14
|
data: Buffer;
|
|
7
15
|
compressed: boolean;
|
|
8
16
|
originalSize: number;
|
|
9
17
|
serializedSize: number;
|
|
10
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Deserialization result
|
|
21
|
+
*/
|
|
11
22
|
export interface DeserializationResult<T> {
|
|
12
23
|
data: T;
|
|
13
24
|
wasCompressed: boolean;
|
|
14
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Simple cache serialization service
|
|
28
|
+
*
|
|
29
|
+
* Handles basic data compression for cache values
|
|
30
|
+
*/
|
|
15
31
|
export declare class CacheSerializationService {
|
|
16
32
|
private readonly logger;
|
|
33
|
+
/**
|
|
34
|
+
* Serialize and optionally compress cache value
|
|
35
|
+
*/
|
|
17
36
|
serialize<T>(value: T, options?: CacheSerializationOptions): Promise<SerializationResult>;
|
|
37
|
+
/**
|
|
38
|
+
* Deserialize and decompress cache value
|
|
39
|
+
*/
|
|
18
40
|
deserialize<T>(buffer: Buffer): Promise<DeserializationResult<T>>;
|
|
41
|
+
/**
|
|
42
|
+
* Serialize value with proper Date handling
|
|
43
|
+
*/
|
|
19
44
|
private serializeWithDates;
|
|
45
|
+
/**
|
|
46
|
+
* Pre-process object to convert Date objects to serializable format
|
|
47
|
+
*/
|
|
20
48
|
private preProcessDates;
|
|
49
|
+
/**
|
|
50
|
+
* Deserialize value with proper Date restoration
|
|
51
|
+
*/
|
|
21
52
|
private deserializeWithDates;
|
|
22
53
|
}
|
|
@@ -22,18 +22,28 @@ const zlib_1 = require("zlib");
|
|
|
22
22
|
const util_1 = require("util");
|
|
23
23
|
const gzipAsync = (0, util_1.promisify)(zlib_1.gzip);
|
|
24
24
|
const gunzipAsync = (0, util_1.promisify)(zlib_1.gunzip);
|
|
25
|
+
/**
|
|
26
|
+
* Simple cache serialization service
|
|
27
|
+
*
|
|
28
|
+
* Handles basic data compression for cache values
|
|
29
|
+
*/
|
|
25
30
|
let CacheSerializationService = CacheSerializationService_1 = class CacheSerializationService {
|
|
26
31
|
constructor() {
|
|
27
32
|
this.logger = new common_1.Logger(CacheSerializationService_1.name);
|
|
28
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Serialize and optionally compress cache value
|
|
36
|
+
*/
|
|
29
37
|
serialize(value_1) {
|
|
30
38
|
return __awaiter(this, arguments, void 0, function* (value, options = {}) {
|
|
31
39
|
const { compress = false, compressThreshold = 1024 } = options;
|
|
32
40
|
try {
|
|
41
|
+
// Serialize the value with date handling
|
|
33
42
|
const serialized = this.serializeWithDates(value);
|
|
34
43
|
const originalSize = Buffer.byteLength(serialized, 'utf8');
|
|
35
44
|
let data;
|
|
36
45
|
let wasCompressed = false;
|
|
46
|
+
// Compress if enabled and data is large enough
|
|
37
47
|
if (compress && originalSize >= compressThreshold) {
|
|
38
48
|
try {
|
|
39
49
|
data = yield gzipAsync(Buffer.from(serialized, 'utf8'));
|
|
@@ -60,12 +70,17 @@ let CacheSerializationService = CacheSerializationService_1 = class CacheSeriali
|
|
|
60
70
|
}
|
|
61
71
|
});
|
|
62
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* Deserialize and decompress cache value
|
|
75
|
+
*/
|
|
63
76
|
deserialize(buffer) {
|
|
64
77
|
return __awaiter(this, void 0, void 0, function* () {
|
|
65
78
|
try {
|
|
66
79
|
let dataString;
|
|
67
80
|
let wasCompressed = false;
|
|
81
|
+
// Try to detect if data is compressed
|
|
68
82
|
if (buffer.length >= 2 && buffer[0] === 0x1f && buffer[1] === 0x8b) {
|
|
83
|
+
// Gzip magic numbers
|
|
69
84
|
dataString = (yield gunzipAsync(buffer)).toString('utf8');
|
|
70
85
|
wasCompressed = true;
|
|
71
86
|
}
|
|
@@ -84,10 +99,17 @@ let CacheSerializationService = CacheSerializationService_1 = class CacheSeriali
|
|
|
84
99
|
}
|
|
85
100
|
});
|
|
86
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Serialize value with proper Date handling
|
|
104
|
+
*/
|
|
87
105
|
serializeWithDates(value) {
|
|
106
|
+
// Pre-process the value to handle Date objects
|
|
88
107
|
const processed = this.preProcessDates(value);
|
|
89
108
|
return JSON.stringify(processed);
|
|
90
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* Pre-process object to convert Date objects to serializable format
|
|
112
|
+
*/
|
|
91
113
|
preProcessDates(obj) {
|
|
92
114
|
if (obj === null || obj === undefined) {
|
|
93
115
|
return obj;
|
|
@@ -107,6 +129,9 @@ let CacheSerializationService = CacheSerializationService_1 = class CacheSeriali
|
|
|
107
129
|
}
|
|
108
130
|
return obj;
|
|
109
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Deserialize value with proper Date restoration
|
|
134
|
+
*/
|
|
110
135
|
deserializeWithDates(dataString) {
|
|
111
136
|
return JSON.parse(dataString, (key, val) => {
|
|
112
137
|
if (val && typeof val === 'object' && val.__type === 'Date') {
|
|
@@ -1,2 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache constants and injection tokens
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Injection token for cache compression enabled flag
|
|
6
|
+
*/
|
|
1
7
|
export declare const CACHE_COMPRESSION_ENABLED: unique symbol;
|
|
8
|
+
/**
|
|
9
|
+
* Injection token for cache compression threshold
|
|
10
|
+
*/
|
|
2
11
|
export declare const CACHE_COMPRESSION_THRESHOLD: unique symbol;
|
package/cache/cache.constants.js
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Cache constants and injection tokens
|
|
4
|
+
*/
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.CACHE_COMPRESSION_THRESHOLD = exports.CACHE_COMPRESSION_ENABLED = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Injection token for cache compression enabled flag
|
|
9
|
+
*/
|
|
4
10
|
exports.CACHE_COMPRESSION_ENABLED = Symbol('CACHE_COMPRESSION_ENABLED');
|
|
11
|
+
/**
|
|
12
|
+
* Injection token for cache compression threshold
|
|
13
|
+
*/
|
|
5
14
|
exports.CACHE_COMPRESSION_THRESHOLD = Symbol('CACHE_COMPRESSION_THRESHOLD');
|
package/cache/cache.health.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { CacheService } from './cache.service';
|
|
2
|
+
/**
|
|
3
|
+
* Cache health check result
|
|
4
|
+
*/
|
|
2
5
|
export interface CacheHealthResult {
|
|
3
6
|
status: 'healthy' | 'degraded' | 'unhealthy';
|
|
4
7
|
layers: {
|
|
@@ -22,14 +25,37 @@ export interface CacheHealthResult {
|
|
|
22
25
|
timestamp: Date;
|
|
23
26
|
overallLatency: number;
|
|
24
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Cache health checker
|
|
30
|
+
*
|
|
31
|
+
* Provides health monitoring for all cache layers
|
|
32
|
+
*/
|
|
25
33
|
export declare class CacheHealthChecker {
|
|
26
34
|
private readonly cacheService;
|
|
27
35
|
private readonly logger;
|
|
28
36
|
constructor(cacheService: CacheService);
|
|
37
|
+
/**
|
|
38
|
+
* Check health of all cache layers
|
|
39
|
+
*/
|
|
29
40
|
checkHealth(): Promise<CacheHealthResult>;
|
|
41
|
+
/**
|
|
42
|
+
* Get detailed cache statistics
|
|
43
|
+
*/
|
|
30
44
|
getDetailedStats(): Promise<any>;
|
|
45
|
+
/**
|
|
46
|
+
* Check CLS cache health
|
|
47
|
+
*/
|
|
31
48
|
private checkClsHealth;
|
|
49
|
+
/**
|
|
50
|
+
* Check Memory cache health
|
|
51
|
+
*/
|
|
32
52
|
private checkMemoryHealth;
|
|
53
|
+
/**
|
|
54
|
+
* Check Redis cache health
|
|
55
|
+
*/
|
|
33
56
|
private checkRedisHealth;
|
|
57
|
+
/**
|
|
58
|
+
* Generate recommendations based on health and stats
|
|
59
|
+
*/
|
|
34
60
|
private generateRecommendations;
|
|
35
61
|
}
|
package/cache/cache.health.js
CHANGED
|
@@ -23,11 +23,19 @@ exports.CacheHealthChecker = void 0;
|
|
|
23
23
|
const common_1 = require("@nestjs/common");
|
|
24
24
|
const cache_service_1 = require("./cache.service");
|
|
25
25
|
const cache_options_interface_1 = require("./interfaces/cache-options.interface");
|
|
26
|
+
/**
|
|
27
|
+
* Cache health checker
|
|
28
|
+
*
|
|
29
|
+
* Provides health monitoring for all cache layers
|
|
30
|
+
*/
|
|
26
31
|
let CacheHealthChecker = CacheHealthChecker_1 = class CacheHealthChecker {
|
|
27
32
|
constructor(cacheService) {
|
|
28
33
|
this.cacheService = cacheService;
|
|
29
34
|
this.logger = new common_1.Logger(CacheHealthChecker_1.name);
|
|
30
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Check health of all cache layers
|
|
38
|
+
*/
|
|
31
39
|
checkHealth() {
|
|
32
40
|
return __awaiter(this, void 0, void 0, function* () {
|
|
33
41
|
const startTime = Date.now();
|
|
@@ -37,6 +45,7 @@ let CacheHealthChecker = CacheHealthChecker_1 = class CacheHealthChecker {
|
|
|
37
45
|
redis: yield this.checkRedisHealth(),
|
|
38
46
|
};
|
|
39
47
|
const overallLatency = Date.now() - startTime;
|
|
48
|
+
// Determine overall status
|
|
40
49
|
const layerStatuses = Object.values(results);
|
|
41
50
|
const healthyCount = layerStatuses.filter((layer) => layer.available).length;
|
|
42
51
|
const totalCount = layerStatuses.length;
|
|
@@ -58,6 +67,9 @@ let CacheHealthChecker = CacheHealthChecker_1 = class CacheHealthChecker {
|
|
|
58
67
|
};
|
|
59
68
|
});
|
|
60
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Get detailed cache statistics
|
|
72
|
+
*/
|
|
61
73
|
getDetailedStats() {
|
|
62
74
|
return __awaiter(this, void 0, void 0, function* () {
|
|
63
75
|
const stats = this.cacheService.getStats();
|
|
@@ -69,10 +81,14 @@ let CacheHealthChecker = CacheHealthChecker_1 = class CacheHealthChecker {
|
|
|
69
81
|
};
|
|
70
82
|
});
|
|
71
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Check CLS cache health
|
|
86
|
+
*/
|
|
72
87
|
checkClsHealth() {
|
|
73
88
|
return __awaiter(this, void 0, void 0, function* () {
|
|
74
89
|
const startTime = Date.now();
|
|
75
90
|
try {
|
|
91
|
+
// Try to write and read a test value
|
|
76
92
|
yield this.cacheService.set('health:cls:test', 'test-value', {
|
|
77
93
|
layers: [cache_options_interface_1.CacheLayer.CLS],
|
|
78
94
|
});
|
|
@@ -101,10 +117,14 @@ let CacheHealthChecker = CacheHealthChecker_1 = class CacheHealthChecker {
|
|
|
101
117
|
}
|
|
102
118
|
});
|
|
103
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Check Memory cache health
|
|
122
|
+
*/
|
|
104
123
|
checkMemoryHealth() {
|
|
105
124
|
return __awaiter(this, void 0, void 0, function* () {
|
|
106
125
|
const startTime = Date.now();
|
|
107
126
|
try {
|
|
127
|
+
// Try to write and read a test value
|
|
108
128
|
yield this.cacheService.set('health:memory:test', 'test-value', {
|
|
109
129
|
layers: [cache_options_interface_1.CacheLayer.MEMORY],
|
|
110
130
|
});
|
|
@@ -113,6 +133,7 @@ let CacheHealthChecker = CacheHealthChecker_1 = class CacheHealthChecker {
|
|
|
113
133
|
});
|
|
114
134
|
const latency = Date.now() - startTime;
|
|
115
135
|
if (result === 'test-value') {
|
|
136
|
+
// Get memory cache size (if available)
|
|
116
137
|
const stats = this.cacheService.getStats();
|
|
117
138
|
return { available: true, latency, size: stats.totalSets };
|
|
118
139
|
}
|
|
@@ -134,10 +155,14 @@ let CacheHealthChecker = CacheHealthChecker_1 = class CacheHealthChecker {
|
|
|
134
155
|
}
|
|
135
156
|
});
|
|
136
157
|
}
|
|
158
|
+
/**
|
|
159
|
+
* Check Redis cache health
|
|
160
|
+
*/
|
|
137
161
|
checkRedisHealth() {
|
|
138
162
|
return __awaiter(this, void 0, void 0, function* () {
|
|
139
163
|
const startTime = Date.now();
|
|
140
164
|
try {
|
|
165
|
+
// Try to write and read a test value
|
|
141
166
|
yield this.cacheService.set('health:redis:test', 'test-value', {
|
|
142
167
|
layers: [cache_options_interface_1.CacheLayer.REDIS],
|
|
143
168
|
});
|
|
@@ -166,8 +191,12 @@ let CacheHealthChecker = CacheHealthChecker_1 = class CacheHealthChecker {
|
|
|
166
191
|
}
|
|
167
192
|
});
|
|
168
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* Generate recommendations based on health and stats
|
|
196
|
+
*/
|
|
169
197
|
generateRecommendations(health, stats) {
|
|
170
198
|
const recommendations = [];
|
|
199
|
+
// Health-based recommendations
|
|
171
200
|
if (!health.layers.redis.available) {
|
|
172
201
|
recommendations.push('Redis is unavailable. Check Redis connection and configuration.');
|
|
173
202
|
}
|
|
@@ -177,6 +206,7 @@ let CacheHealthChecker = CacheHealthChecker_1 = class CacheHealthChecker {
|
|
|
177
206
|
if (health.overallLatency > 100) {
|
|
178
207
|
recommendations.push('Cache latency is high. Consider optimizing cache operations or increasing resources.');
|
|
179
208
|
}
|
|
209
|
+
// Statistics-based recommendations
|
|
180
210
|
if (stats.hitRate < 0.5) {
|
|
181
211
|
recommendations.push('Cache hit rate is low. Review cache TTL and key patterns.');
|
|
182
212
|
}
|