pp-command-bus 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/command-bus/command-bus.spec.js +26 -8
  2. package/dist/command-bus/command-bus.spec.js.map +1 -1
  3. package/dist/command-bus/config/auto-config-optimizer.d.ts +35 -0
  4. package/dist/command-bus/config/auto-config-optimizer.js +52 -0
  5. package/dist/command-bus/config/auto-config-optimizer.js.map +1 -0
  6. package/dist/command-bus/config/auto-config-optimizer.spec.d.ts +1 -0
  7. package/dist/command-bus/config/auto-config-optimizer.spec.js +42 -0
  8. package/dist/command-bus/config/auto-config-optimizer.spec.js.map +1 -0
  9. package/dist/command-bus/config/command-bus-config.d.ts +6 -0
  10. package/dist/command-bus/config/command-bus-config.js +33 -6
  11. package/dist/command-bus/config/command-bus-config.js.map +1 -1
  12. package/dist/command-bus/config/command-bus-config.spec.js +62 -2
  13. package/dist/command-bus/config/command-bus-config.spec.js.map +1 -1
  14. package/dist/command-bus/index.d.ts +4 -0
  15. package/dist/command-bus/index.js +21 -6
  16. package/dist/command-bus/index.js.map +1 -1
  17. package/dist/command-bus/job/job-processor.d.ts +2 -0
  18. package/dist/command-bus/job/job-processor.js +50 -2
  19. package/dist/command-bus/job/job-processor.js.map +1 -1
  20. package/dist/command-bus/job/job-processor.spec.js +13 -0
  21. package/dist/command-bus/job/job-processor.spec.js.map +1 -1
  22. package/dist/command-bus/queue/queue-manager.d.ts +35 -3
  23. package/dist/command-bus/queue/queue-manager.js +107 -4
  24. package/dist/command-bus/queue/queue-manager.js.map +1 -1
  25. package/dist/command-bus/queue/queue-manager.spec.js +155 -3
  26. package/dist/command-bus/queue/queue-manager.spec.js.map +1 -1
  27. package/dist/command-bus/rpc/rpc-coordinator.js +6 -1
  28. package/dist/command-bus/rpc/rpc-coordinator.js.map +1 -1
  29. package/dist/command-bus/rpc/rpc-coordinator.spec.js +211 -0
  30. package/dist/command-bus/rpc/rpc-coordinator.spec.js.map +1 -1
  31. package/dist/command-bus/worker/index.d.ts +6 -1
  32. package/dist/command-bus/worker/index.js +8 -2
  33. package/dist/command-bus/worker/index.js.map +1 -1
  34. package/dist/command-bus/worker/worker-benchmark.d.ts +70 -0
  35. package/dist/command-bus/worker/worker-benchmark.js +210 -0
  36. package/dist/command-bus/worker/worker-benchmark.js.map +1 -0
  37. package/dist/command-bus/worker/worker-benchmark.spec.d.ts +1 -0
  38. package/dist/command-bus/worker/worker-benchmark.spec.js +300 -0
  39. package/dist/command-bus/worker/worker-benchmark.spec.js.map +1 -0
  40. package/dist/command-bus/worker/worker-metrics-collector.d.ts +87 -0
  41. package/dist/command-bus/worker/worker-metrics-collector.js +259 -0
  42. package/dist/command-bus/worker/worker-metrics-collector.js.map +1 -0
  43. package/dist/command-bus/worker/worker-metrics-collector.spec.d.ts +1 -0
  44. package/dist/command-bus/worker/worker-metrics-collector.spec.js +315 -0
  45. package/dist/command-bus/worker/worker-metrics-collector.spec.js.map +1 -0
  46. package/dist/command-bus/worker/worker-orchestrator.d.ts +29 -4
  47. package/dist/command-bus/worker/worker-orchestrator.js +198 -27
  48. package/dist/command-bus/worker/worker-orchestrator.js.map +1 -1
  49. package/dist/command-bus/worker/worker-orchestrator.spec.js +473 -52
  50. package/dist/command-bus/worker/worker-orchestrator.spec.js.map +1 -1
  51. package/dist/examples/auto-config.demo.d.ts +9 -0
  52. package/dist/examples/auto-config.demo.js +106 -0
  53. package/dist/examples/auto-config.demo.js.map +1 -0
  54. package/dist/examples/rpc-throughput.demo.d.ts +5 -0
  55. package/dist/examples/rpc-throughput.demo.js +326 -0
  56. package/dist/examples/rpc-throughput.demo.js.map +1 -0
  57. package/dist/pp-command-bus-1.1.0.tgz +0 -0
  58. package/package.json +3 -2
  59. package/dist/pp-command-bus-1.0.2.tgz +0 -0
