@nest-omni/core 3.1.1-9 → 3.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 (306) hide show
  1. package/.hygen/new/crud/controller.ejs.t +82 -0
  2. package/.hygen/new/crud/create.dto.ejs.t +12 -0
  3. package/.hygen/new/crud/entity.ejs.t +26 -0
  4. package/.hygen/new/crud/get.dto.ejs.t +19 -0
  5. package/.hygen/new/crud/index-dto.ejs.t +29 -0
  6. package/.hygen/new/crud/index-response.dto.ejs.t +18 -0
  7. package/.hygen/new/crud/module.ejs.t +32 -0
  8. package/.hygen/new/crud/prompt.js +89 -0
  9. package/.hygen/new/crud/service.ejs.t +76 -0
  10. package/.hygen/new/crud/update.dto.ejs.t +11 -0
  11. package/.hygen/new/module/controller.ejs.t +93 -0
  12. package/.hygen/new/module/create-command.ejs.t +90 -0
  13. package/.hygen/new/module/create.dto.ejs.t +11 -0
  14. package/.hygen/new/module/dto.ejs.t +24 -0
  15. package/.hygen/new/module/entity.ejs.t +33 -0
  16. package/.hygen/new/module/get-query.ejs.t +57 -0
  17. package/.hygen/new/module/module.ejs.t +44 -0
  18. package/.hygen/new/module/not-found.exception.ejs.t +18 -0
  19. package/.hygen/new/module/page-options.dto.ejs.t +12 -0
  20. package/.hygen/new/module/prompt.js +104 -0
  21. package/.hygen/new/module/repository.ejs.t +16 -0
  22. package/.hygen/new/module/service.ejs.t +139 -0
  23. package/.hygen/new/module/translation-dto.ejs.t +27 -0
  24. package/.hygen/new/module/translation-entity.ejs.t +40 -0
  25. package/.hygen/new/module/translation-repository.ejs.t +16 -0
  26. package/.hygen/new/module/update.dto.ejs.t +10 -0
  27. package/.hygen.js +116 -0
  28. package/cache/cache-metrics.service.d.ts +83 -0
  29. package/cache/cache-metrics.service.js +298 -0
  30. package/cache/cache-serialization.service.d.ts +22 -0
  31. package/cache/cache-serialization.service.js +122 -0
  32. package/cache/cache.constants.d.ts +2 -0
  33. package/cache/cache.constants.js +5 -0
  34. package/cache/cache.health.d.ts +35 -0
  35. package/cache/cache.health.js +193 -0
  36. package/cache/cache.module.d.ts +26 -0
  37. package/cache/cache.module.js +155 -0
  38. package/cache/cache.service.d.ts +37 -0
  39. package/cache/cache.service.js +308 -0
  40. package/cache/cache.warmup.service.d.ts +34 -0
  41. package/cache/cache.warmup.service.js +199 -0
  42. package/cache/decorators/cache-evict.decorator.d.ts +2 -0
  43. package/cache/decorators/cache-evict.decorator.js +72 -0
  44. package/cache/decorators/cache-put.decorator.d.ts +2 -0
  45. package/cache/decorators/cache-put.decorator.js +48 -0
  46. package/cache/decorators/cacheable.decorator.d.ts +4 -0
  47. package/cache/decorators/cacheable.decorator.js +68 -0
  48. package/cache/decorators/index.d.ts +3 -0
  49. package/cache/decorators/index.js +11 -0
  50. package/cache/dependencies/callback.dependency.d.ts +11 -0
  51. package/cache/dependencies/callback.dependency.js +92 -0
  52. package/cache/dependencies/chain.dependency.d.ts +20 -0
  53. package/cache/dependencies/chain.dependency.js +113 -0
  54. package/cache/dependencies/db.dependency.d.ts +15 -0
  55. package/cache/dependencies/db.dependency.js +71 -0
  56. package/cache/dependencies/file.dependency.d.ts +17 -0
  57. package/cache/dependencies/file.dependency.js +63 -0
  58. package/cache/dependencies/index.d.ts +6 -0
  59. package/cache/dependencies/index.js +22 -0
  60. package/cache/dependencies/tag.dependency.d.ts +16 -0
  61. package/cache/dependencies/tag.dependency.js +75 -0
  62. package/cache/dependencies/time.dependency.d.ts +19 -0
  63. package/cache/dependencies/time.dependency.js +71 -0
  64. package/cache/examples/basic-usage.d.ts +58 -0
  65. package/cache/examples/basic-usage.js +379 -0
  66. package/cache/index.d.ts +15 -0
  67. package/cache/index.js +44 -0
  68. package/cache/interfaces/cache-dependency.interface.d.ts +11 -0
  69. package/cache/interfaces/cache-dependency.interface.js +2 -0
  70. package/cache/interfaces/cache-options.interface.d.ts +32 -0
  71. package/cache/interfaces/cache-options.interface.js +9 -0
  72. package/cache/interfaces/cache-provider.interface.d.ts +28 -0
  73. package/cache/interfaces/cache-provider.interface.js +2 -0
  74. package/cache/interfaces/index.d.ts +3 -0
  75. package/cache/interfaces/index.js +19 -0
  76. package/cache/providers/base-cache.provider.d.ts +16 -0
  77. package/cache/providers/base-cache.provider.js +32 -0
  78. package/cache/providers/cls-cache.provider.d.ts +16 -0
  79. package/cache/providers/cls-cache.provider.js +140 -0
  80. package/cache/providers/index.d.ts +4 -0
  81. package/cache/providers/index.js +23 -0
  82. package/cache/providers/memory-cache.provider.d.ts +26 -0
  83. package/cache/providers/memory-cache.provider.js +171 -0
  84. package/cache/providers/redis-cache.provider.d.ts +23 -0
  85. package/cache/providers/redis-cache.provider.js +215 -0
  86. package/cache/utils/dependency-manager.util.d.ts +15 -0
  87. package/cache/utils/dependency-manager.util.js +141 -0
  88. package/cache/utils/index.d.ts +2 -0
  89. package/cache/utils/index.js +18 -0
  90. package/cache/utils/key-generator.util.d.ts +13 -0
  91. package/cache/utils/key-generator.util.js +74 -0
  92. package/common/abstract.entity.d.ts +20 -0
  93. package/common/abstract.entity.js +81 -0
  94. package/common/boilerplate.polyfill.d.ts +50 -0
  95. package/common/boilerplate.polyfill.js +152 -0
  96. package/common/dto/abstract.dto.d.ts +13 -0
  97. package/common/dto/abstract.dto.js +59 -0
  98. package/common/dto/bulk-id.dto.d.ts +3 -0
  99. package/common/dto/bulk-id.dto.js +27 -0
  100. package/common/dto/create-translation.dto.d.ts +5 -0
  101. package/common/dto/create-translation.dto.js +25 -0
  102. package/common/dto/dto-container.d.ts +9 -0
  103. package/common/dto/dto-container.js +59 -0
  104. package/common/dto/dto-decorators.d.ts +18 -0
  105. package/common/dto/dto-decorators.js +59 -0
  106. package/common/dto/dto-extensions.d.ts +12 -0
  107. package/common/dto/dto-extensions.js +63 -0
  108. package/common/dto/dto-service-accessor.d.ts +7 -0
  109. package/common/dto/dto-service-accessor.js +49 -0
  110. package/common/dto/dto-transformer.d.ts +11 -0
  111. package/common/dto/dto-transformer.js +49 -0
  112. package/common/dto/index.d.ts +12 -0
  113. package/common/dto/index.js +28 -0
  114. package/common/dto/page-meta.dto.d.ts +15 -0
  115. package/common/dto/page-meta.dto.js +48 -0
  116. package/common/dto/page-options.dto.d.ts +5 -0
  117. package/common/dto/page-options.dto.js +40 -0
  118. package/common/dto/page.dto.d.ts +11 -0
  119. package/common/dto/page.dto.js +53 -0
  120. package/common/examples/paginate-and-map.example.d.ts +14 -0
  121. package/common/examples/paginate-and-map.example.js +158 -0
  122. package/common/index.d.ts +6 -0
  123. package/common/index.js +22 -0
  124. package/common/snake-naming.strategy.d.ts +11 -0
  125. package/common/snake-naming.strategy.js +37 -0
  126. package/common/types.d.ts +9 -0
  127. package/common/types.js +2 -0
  128. package/common/utils.d.ts +3 -0
  129. package/common/utils.js +24 -0
  130. package/constants/index.d.ts +2 -0
  131. package/constants/index.js +18 -0
  132. package/constants/language-code.d.ts +5 -0
  133. package/constants/language-code.js +9 -0
  134. package/constants/order.d.ts +4 -0
  135. package/constants/order.js +8 -0
  136. package/decorators/api-page-ok-response.decorator.d.ts +5 -0
  137. package/decorators/api-page-ok-response.decorator.js +24 -0
  138. package/decorators/auth-user.decorator.d.ts +1 -0
  139. package/decorators/auth-user.decorator.js +14 -0
  140. package/decorators/controller.decorator.d.ts +1 -0
  141. package/decorators/controller.decorator.js +10 -0
  142. package/decorators/examples/validation-decorators.example.d.ts +69 -0
  143. package/decorators/examples/validation-decorators.example.js +331 -0
  144. package/decorators/field.decorators.d.ts +79 -0
  145. package/decorators/field.decorators.js +499 -0
  146. package/decorators/http.decorators.d.ts +3 -0
  147. package/decorators/http.decorators.js +7 -0
  148. package/decorators/index.d.ts +12 -0
  149. package/decorators/index.js +28 -0
  150. package/decorators/operation.decorator.d.ts +1 -0
  151. package/decorators/operation.decorator.js +6 -0
  152. package/decorators/property.decorators.d.ts +15 -0
  153. package/decorators/property.decorators.js +31 -0
  154. package/decorators/public-route.decorator.d.ts +3 -0
  155. package/decorators/public-route.decorator.js +7 -0
  156. package/decorators/swagger.schema.d.ts +5 -0
  157. package/decorators/swagger.schema.js +78 -0
  158. package/decorators/timestamp-column.decorator.d.ts +1 -0
  159. package/decorators/timestamp-column.decorator.js +27 -0
  160. package/decorators/transform.decorators.d.ts +8 -0
  161. package/decorators/transform.decorators.js +100 -0
  162. package/decorators/translate.decorator.d.ts +5 -0
  163. package/decorators/translate.decorator.js +17 -0
  164. package/decorators/use-dto.decorator.d.ts +4 -0
  165. package/decorators/use-dto.decorator.js +8 -0
  166. package/decorators/user-check.decorator.d.ts +6 -0
  167. package/decorators/user-check.decorator.js +21 -0
  168. package/decorators/user.decorator.d.ts +12 -0
  169. package/decorators/user.decorator.js +44 -0
  170. package/decorators/user_auth.decorator.d.ts +1 -0
  171. package/decorators/user_auth.decorator.js +15 -0
  172. package/decorators/validator.decorators.d.ts +18 -0
  173. package/decorators/validator.decorators.js +193 -0
  174. package/exceptions/file-not-image.exception.d.ts +4 -0
  175. package/exceptions/file-not-image.exception.js +10 -0
  176. package/exceptions/index.d.ts +2 -0
  177. package/exceptions/index.js +18 -0
  178. package/exceptions/page-type.exception.d.ts +4 -0
  179. package/exceptions/page-type.exception.js +10 -0
  180. package/exceptions/user-not-found.exception.d.ts +4 -0
  181. package/exceptions/user-not-found.exception.js +10 -0
  182. package/filters/bad-request.filter.d.ts +5 -0
  183. package/filters/bad-request.filter.js +71 -0
  184. package/filters/constraint-errors.d.ts +1 -0
  185. package/filters/constraint-errors.js +6 -0
  186. package/filters/index.d.ts +3 -0
  187. package/filters/index.js +19 -0
  188. package/filters/query-failed.filter.d.ts +10 -0
  189. package/filters/query-failed.filter.js +42 -0
  190. package/health-checker/health-checker.controller.d.ts +13 -0
  191. package/health-checker/health-checker.controller.js +69 -0
  192. package/health-checker/health-checker.module.d.ts +2 -0
  193. package/health-checker/health-checker.module.js +24 -0
  194. package/health-checker/index.d.ts +2 -0
  195. package/health-checker/index.js +18 -0
  196. package/helpers/common.helper.d.ts +3 -0
  197. package/helpers/common.helper.js +36 -0
  198. package/helpers/date.helper.d.ts +10 -0
  199. package/helpers/date.helper.js +57 -0
  200. package/helpers/index.d.ts +2 -0
  201. package/helpers/index.js +18 -0
  202. package/i18n/en_US/validation.json +44 -0
  203. package/i18n/zh_CN/validation.json +44 -0
  204. package/index.d.ts +18 -0
  205. package/index.js +3 -0
  206. package/interceptors/index.d.ts +2 -0
  207. package/interceptors/index.js +18 -0
  208. package/interceptors/language-interceptor.service.d.ts +6 -0
  209. package/interceptors/language-interceptor.service.js +29 -0
  210. package/interceptors/translation-interceptor.service.d.ts +5 -0
  211. package/interceptors/translation-interceptor.service.js +34 -0
  212. package/interfaces/IApiFile.d.ts +4 -0
  213. package/interfaces/IApiFile.js +2 -0
  214. package/interfaces/IFile.d.ts +8 -0
  215. package/interfaces/IFile.js +2 -0
  216. package/interfaces/ITranslationDecoratorInterface.d.ts +3 -0
  217. package/interfaces/ITranslationDecoratorInterface.js +2 -0
  218. package/interfaces/index.d.ts +3 -0
  219. package/interfaces/index.js +19 -0
  220. package/interfaces/response.d.ts +25 -0
  221. package/interfaces/response.js +2 -0
  222. package/middlewares/index.d.ts +4 -0
  223. package/middlewares/index.js +20 -0
  224. package/middlewares/omni-auth.middleware.d.ts +1 -0
  225. package/middlewares/omni-auth.middleware.js +13 -0
  226. package/middlewares/powerby.middleware.d.ts +1 -0
  227. package/middlewares/powerby.middleware.js +10 -0
  228. package/middlewares/request-id.middleware.d.ts +7 -0
  229. package/middlewares/request-id.middleware.js +22 -0
  230. package/middlewares/xml.middleware.d.ts +4 -0
  231. package/middlewares/xml.middleware.js +24 -0
  232. package/package.json +41 -116
  233. package/providers/context.provider.d.ts +34 -0
  234. package/providers/context.provider.js +80 -0
  235. package/providers/generator.provider.d.ts +9 -0
  236. package/providers/generator.provider.js +50 -0
  237. package/providers/index.d.ts +2 -0
  238. package/providers/index.js +18 -0
  239. package/redis-lock/examples/lock-strategy.examples.d.ts +73 -0
  240. package/redis-lock/examples/lock-strategy.examples.js +387 -0
  241. package/redis-lock/index.d.ts +4 -0
  242. package/redis-lock/index.js +16 -0
  243. package/redis-lock/redis-lock.decorator.d.ts +12 -0
  244. package/redis-lock/redis-lock.decorator.js +125 -0
  245. package/redis-lock/redis-lock.module.d.ts +23 -0
  246. package/redis-lock/redis-lock.module.js +117 -0
  247. package/redis-lock/redis-lock.service.d.ts +66 -0
  248. package/redis-lock/redis-lock.service.js +413 -0
  249. package/setup/bootstrap.setup.d.ts +2 -0
  250. package/setup/bootstrap.setup.js +184 -0
  251. package/setup/index.d.ts +4 -0
  252. package/setup/index.js +20 -0
  253. package/setup/mode.setup.d.ts +12 -0
  254. package/setup/mode.setup.js +60 -0
  255. package/setup/schedule.decorator.d.ts +23 -0
  256. package/setup/schedule.decorator.js +233 -0
  257. package/setup/worker.decorator.d.ts +14 -0
  258. package/setup/worker.decorator.js +130 -0
  259. package/shared/index.d.ts +2 -0
  260. package/shared/index.js +18 -0
  261. package/shared/serviceRegistryModule.d.ts +2 -0
  262. package/shared/serviceRegistryModule.js +170 -0
  263. package/shared/services/api-config.service.d.ts +54 -0
  264. package/shared/services/api-config.service.js +287 -0
  265. package/shared/services/generator.service.d.ts +4 -0
  266. package/shared/services/generator.service.js +23 -0
  267. package/shared/services/index.d.ts +4 -0
  268. package/shared/services/index.js +20 -0
  269. package/shared/services/translation.service.d.ts +9 -0
  270. package/shared/services/translation.service.js +70 -0
  271. package/shared/services/validator.service.d.ts +3 -0
  272. package/shared/services/validator.service.js +20 -0
  273. package/validator-json/decorators.d.ts +6 -0
  274. package/validator-json/decorators.js +22 -0
  275. package/validator-json/default.d.ts +6 -0
  276. package/validator-json/default.js +138 -0
  277. package/validator-json/defaultConverters.d.ts +8 -0
  278. package/validator-json/defaultConverters.js +376 -0
  279. package/validator-json/index.d.ts +4 -0
  280. package/validator-json/index.js +20 -0
  281. package/validator-json/options.d.ts +11 -0
  282. package/validator-json/options.js +10 -0
  283. package/validators/file-mimetype.validator.d.ts +13 -0
  284. package/validators/file-mimetype.validator.js +21 -0
  285. package/validators/index.d.ts +6 -0
  286. package/validators/index.js +22 -0
  287. package/validators/is-exists.validator.d.ts +18 -0
  288. package/validators/is-exists.validator.js +60 -0
  289. package/validators/is-unique.validator.d.ts +17 -0
  290. package/validators/is-unique.validator.js +91 -0
  291. package/validators/phone-country-code.validator.d.ts +2 -0
  292. package/validators/phone-country-code.validator.js +29 -0
  293. package/validators/same-as.validator.d.ts +2 -0
  294. package/validators/same-as.validator.js +24 -0
  295. package/validators/skip-empty.validator.d.ts +1 -0
  296. package/validators/skip-empty.validator.js +17 -0
  297. package/vault/index.d.ts +4 -0
  298. package/vault/index.js +20 -0
  299. package/vault/interfaces/vault-options.interface.d.ts +22 -0
  300. package/vault/interfaces/vault-options.interface.js +2 -0
  301. package/vault/vault-config.loader.d.ts +13 -0
  302. package/vault/vault-config.loader.js +246 -0
  303. package/vault/vault-config.service.d.ts +18 -0
  304. package/vault/vault-config.service.js +174 -0
  305. package/vault/vault.module.d.ts +2 -0
  306. package/vault/vault.module.js +21 -0
@@ -0,0 +1,298 @@
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 CacheMetricsService_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.CacheMetricsService = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const events_1 = require("events");
16
+ let CacheMetricsService = CacheMetricsService_1 = class CacheMetricsService extends events_1.EventEmitter {
17
+ constructor() {
18
+ super();
19
+ this.logger = new common_1.Logger(CacheMetricsService_1.name);
20
+ this.operations = [];
21
+ this.maxOperations = 10000;
22
+ this.maxAge = 3600000;
23
+ setInterval(() => this.cleanupOldRecords(), 60000);
24
+ }
25
+ recordOperation(type, layer, hit, latency, error, key) {
26
+ const record = {
27
+ type,
28
+ layer,
29
+ hit,
30
+ latency,
31
+ error,
32
+ key,
33
+ timestamp: new Date(),
34
+ };
35
+ this.operations.push(record);
36
+ if (this.operations.length > this.maxOperations) {
37
+ this.operations.splice(0, this.operations.length - this.maxOperations);
38
+ }
39
+ this.emit('operation', record);
40
+ if (error) {
41
+ this.logger.warn(`Cache operation error: ${type} on ${layer} - ${error}`);
42
+ }
43
+ }
44
+ getMetrics(timeWindowMs = 300000) {
45
+ const endTime = new Date();
46
+ const startTime = new Date(endTime.getTime() - timeWindowMs);
47
+ const recentOperations = this.operations.filter((op) => op.timestamp >= startTime && op.timestamp <= endTime);
48
+ if (recentOperations.length === 0) {
49
+ return this.createEmptyMetrics(startTime, endTime);
50
+ }
51
+ const hits = recentOperations.filter((op) => op.hit).length;
52
+ const misses = recentOperations.filter((op) => !op.hit).length;
53
+ const errors = recentOperations.filter((op) => op.error).length;
54
+ const latencies = recentOperations
55
+ .map((op) => op.latency)
56
+ .sort((a, b) => a - b);
57
+ const gets = recentOperations.filter((op) => op.type === 'get').length;
58
+ const sets = recentOperations.filter((op) => op.type === 'set').length;
59
+ const deletes = recentOperations.filter((op) => op.type === 'delete').length;
60
+ const clears = recentOperations.filter((op) => op.type === 'clear').length;
61
+ const layerOperations = {
62
+ cls: recentOperations.filter((op) => op.layer === 'cls'),
63
+ memory: recentOperations.filter((op) => op.layer === 'memory'),
64
+ redis: recentOperations.filter((op) => op.layer === 'redis'),
65
+ };
66
+ const layerMetrics = {
67
+ cls: this.calculateLayerMetrics(layerOperations.cls),
68
+ memory: this.calculateLayerMetrics(layerOperations.memory),
69
+ redis: this.calculateLayerMetrics(layerOperations.redis),
70
+ };
71
+ return {
72
+ totalOperations: recentOperations.length,
73
+ hits,
74
+ misses,
75
+ hitRate: recentOperations.length > 0 ? hits / recentOperations.length : 0,
76
+ avgLatency: this.average(latencies),
77
+ minLatency: latencies.length > 0 ? latencies[0] : 0,
78
+ maxLatency: latencies.length > 0 ? latencies[latencies.length - 1] : 0,
79
+ p95Latency: this.percentile(latencies, 0.95),
80
+ p99Latency: this.percentile(latencies, 0.99),
81
+ gets,
82
+ sets,
83
+ deletes,
84
+ clears,
85
+ totalKeys: this.getUniqueKeyCount(recentOperations),
86
+ totalSize: this.estimateTotalSize(recentOperations),
87
+ errors,
88
+ errorRate: recentOperations.length > 0 ? errors / recentOperations.length : 0,
89
+ layerMetrics,
90
+ timeWindow: {
91
+ start: startTime,
92
+ end: endTime,
93
+ duration: timeWindowMs,
94
+ },
95
+ };
96
+ }
97
+ getSnapshot() {
98
+ const now = new Date();
99
+ const oneMinuteAgo = new Date(now.getTime() - 60000);
100
+ const recentOperations = this.operations.filter((op) => op.timestamp >= oneMinuteAgo);
101
+ if (recentOperations.length === 0) {
102
+ return {
103
+ totalOperations: 0,
104
+ hits: 0,
105
+ misses: 0,
106
+ hitRate: 0,
107
+ avgLatency: 0,
108
+ errors: 0,
109
+ errorRate: 0,
110
+ };
111
+ }
112
+ const hits = recentOperations.filter((op) => op.hit).length;
113
+ const errors = recentOperations.filter((op) => op.error).length;
114
+ const latencies = recentOperations.map((op) => op.latency);
115
+ return {
116
+ totalOperations: recentOperations.length,
117
+ hits,
118
+ misses: recentOperations.length - hits,
119
+ hitRate: hits / recentOperations.length,
120
+ avgLatency: this.average(latencies),
121
+ minLatency: Math.min(...latencies),
122
+ maxLatency: Math.max(...latencies),
123
+ errors,
124
+ errorRate: errors / recentOperations.length,
125
+ };
126
+ }
127
+ getSlowOperations(limit = 10) {
128
+ return this.operations
129
+ .filter((op) => op.error === undefined)
130
+ .sort((a, b) => b.latency - a.latency)
131
+ .slice(0, limit);
132
+ }
133
+ getMostAccessedKeys(limit = 10) {
134
+ const keyStats = new Map();
135
+ this.operations.forEach((op) => {
136
+ if (op.key) {
137
+ const stats = keyStats.get(op.key) || { count: 0, totalLatency: 0 };
138
+ stats.count++;
139
+ stats.totalLatency += op.latency;
140
+ keyStats.set(op.key, stats);
141
+ }
142
+ });
143
+ return Array.from(keyStats.entries())
144
+ .map(([key, stats]) => ({
145
+ key,
146
+ count: stats.count,
147
+ avgLatency: stats.totalLatency / stats.count,
148
+ }))
149
+ .sort((a, b) => b.count - a.count)
150
+ .slice(0, limit);
151
+ }
152
+ getErrorBreakdown() {
153
+ const errorStats = new Map();
154
+ this.operations.forEach((op) => {
155
+ if (op.error) {
156
+ const stats = errorStats.get(op.error) || {
157
+ count: 0,
158
+ lastOccurrence: op.timestamp,
159
+ };
160
+ stats.count++;
161
+ stats.lastOccurrence =
162
+ op.timestamp > stats.lastOccurrence
163
+ ? op.timestamp
164
+ : stats.lastOccurrence;
165
+ errorStats.set(op.error, stats);
166
+ }
167
+ });
168
+ return Array.from(errorStats.entries())
169
+ .map(([error, stats]) => ({
170
+ error,
171
+ count: stats.count,
172
+ lastOccurrence: stats.lastOccurrence,
173
+ }))
174
+ .sort((a, b) => b.count - a.count);
175
+ }
176
+ resetMetrics() {
177
+ this.operations.length = 0;
178
+ this.logger.log('Cache metrics reset');
179
+ this.emit('reset');
180
+ }
181
+ exportMetrics(format = 'json') {
182
+ const metrics = this.getMetrics();
183
+ if (format === 'prometheus') {
184
+ return this.toPrometheusFormat(metrics);
185
+ }
186
+ return JSON.stringify(metrics, null, 2);
187
+ }
188
+ cleanupOldRecords() {
189
+ const cutoff = new Date(Date.now() - this.maxAge);
190
+ const initialLength = this.operations.length;
191
+ for (let i = this.operations.length - 1; i >= 0; i--) {
192
+ if (this.operations[i].timestamp < cutoff) {
193
+ this.operations.splice(0, i + 1);
194
+ break;
195
+ }
196
+ }
197
+ const removed = initialLength - this.operations.length;
198
+ if (removed > 0) {
199
+ this.logger.debug(`Cleaned up ${removed} old cache operation records`);
200
+ }
201
+ }
202
+ createEmptyMetrics(start, end) {
203
+ return {
204
+ totalOperations: 0,
205
+ hits: 0,
206
+ misses: 0,
207
+ hitRate: 0,
208
+ avgLatency: 0,
209
+ minLatency: 0,
210
+ maxLatency: 0,
211
+ p95Latency: 0,
212
+ p99Latency: 0,
213
+ gets: 0,
214
+ sets: 0,
215
+ deletes: 0,
216
+ clears: 0,
217
+ totalKeys: 0,
218
+ totalSize: 0,
219
+ errors: 0,
220
+ errorRate: 0,
221
+ layerMetrics: {
222
+ cls: { hits: 0, misses: 0, avgLatency: 0 },
223
+ memory: { hits: 0, misses: 0, avgLatency: 0, size: 0 },
224
+ redis: { hits: 0, misses: 0, avgLatency: 0 },
225
+ },
226
+ timeWindow: {
227
+ start,
228
+ end,
229
+ duration: end.getTime() - start.getTime(),
230
+ },
231
+ };
232
+ }
233
+ calculateLayerMetrics(operations) {
234
+ const hits = operations.filter((op) => op.hit).length;
235
+ const misses = operations.filter((op) => !op.hit).length;
236
+ const latencies = operations.map((op) => op.latency);
237
+ return {
238
+ hits,
239
+ misses,
240
+ avgLatency: latencies.length > 0 ? this.average(latencies) : 0,
241
+ size: operations.length,
242
+ };
243
+ }
244
+ average(numbers) {
245
+ return numbers.length > 0
246
+ ? numbers.reduce((sum, num) => sum + num, 0) / numbers.length
247
+ : 0;
248
+ }
249
+ percentile(sortedNumbers, p) {
250
+ if (sortedNumbers.length === 0)
251
+ return 0;
252
+ const index = Math.ceil(sortedNumbers.length * p) - 1;
253
+ return sortedNumbers[Math.max(0, Math.min(index, sortedNumbers.length - 1))];
254
+ }
255
+ getUniqueKeyCount(operations) {
256
+ const keys = new Set();
257
+ operations.forEach((op) => {
258
+ if (op.key)
259
+ keys.add(op.key);
260
+ });
261
+ return keys.size;
262
+ }
263
+ estimateTotalSize(operations) {
264
+ const avgValueSize = 120;
265
+ return this.getUniqueKeyCount(operations) * avgValueSize;
266
+ }
267
+ toPrometheusFormat(metrics) {
268
+ const labels = {
269
+ layer: 'cls|memory|redis',
270
+ };
271
+ let output = '';
272
+ output += `# HELP cache_hit_rate Cache hit rate\n`;
273
+ output += `# TYPE cache_hit_rate gauge\n`;
274
+ output += `cache_hit_rate ${metrics.hitRate}\n`;
275
+ output += `# HELP cache_operations_total Total cache operations\n`;
276
+ output += `# TYPE cache_operations_total counter\n`;
277
+ output += `cache_operations_total{type="get"} ${metrics.gets}\n`;
278
+ output += `cache_operations_total{type="set"} ${metrics.sets}\n`;
279
+ output += `cache_operations_total{type="delete"} ${metrics.deletes}\n`;
280
+ output += `cache_operations_total{type="clear"} ${metrics.clears}\n`;
281
+ output += `# HELP cache_latency_ms Cache operation latency\n`;
282
+ output += `# TYPE cache_latency_ms histogram\n`;
283
+ output += `cache_latency_ms{quantile="0.5"} ${metrics.avgLatency}\n`;
284
+ output += `cache_latency_ms{quantile="0.95"} ${metrics.p95Latency}\n`;
285
+ output += `cache_latency_ms{quantile="0.99"} ${metrics.p99Latency}\n`;
286
+ Object.entries(metrics.layerMetrics).forEach(([layer, layerMetrics]) => {
287
+ output += `cache_layer_hits_total{layer="${layer}"} ${layerMetrics.hits}\n`;
288
+ output += `cache_layer_misses_total{layer="${layer}"} ${layerMetrics.misses}\n`;
289
+ output += `cache_layer_latency_ms{layer="${layer}"} ${layerMetrics.avgLatency}\n`;
290
+ });
291
+ return output;
292
+ }
293
+ };
294
+ exports.CacheMetricsService = CacheMetricsService;
295
+ exports.CacheMetricsService = CacheMetricsService = CacheMetricsService_1 = __decorate([
296
+ (0, common_1.Injectable)(),
297
+ __metadata("design:paramtypes", [])
298
+ ], CacheMetricsService);
@@ -0,0 +1,22 @@
1
+ export interface CacheSerializationOptions {
2
+ compress?: boolean;
3
+ compressThreshold?: number;
4
+ }
5
+ export interface SerializationResult {
6
+ data: Buffer;
7
+ compressed: boolean;
8
+ originalSize: number;
9
+ serializedSize: number;
10
+ }
11
+ export interface DeserializationResult<T> {
12
+ data: T;
13
+ wasCompressed: boolean;
14
+ }
15
+ export declare class CacheSerializationService {
16
+ private readonly logger;
17
+ serialize<T>(value: T, options?: CacheSerializationOptions): Promise<SerializationResult>;
18
+ deserialize<T>(buffer: Buffer): Promise<DeserializationResult<T>>;
19
+ private serializeWithDates;
20
+ private preProcessDates;
21
+ private deserializeWithDates;
22
+ }
@@ -0,0 +1,122 @@
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 __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
9
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
10
+ return new (P || (P = Promise))(function (resolve, reject) {
11
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
12
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
13
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
14
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
15
+ });
16
+ };
17
+ var CacheSerializationService_1;
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.CacheSerializationService = void 0;
20
+ const common_1 = require("@nestjs/common");
21
+ const zlib_1 = require("zlib");
22
+ const util_1 = require("util");
23
+ const gzipAsync = (0, util_1.promisify)(zlib_1.gzip);
24
+ const gunzipAsync = (0, util_1.promisify)(zlib_1.gunzip);
25
+ let CacheSerializationService = CacheSerializationService_1 = class CacheSerializationService {
26
+ constructor() {
27
+ this.logger = new common_1.Logger(CacheSerializationService_1.name);
28
+ }
29
+ serialize(value_1) {
30
+ return __awaiter(this, arguments, void 0, function* (value, options = {}) {
31
+ const { compress = false, compressThreshold = 1024 } = options;
32
+ try {
33
+ const serialized = this.serializeWithDates(value);
34
+ const originalSize = Buffer.byteLength(serialized, 'utf8');
35
+ let data;
36
+ let wasCompressed = false;
37
+ if (compress && originalSize >= compressThreshold) {
38
+ try {
39
+ data = yield gzipAsync(Buffer.from(serialized, 'utf8'));
40
+ wasCompressed = true;
41
+ }
42
+ catch (error) {
43
+ this.logger.warn('Compression failed, using uncompressed data:', error);
44
+ data = Buffer.from(serialized, 'utf8');
45
+ }
46
+ }
47
+ else {
48
+ data = Buffer.from(serialized, 'utf8');
49
+ }
50
+ return {
51
+ data,
52
+ compressed: wasCompressed,
53
+ originalSize,
54
+ serializedSize: data.length,
55
+ };
56
+ }
57
+ catch (error) {
58
+ this.logger.error('Serialization failed:', error);
59
+ throw new Error(`Failed to serialize cache value: ${error instanceof Error ? error.message : String(error)}`);
60
+ }
61
+ });
62
+ }
63
+ deserialize(buffer) {
64
+ return __awaiter(this, void 0, void 0, function* () {
65
+ try {
66
+ let dataString;
67
+ let wasCompressed = false;
68
+ if (buffer.length >= 2 && buffer[0] === 0x1f && buffer[1] === 0x8b) {
69
+ dataString = (yield gunzipAsync(buffer)).toString('utf8');
70
+ wasCompressed = true;
71
+ }
72
+ else {
73
+ dataString = buffer.toString('utf8');
74
+ }
75
+ const data = this.deserializeWithDates(dataString);
76
+ return {
77
+ data,
78
+ wasCompressed,
79
+ };
80
+ }
81
+ catch (error) {
82
+ this.logger.error('Deserialization failed:', error);
83
+ throw new Error(`Failed to deserialize cache value: ${error instanceof Error ? error.message : String(error)}`);
84
+ }
85
+ });
86
+ }
87
+ serializeWithDates(value) {
88
+ const processed = this.preProcessDates(value);
89
+ return JSON.stringify(processed);
90
+ }
91
+ preProcessDates(obj) {
92
+ if (obj === null || obj === undefined) {
93
+ return obj;
94
+ }
95
+ if (obj instanceof Date) {
96
+ return { __type: 'Date', value: obj.toISOString() };
97
+ }
98
+ if (Array.isArray(obj)) {
99
+ return obj.map((item) => this.preProcessDates(item));
100
+ }
101
+ if (typeof obj === 'object') {
102
+ const processed = {};
103
+ for (const [key, value] of Object.entries(obj)) {
104
+ processed[key] = this.preProcessDates(value);
105
+ }
106
+ return processed;
107
+ }
108
+ return obj;
109
+ }
110
+ deserializeWithDates(dataString) {
111
+ return JSON.parse(dataString, (key, val) => {
112
+ if (val && typeof val === 'object' && val.__type === 'Date') {
113
+ return new Date(val.value);
114
+ }
115
+ return val;
116
+ });
117
+ }
118
+ };
119
+ exports.CacheSerializationService = CacheSerializationService;
120
+ exports.CacheSerializationService = CacheSerializationService = CacheSerializationService_1 = __decorate([
121
+ (0, common_1.Injectable)()
122
+ ], CacheSerializationService);
@@ -0,0 +1,2 @@
1
+ export declare const CACHE_COMPRESSION_ENABLED: unique symbol;
2
+ export declare const CACHE_COMPRESSION_THRESHOLD: unique symbol;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CACHE_COMPRESSION_THRESHOLD = exports.CACHE_COMPRESSION_ENABLED = void 0;
4
+ exports.CACHE_COMPRESSION_ENABLED = Symbol('CACHE_COMPRESSION_ENABLED');
5
+ exports.CACHE_COMPRESSION_THRESHOLD = Symbol('CACHE_COMPRESSION_THRESHOLD');
@@ -0,0 +1,35 @@
1
+ import { CacheService } from './cache.service';
2
+ export interface CacheHealthResult {
3
+ status: 'healthy' | 'degraded' | 'unhealthy';
4
+ layers: {
5
+ cls: {
6
+ available: boolean;
7
+ latency?: number;
8
+ error?: string;
9
+ };
10
+ memory: {
11
+ available: boolean;
12
+ latency?: number;
13
+ size?: number;
14
+ error?: string;
15
+ };
16
+ redis: {
17
+ available: boolean;
18
+ latency?: number;
19
+ error?: string;
20
+ };
21
+ };
22
+ timestamp: Date;
23
+ overallLatency: number;
24
+ }
25
+ export declare class CacheHealthChecker {
26
+ private readonly cacheService;
27
+ private readonly logger;
28
+ constructor(cacheService: CacheService);
29
+ checkHealth(): Promise<CacheHealthResult>;
30
+ getDetailedStats(): Promise<any>;
31
+ private checkClsHealth;
32
+ private checkMemoryHealth;
33
+ private checkRedisHealth;
34
+ private generateRecommendations;
35
+ }
@@ -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);