@@ -0,0 +1,210 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const auto_config_optimizer_1 = __importDefault(require("../config/auto-config-optimizer"));
16
+ const command_1 = __importDefault(require("../command"));
17
+ const crypto_1 = require("crypto");
18
+ /**
19
+ * Testowa komenda dla benchmarku
20
+ */
21
+ class BenchmarkTestCommand extends command_1.default {
22
+ constructor(testId) {
23
+ super();
24
+ this.testId = testId;
25
+ }
26
+ }
27
+ /**
28
+ * Szybki benchmark workera (~1-2s)
29
+ * Mierzy latencję Redis, przepustowość workera i czas przetwarzania handlera
30
+ */
31
+ class WorkerBenchmark {
32
+ constructor(commandName, redisConnection, jobProcessor, logger) {
33
+ this.commandName = commandName;
34
+ this.redisConnection = redisConnection;
35
+ this.jobProcessor = jobProcessor;
36
+ this.logger = logger;
37
+ }
38
+ /**
39
+ * Uruchamia benchmark i zwraca wyniki z rekomendowanym concurrency
40
+ */
41
+ run() {
42
+ return __awaiter(this, void 0, void 0, function* () {
43
+ this.logger.log(`Rozpoczynam benchmark dla ${this.commandName}`, {
44
+ commandName: this.commandName,
45
+ timestamp: new Date().toISOString(),
46
+ });
47
+ const startTime = Date.now();
48
+ // Zbierz metryki
49
+ const redisLatencyMs = yield this.measureRedisLatency();
50
+ const handlerAvgTimeMs = yield this.measureHandlerTime();
51
+ const systemInfo = auto_config_optimizer_1.default.getSystemInfo();
52
+ // Oblicz rekomendowane concurrency
53
+ const recommendedConcurrency = this.calculateConcurrency(redisLatencyMs, handlerAvgTimeMs, systemInfo);
54
+ const totalTime = Date.now() - startTime;
55
+ const result = {
56
+ redisLatencyMs,
57
+ workerThroughputJobsPerSec: 0, // Pominiemy throughput test dla prostoty
58
+ handlerAvgTimeMs,
59
+ systemInfo,
60
+ recommendedConcurrency,
61
+ };
62
+ this.logger.log('Benchmark zakończony', Object.assign(Object.assign({ commandName: this.commandName }, result), { benchmarkDurationMs: totalTime, timestamp: new Date().toISOString() }));
63
+ return result;
64
+ });
65
+ }
66
+ /**
67
+ * Mierzy latencję Redis (ping + set/get)
68
+ * @returns Średnia latencja w ms
69
+ */
70
+ measureRedisLatency() {
71
+ return __awaiter(this, void 0, void 0, function* () {
72
+ const measurements = [];
73
+ try {
74
+ // 10 prób ping
75
+ for (let i = 0; i < 10; i++) {
76
+ const start = Date.now();
77
+ yield this.redisConnection.ping();
78
+ measurements.push(Date.now() - start);
79
+ }
80
+ // 10 prób set/get
81
+ for (let i = 0; i < 10; i++) {
82
+ const key = `{benchmark:${this.commandName}:${i}:${(0, crypto_1.randomUUID)()}}`;
83
+ const value = `test-value-${i}`;
84
+ const setStart = Date.now();
85
+ yield this.redisConnection.set(key, value);
86
+ measurements.push(Date.now() - setStart);
87
+ const getStart = Date.now();
88
+ yield this.redisConnection.get(key);
89
+ measurements.push(Date.now() - getStart);
90
+ yield this.redisConnection.del(key);
91
+ }
92
+ return this.calculateAverage(measurements);
93
+ }
94
+ catch (error) {
95
+ this.logger.error('Błąd podczas pomiaru latencji Redis', {
96
+ commandName: this.commandName,
97
+ error: error instanceof Error ? error.message : String(error),
98
+ });
99
+ // Fallback: zakładamy średnią latencję
100
+ return 5;
101
+ }
102
+ });
103
+ }
104
+ /**
105
+ * Mierzy średni czas przetwarzania handlera
106
+ * Symuluje losowy delay 50-10000ms dla realistycznego benchmarku
107
+ * @returns Średni czas w ms
108
+ */
109
+ measureHandlerTime() {
110
+ return __awaiter(this, void 0, void 0, function* () {
111
+ const measurements = [];
112
+ try {
113
+ // 100 wywołań testowych
114
+ for (let i = 0; i < 100; i++) {
115
+ const testCommand = new BenchmarkTestCommand(i);
116
+ const mockJob = {
117
+ id: `{benchmark-job-${i}:${(0, crypto_1.randomUUID)()}}`,
118
+ data: testCommand,
119
+ opts: {},
120
+ attemptsMade: 0,
121
+ };
122
+ const start = Date.now();
123
+ try {
124
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
125
+ yield this.jobProcessor.process(mockJob, this.commandName);
126
+ }
127
+ catch (_a) {
128
+ // Ignoruj błędy handlera w benchmarku
129
+ }
130
+ const duration = Date.now() - start;
131
+ // Symuluj losowy delay handlera (50-5000ms)
132
+ const randomDelay = this.getRandomDelay(50, 5000);
133
+ const totalDuration = duration + randomDelay;
134
+ if (totalDuration > 0) {
135
+ measurements.push(totalDuration);
136
+ }
137
+ }
138
+ // Jeśli nie udało się zmierzyć, zwróć fallback
139
+ if (measurements.length === 0) {
140
+ return 50;
141
+ }
142
+ return this.calculateAverage(measurements);
143
+ }
144
+ catch (error) {
145
+ this.logger.error('Błąd podczas pomiaru czasu handlera', {
146
+ commandName: this.commandName,
147
+ error: error instanceof Error ? error.message : String(error),
148
+ });
149
+ // Fallback: zakładamy średni czas
150
+ return 50;
151
+ }
152
+ });
153
+ }
154
+ /**
155
+ * Oblicza rekomendowane concurrency na podstawie metryk
156
+ */
157
+ calculateConcurrency(redisLatencyMs, handlerAvgTimeMs, systemInfo) {
158
+ const { cpuCount, freeMemoryGB } = systemInfo;
159
+ // Bazowy concurrency dla I/O-heavy workload
160
+ let baseConcurrency = cpuCount * 50;
161
+ // Korekta dla dostępnej pamięci RAM
162
+ if (freeMemoryGB < 2) {
163
+ baseConcurrency *= 0.3;
164
+ }
165
+ else if (freeMemoryGB < 4) {
166
+ baseConcurrency *= 0.5;
167
+ }
168
+ else if (freeMemoryGB >= 16) {
169
+ baseConcurrency *= 1.2;
170
+ }
171
+ let factor = 1.0;
172
+ // Korekta dla latencji Redis - bardziej agresywna
173
+ if (redisLatencyMs < 1) {
174
+ factor *= 1.5; // Bardzo szybki Redis
175
+ }
176
+ else if (redisLatencyMs > 10) {
177
+ factor *= 0.3; // Wolny Redis - mocniejsza redukcja
178
+ }
179
+ // Korekta dla czasu handlera - bardziej agresywna
180
+ if (handlerAvgTimeMs < 10) {
181
+ factor *= 1.2; // Szybki handler
182
+ }
183
+ else if (handlerAvgTimeMs > 100) {
184
+ factor *= 0.5; // Wolny handler - mocniejsza redukcja
185
+ }
186
+ const recommendedConcurrency = Math.round(baseConcurrency * factor);
187
+ // Zapewnij sensowne granice: min 10, max 2000
188
+ return Math.max(10, Math.min(2000, recommendedConcurrency));
189
+ }
190
+ /**
191
+ * Oblicza średnią z tablicy wartości
192
+ */
193
+ calculateAverage(values) {
194
+ if (values.length === 0)
195
+ return 0;
196
+ const sum = values.reduce((acc, val) => acc + val, 0);
197
+ return Number((sum / values.length).toFixed(2));
198
+ }
199
+ /**
200
+ * Generuje losowy delay w zadanym zakresie
201
+ * @param min - Minimalna wartość w ms
202
+ * @param max - Maksymalna wartość w ms
203
+ * @returns Losowy delay w ms
204
+ */
205
+ getRandomDelay(min, max) {
206
+ return Math.floor(Math.random() * (max - min + 1)) + min;
207
+ }
208
+ }
209
+ exports.default = WorkerBenchmark;
210
+ //# sourceMappingURL=worker-benchmark.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-benchmark.js","sourceRoot":"","sources":["../../../src/command-bus/worker/worker-benchmark.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAGA,4FAAuF;AACvF,yDAAiC;AACjC,mCAAoC;AA+BpC;;GAEG;AACH,MAAM,oBAAqB,SAAQ,iBAAO;IACxC,YAA4B,MAAc;QACxC,KAAK,EAAE,CAAC;QADkB,WAAM,GAAN,MAAM,CAAQ;IAE1C,CAAC;CACF;AAED;;;GAGG;AACH,MAAqB,eAAe;IAClC,YACmB,WAAmB,EACnB,eAAsB,EACtB,YAA0B,EAC1B,MAAe;QAHf,gBAAW,GAAX,WAAW,CAAQ;QACnB,oBAAe,GAAf,eAAe,CAAO;QACtB,iBAAY,GAAZ,YAAY,CAAc;QAC1B,WAAM,GAAN,MAAM,CAAS;IAC/B,CAAC;IAEJ;;OAEG;IACU,GAAG;;YACd,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,6BAA6B,IAAI,CAAC,WAAW,EAAE,EAAE;gBAC/D,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC,CAAC,CAAC;YAEH,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAE7B,iBAAiB;YACjB,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACxD,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACzD,MAAM,UAAU,GAAG,+BAAmB,CAAC,aAAa,EAAE,CAAC;YAEvD,mCAAmC;YACnC,MAAM,sBAAsB,GAAG,IAAI,CAAC,oBAAoB,CACtD,cAAc,EACd,gBAAgB,EAChB,UAAU,CACX,CAAC;YAEF,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAEzC,MAAM,MAAM,GAAoB;gBAC9B,cAAc;gBACd,0BAA0B,EAAE,CAAC,EAAE,yCAAyC;gBACxE,gBAAgB;gBAChB,UAAU;gBACV,sBAAsB;aACvB,CAAC;YAEF,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,sBAAsB,gCACpC,WAAW,EAAE,IAAI,CAAC,WAAW,IAC1B,MAAM,KACT,mBAAmB,EAAE,SAAS,EAC9B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,IACnC,CAAC;YAEH,OAAO,MAAM,CAAC;QAChB,CAAC;KAAA;IAED;;;OAGG;IACW,mBAAmB;;YAC/B,MAAM,YAAY,GAAa,EAAE,CAAC;YAElC,IAAI,CAAC;gBACH,eAAe;gBACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;oBACzB,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;oBAClC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC;gBACxC,CAAC;gBAED,kBAAkB;gBAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC5B,MAAM,GAAG,GAAG,cAAc,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,IAAA,mBAAU,GAAE,GAAG,CAAC;oBACnE,MAAM,KAAK,GAAG,cAAc,CAAC,EAAE,CAAC;oBAEhC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;oBAC5B,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;oBAC3C,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,CAAC;oBAEzC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;oBAC5B,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;oBACpC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,CAAC;oBACzC,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACtC,CAAC;gBAED,OAAO,IAAI,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;YAC7C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,qCAAqC,EAAE;oBACvD,WAAW,EAAE,IAAI,CAAC,WAAW;oBAC7B,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;iBAC9D,CAAC,CAAC;gBACH,uCAAuC;gBACvC,OAAO,CAAC,CAAC;YACX,CAAC;QACH,CAAC;KAAA;IAED;;;;OAIG;IACW,kBAAkB;;YAC9B,MAAM,YAAY,GAAa,EAAE,CAAC;YAElC,IAAI,CAAC;gBACH,wBAAwB;gBACxB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC7B,MAAM,WAAW,GAAG,IAAI,oBAAoB,CAAC,CAAC,CAAC,CAAC;oBAChD,MAAM,OAAO,GAAG;wBACd,EAAE,EAAE,kBAAkB,CAAC,IAAI,IAAA,mBAAU,GAAE,GAAG;wBAC1C,IAAI,EAAE,WAAW;wBACjB,IAAI,EAAE,EAAE;wBACR,YAAY,EAAE,CAAC;qBAChB,CAAC;oBAEF,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;oBACzB,IAAI,CAAC;wBACH,8DAA8D;wBAC9D,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,OAAc,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;oBACpE,CAAC;oBAAC,WAAM,CAAC;wBACP,sCAAsC;oBACxC,CAAC;oBACD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;oBAEpC,4CAA4C;oBAC5C,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;oBAClD,MAAM,aAAa,GAAG,QAAQ,GAAG,WAAW,CAAC;oBAE7C,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;wBACtB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;oBACnC,CAAC;gBACH,CAAC;gBAED,+CAA+C;gBAC/C,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC9B,OAAO,EAAE,CAAC;gBACZ,CAAC;gBAED,OAAO,IAAI,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;YAC7C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,qCAAqC,EAAE;oBACvD,WAAW,EAAE,IAAI,CAAC,WAAW;oBAC7B,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;iBAC9D,CAAC,CAAC;gBACH,kCAAkC;gBAClC,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;KAAA;IAED;;OAEG;IACK,oBAAoB,CAC1B,cAAsB,EACtB,gBAAwB,EACxB,UAAsB;QAEtB,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,UAAU,CAAC;QAE9C,4CAA4C;QAC5C,IAAI,eAAe,GAAG,QAAQ,GAAG,EAAE,CAAC;QAEpC,oCAAoC;QACpC,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;YACrB,eAAe,IAAI,GAAG,CAAC;QACzB,CAAC;aAAM,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;YAC5B,eAAe,IAAI,GAAG,CAAC;QACzB,CAAC;aAAM,IAAI,YAAY,IAAI,EAAE,EAAE,CAAC;YAC9B,eAAe,IAAI,GAAG,CAAC;QACzB,CAAC;QAED,IAAI,MAAM,GAAG,GAAG,CAAC;QAEjB,kDAAkD;QAClD,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,GAAG,CAAC,CAAC,sBAAsB;QACvC,CAAC;aAAM,IAAI,cAAc,GAAG,EAAE,EAAE,CAAC;YAC/B,MAAM,IAAI,GAAG,CAAC,CAAC,oCAAoC;QACrD,CAAC;QAED,kDAAkD;QAClD,IAAI,gBAAgB,GAAG,EAAE,EAAE,CAAC;YAC1B,MAAM,IAAI,GAAG,CAAC,CAAC,iBAAiB;QAClC,CAAC;aAAM,IAAI,gBAAgB,GAAG,GAAG,EAAE,CAAC;YAClC,MAAM,IAAI,GAAG,CAAC,CAAC,sCAAsC;QACvD,CAAC;QAED,MAAM,sBAAsB,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,GAAG,MAAM,CAAC,CAAC;QAEpE,8CAA8C;QAC9C,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED;;OAEG;IACK,gBAAgB,CAAC,MAAgB;QACvC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QAClC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC;QACtD,OAAO,MAAM,CAAC,CAAC,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC;IAED;;;;;OAKG;IACK,cAAc,CAAC,GAAW,EAAE,GAAW;QAC7C,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;IAC3D,CAAC;CACF;AA/MD,kCA+MC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,300 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ var __importDefault = (this && this.__importDefault) || function (mod) {
45
+ return (mod && mod.__esModule) ? mod : { "default": mod };
46
+ };
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ const worker_benchmark_1 = __importDefault(require("./worker-benchmark"));
49
+ const os = __importStar(require("os"));
50
+ // Mock os module
51
+ jest.mock('os');
52
+ describe('WorkerBenchmark', () => {
53
+ let mockRedis;
54
+ let mockJobProcessor;
55
+ let mockLogger;
56
+ let benchmark;
57
+ beforeEach(() => {
58
+ // Mock Redis
59
+ mockRedis = {
60
+ ping: jest.fn().mockResolvedValue('PONG'),
61
+ set: jest.fn().mockResolvedValue('OK'),
62
+ get: jest.fn().mockResolvedValue('test-value'),
63
+ del: jest.fn().mockResolvedValue(1),
64
+ };
65
+ // Mock JobProcessor
66
+ mockJobProcessor = {
67
+ process: jest.fn().mockResolvedValue({ success: true }),
68
+ };
69
+ // Mock Logger
70
+ mockLogger = {
71
+ log: jest.fn(),
72
+ debug: jest.fn(),
73
+ error: jest.fn(),
74
+ warn: jest.fn(),
75
+ };
76
+ // Mock os functions (używamy availableParallelism zamiast cpus)
77
+ os.availableParallelism.mockReturnValue(8); // 8 cores
78
+ os.freemem.mockReturnValue(8 * 1024 * 1024 * 1024); // 8GB free
79
+ os.totalmem.mockReturnValue(16 * 1024 * 1024 * 1024); // 16GB total
80
+ });
81
+ describe('run', () => {
82
+ it('powinien uruchomić pełny benchmark i zwrócić wyniki', () => __awaiter(void 0, void 0, void 0, function* () {
83
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
84
+ const result = yield benchmark.run();
85
+ expect(result).toEqual(expect.objectContaining({
86
+ redisLatencyMs: expect.any(Number),
87
+ workerThroughputJobsPerSec: 0, // Pomijamy throughput test
88
+ handlerAvgTimeMs: expect.any(Number),
89
+ systemInfo: expect.objectContaining({
90
+ cpuCount: 8,
91
+ freeMemoryGB: expect.any(Number),
92
+ totalMemoryGB: expect.any(Number),
93
+ }),
94
+ recommendedConcurrency: expect.any(Number),
95
+ }));
96
+ expect(mockLogger.log).toHaveBeenCalledWith('Rozpoczynam benchmark dla TestCommand', expect.any(Object));
97
+ expect(mockLogger.log).toHaveBeenCalledWith('Benchmark zakończony', expect.any(Object));
98
+ }));
99
+ it('powinien zalogować czas trwania benchmarku', () => __awaiter(void 0, void 0, void 0, function* () {
100
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
101
+ yield benchmark.run();
102
+ expect(mockLogger.log).toHaveBeenCalledWith('Benchmark zakończony', expect.objectContaining({
103
+ benchmarkDurationMs: expect.any(Number),
104
+ }));
105
+ }));
106
+ });
107
+ describe('measureRedisLatency', () => {
108
+ it('powinien zmierzyć latencję Redis (ping + set/get)', () => __awaiter(void 0, void 0, void 0, function* () {
109
+ // Symuluj opóźnienia Redis
110
+ mockRedis.ping.mockImplementation(() => new Promise((resolve) => setTimeout(resolve, 2)));
111
+ mockRedis.set.mockImplementation(() => new Promise((resolve) => setTimeout(resolve, 3)));
112
+ mockRedis.get.mockImplementation(() => new Promise((resolve) => setTimeout(resolve, 1)));
113
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
114
+ const result = yield benchmark.run();
115
+ // Sprawdź że latencja została zmierzona
116
+ expect(result.redisLatencyMs).toBeGreaterThan(0);
117
+ // Sprawdź że wykonano odpowiednią liczbę operacji
118
+ expect(mockRedis.ping).toHaveBeenCalledTimes(10); // 10 ping
119
+ expect(mockRedis.set).toHaveBeenCalledTimes(10); // 10 set
120
+ expect(mockRedis.get).toHaveBeenCalledTimes(10); // 10 get
121
+ expect(mockRedis.del).toHaveBeenCalledTimes(10); // 10 del (cleanup)
122
+ }));
123
+ it('powinien użyć fallback latencji gdy Redis zwraca błąd', () => __awaiter(void 0, void 0, void 0, function* () {
124
+ mockRedis.ping.mockRejectedValue(new Error('Redis connection error'));
125
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
126
+ const result = yield benchmark.run();
127
+ // Fallback latencja: 5ms
128
+ expect(result.redisLatencyMs).toBe(5);
129
+ expect(mockLogger.error).toHaveBeenCalledWith('Błąd podczas pomiaru latencji Redis', expect.objectContaining({
130
+ commandName: 'TestCommand',
131
+ error: 'Redis connection error',
132
+ }));
133
+ }));
134
+ it('powinien używać unikalnych kluczy Redis dla każdego pomiaru', () => __awaiter(void 0, void 0, void 0, function* () {
135
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
136
+ yield benchmark.run();
137
+ // Sprawdź że klucze są unikalne (zawierają UUID)
138
+ const setCalls = mockRedis.set.mock.calls;
139
+ const keys = setCalls.map((call) => call[0]);
140
+ // Wszystkie klucze powinny być różne
141
+ const uniqueKeys = new Set(keys);
142
+ expect(uniqueKeys.size).toBe(keys.length);
143
+ // Klucze powinny mieć format: {benchmark:TestCommand:i:uuid}
144
+ keys.forEach((key) => {
145
+ expect(key).toMatch(/^{benchmark:TestCommand:\d+:[a-f0-9-]+}$/);
146
+ });
147
+ }));
148
+ });
149
+ describe('measureHandlerTime', () => {
150
+ it('powinien zmierzyć średni czas przetwarzania handlera', () => __awaiter(void 0, void 0, void 0, function* () {
151
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
152
+ const result = yield benchmark.run();
153
+ // Sprawdź że czas handlera został zmierzony
154
+ expect(result.handlerAvgTimeMs).toBeGreaterThan(0);
155
+ // Sprawdź że wykonano 100 wywołań
156
+ expect(mockJobProcessor.process).toHaveBeenCalledTimes(100);
157
+ }));
158
+ it('powinien symulować losowy delay handlera (50-5000ms)', () => __awaiter(void 0, void 0, void 0, function* () {
159
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
160
+ const result = yield benchmark.run();
161
+ // Czas powinien być w zakresie min 50ms (bez błędów handlera)
162
+ expect(result.handlerAvgTimeMs).toBeGreaterThanOrEqual(50);
163
+ }));
164
+ it('powinien ignorować błędy handlera w benchmarku', () => __awaiter(void 0, void 0, void 0, function* () {
165
+ mockJobProcessor.process.mockRejectedValue(new Error('Handler error'));
166
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
167
+ const result = yield benchmark.run();
168
+ // Benchmark powinien zakończyć się pomyślnie mimo błędów handlera
169
+ expect(result.handlerAvgTimeMs).toBeGreaterThanOrEqual(0);
170
+ }));
171
+ it('powinien użyć fallback czasu gdy brak pomiarów', () => __awaiter(void 0, void 0, void 0, function* () {
172
+ // Symuluj scenariusz gdzie wszystkie pomiary są nieprawidłowe
173
+ mockJobProcessor.process.mockImplementation(() => {
174
+ throw new Error('Critical error');
175
+ });
176
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
177
+ const result = yield benchmark.run();
178
+ // Fallback: 50ms
179
+ expect(result.handlerAvgTimeMs).toBeGreaterThanOrEqual(50);
180
+ }));
181
+ });
182
+ describe('calculateConcurrency', () => {
183
+ it('powinien obliczyć bazowy concurrency (cpuCount * 50)', () => __awaiter(void 0, void 0, void 0, function* () {
184
+ // 8 cores * 50 = 400
185
+ os.availableParallelism.mockReturnValue(8);
186
+ os.freemem.mockReturnValue(8 * 1024 * 1024 * 1024); // 8GB
187
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
188
+ const result = yield benchmark.run();
189
+ // Bazowy: 8 * 50 = 400
190
+ // Z korektami powinien być w rozsądnym zakresie
191
+ expect(result.recommendedConcurrency).toBeGreaterThanOrEqual(10);
192
+ expect(result.recommendedConcurrency).toBeLessThanOrEqual(2000);
193
+ }));
194
+ it('powinien zastosować korektę dla niskiej RAM (< 2GB)', () => __awaiter(void 0, void 0, void 0, function* () {
195
+ os.availableParallelism.mockReturnValue(8);
196
+ os.freemem.mockReturnValue(1.5 * 1024 * 1024 * 1024); // 1.5GB
197
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
198
+ const result = yield benchmark.run();
199
+ // Bazowy: 8 * 50 = 400
200
+ // Korekta < 2GB: * 0.3 = 120
201
+ // Z innymi korektami może być jeszcze niższy lub wyższy
202
+ expect(result.recommendedConcurrency).toBeGreaterThanOrEqual(10);
203
+ }));
204
+ it('powinien zastosować korektę dla średniej RAM (< 4GB)', () => __awaiter(void 0, void 0, void 0, function* () {
205
+ os.availableParallelism.mockReturnValue(8);
206
+ os.freemem.mockReturnValue(3 * 1024 * 1024 * 1024); // 3GB
207
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
208
+ const result = yield benchmark.run();
209
+ // Bazowy: 8 * 50 = 400
210
+ // Korekta < 4GB: * 0.5 = 200
211
+ expect(result.recommendedConcurrency).toBeGreaterThanOrEqual(10);
212
+ }));
213
+ it('powinien zastosować korektę dla wysokiej RAM (>= 16GB)', () => __awaiter(void 0, void 0, void 0, function* () {
214
+ os.availableParallelism.mockReturnValue(8);
215
+ os.freemem.mockReturnValue(20 * 1024 * 1024 * 1024); // 20GB
216
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
217
+ const result = yield benchmark.run();
218
+ // Bazowy: 8 * 50 = 400
219
+ // Korekta >= 16GB: * 1.2 = 480
220
+ expect(result.recommendedConcurrency).toBeGreaterThanOrEqual(10);
221
+ }));
222
+ it('powinien zwiększyć concurrency dla szybkiego Redis (< 1ms)', () => __awaiter(void 0, void 0, void 0, function* () {
223
+ // Symuluj bardzo szybki Redis
224
+ mockRedis.ping.mockImplementation(() => Promise.resolve('PONG'));
225
+ mockRedis.set.mockImplementation(() => Promise.resolve('OK'));
226
+ mockRedis.get.mockImplementation(() => Promise.resolve('value'));
227
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
228
+ const result = yield benchmark.run();
229
+ // Redis latency powinno być < 1ms, co daje factor * 1.5
230
+ expect(result.redisLatencyMs).toBeLessThan(1);
231
+ expect(result.recommendedConcurrency).toBeGreaterThanOrEqual(10);
232
+ }));
233
+ it('powinien zmniejszyć concurrency dla wolnego Redis (> 10ms)', () => __awaiter(void 0, void 0, void 0, function* () {
234
+ // Symuluj wolny Redis - wszystkie operacje opóźnione
235
+ mockRedis.ping.mockImplementation(() => new Promise((resolve) => setTimeout(() => resolve('PONG'), 15)));
236
+ mockRedis.set.mockImplementation(() => new Promise((resolve) => setTimeout(() => resolve('OK'), 15)));
237
+ mockRedis.get.mockImplementation(() => new Promise((resolve) => setTimeout(() => resolve('value'), 15)));
238
+ // Ustaw wystarczające zasoby żeby nie było zbyt dużej redukcji
239
+ os.availableParallelism.mockReturnValue(8);
240
+ os.freemem.mockReturnValue(8 * 1024 * 1024 * 1024); // 8GB
241
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
242
+ const result = yield benchmark.run();
243
+ // Redis latency > 10ms, co daje factor * 0.3, ale limity zapewniają min 10
244
+ expect(result.redisLatencyMs).toBeGreaterThan(10);
245
+ expect(result.recommendedConcurrency).toBeGreaterThanOrEqual(10);
246
+ }));
247
+ it('powinien zastosować limity: min 10, max 2000', () => __awaiter(void 0, void 0, void 0, function* () {
248
+ // Przypadek 1: Bardzo niska konfiguracja
249
+ os.availableParallelism.mockReturnValue(1); // 1 core
250
+ os.freemem.mockReturnValue(0.5 * 1024 * 1024 * 1024); // 0.5GB
251
+ mockRedis.ping.mockImplementation(() => new Promise((resolve) => setTimeout(() => resolve('PONG'), 50)));
252
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
253
+ const result1 = yield benchmark.run();
254
+ // Minimum 10
255
+ expect(result1.recommendedConcurrency).toBeGreaterThanOrEqual(10);
256
+ // Przypadek 2: Bardzo wysoka konfiguracja
257
+ os.availableParallelism.mockReturnValue(64); // 64 cores
258
+ os.freemem.mockReturnValue(128 * 1024 * 1024 * 1024); // 128GB
259
+ mockRedis.ping.mockResolvedValue('PONG'); // Natychmiastowy ping
260
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
261
+ const result2 = yield benchmark.run();
262
+ // Maximum 2000
263
+ expect(result2.recommendedConcurrency).toBeLessThanOrEqual(2000);
264
+ }));
265
+ });
266
+ describe('calculateAverage', () => {
267
+ it('powinien obliczyć średnią z wartości', () => __awaiter(void 0, void 0, void 0, function* () {
268
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
269
+ const result = yield benchmark.run();
270
+ // Sprawdź że średnie są zaokrąglone do 2 miejsc po przecinku
271
+ expect(result.redisLatencyMs).toEqual(expect.any(Number));
272
+ expect(result.handlerAvgTimeMs).toEqual(expect.any(Number));
273
+ }));
274
+ });
275
+ describe('getRandomDelay', () => {
276
+ it('powinien generować losowy delay w zadanym zakresie', () => __awaiter(void 0, void 0, void 0, function* () {
277
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
278
+ const result = yield benchmark.run();
279
+ // Handler time powinien zawierać losowy delay 50-5000ms
280
+ expect(result.handlerAvgTimeMs).toBeGreaterThanOrEqual(50);
281
+ }));
282
+ });
283
+ describe('integracja z systemInfo', () => {
284
+ it('powinien zwrócić poprawne informacje o systemie', () => __awaiter(void 0, void 0, void 0, function* () {
285
+ os.availableParallelism.mockReturnValue(12);
286
+ os.freemem.mockReturnValue(10 * 1024 * 1024 * 1024);
287
+ os.totalmem.mockReturnValue(32 * 1024 * 1024 * 1024);
288
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
289
+ const result = yield benchmark.run();
290
+ expect(result.systemInfo).toEqual({
291
+ cpuCount: 12,
292
+ freeMemoryGB: expect.any(Number),
293
+ totalMemoryGB: expect.any(Number),
294
+ });
295
+ expect(result.systemInfo.freeMemoryGB).toBeCloseTo(10, 1);
296
+ expect(result.systemInfo.totalMemoryGB).toBeCloseTo(32, 1);
297
+ }));
298
+ });
299
+ });
300
+ //# sourceMappingURL=worker-benchmark.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-benchmark.spec.js","sourceRoot":"","sources":["../../../src/command-bus/worker/worker-benchmark.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ import type { Queue } from 'bullmq';
2
+ import type { ILogger } from '../../shared/types';
3
+ /**
4
+ * Snapshot metryk dla analizy trendu
5
+ */
6
+ interface MetricsSnapshot {
7
+ waiting: number;
8
+ active: number;
9
+ jobsPerSecond: number;
10
+ avgProcessingTimeMs: number;
11
+ timestamp: number;
12
+ }
13
+ /**
14
+ * Rekomendacja zmiany concurrency
15
+ */
16
+ interface ConcurrencyRecommendation {
17
+ shouldAdjust: boolean;
18
+ direction: 'increase' | 'decrease' | 'none';
19
+ reason: string;
20
+ currentMetrics: MetricsSnapshot;
21
+ }
22
+ /**
23
+ * Zbiera i loguje metryki diagnostyczne workera co 5 sekund
24
+ */
25
+ export default class WorkerMetricsCollector {
26
+ private readonly commandName;
27
+ private readonly queue;
28
+ private readonly logger;
29
+ private readonly onConcurrencyRecommendation?;
30
+ private intervalId?;
31
+ private previousCompleted;
32
+ private previousTimestamp;
33
+ private processingTimes;
34
+ /**
35
+ * Okno przesuwne dla ostatnich 10 pomiarów metryk (50s historii)
36
+ */
37
+ private metricsHistory;
38
+ private readonly maxHistorySize;
39
+ constructor(commandName: string, queue: Queue, logger: ILogger, onConcurrencyRecommendation?: ((recommendation: ConcurrencyRecommendation) => void) | undefined);
40
+ /**
41
+ * Uruchamia zbieranie metryk co 5 sekund
42
+ */
43
+ start(): void;
44
+ /**
45
+ * Zatrzymuje zbieranie metryk
46
+ */
47
+ stop(): void;
48
+ /**
49
+ * Rejestruje czas przetwarzania joba (w ms)
50
+ */
51
+ recordJobProcessingTime(durationMs: number): void;
52
+ /**
53
+ * Zbiera metryki z kolejki i loguje
54
+ */
55
+ private collectMetrics;
56
+ /**
57
+ * Oblicza przepustowość (jobs/sec, jobs/min) na podstawie różnicy completed
58
+ */
59
+ private calculateThroughput;
60
+ /**
61
+ * Oblicza średni czas przetwarzania z zebranych pomiarów
62
+ */
63
+ private calculateAvgProcessingTime;
64
+ /**
65
+ * Dodaje snapshot metryk do okna przesuwnego (max 10 pomiarów)
66
+ */
67
+ private addToHistory;
68
+ /**
69
+ * Analizuje trendy w metrykach i rekomenduje zmianę concurrency
70
+ * Warunki zwiększenia (wszystkie muszą być true):
71
+ * - waiting > active * 2 (duży backlog)
72
+ * - Trend waiting: rośnie w 7/10 ostatnich pomiarów
73
+ * - Trend throughput: rośnie w 7/10 pomiarów
74
+ *
75
+ * Warunki zmniejszenia (wszystkie muszą być true):
76
+ * - waiting < active / 2 (mało pending)
77
+ * - Trend waiting: maleje w 7/10 ostatnich pomiarów
78
+ * - Trend throughput: maleje w 7/10 pomiarów
79
+ */
80
+ private analyzeMetricsAndRecommendConcurrency;
81
+ /**
82
+ * Analizuje trend dla danej metryki
83
+ * @returns 'increasing' jeśli rośnie w 7/10 pomiarów, 'decreasing' jeśli maleje, 'stable' w przeciwnym razie
84
+ */
85
+ private analyzeTrend;
86
+ }
87
+ export {};