pp-command-bus 1.0.3 → 1.2.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 (53) hide show
  1. package/dist/command-bus/command-bus.spec.js +41 -9
  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 +2 -2
  15. package/dist/command-bus/index.js +26 -15
  16. package/dist/command-bus/index.js.map +1 -1
  17. package/dist/command-bus/job/job-processor.d.ts +8 -10
  18. package/dist/command-bus/job/job-processor.js +23 -113
  19. package/dist/command-bus/job/job-processor.js.map +1 -1
  20. package/dist/command-bus/job/job-processor.spec.js +17 -107
  21. package/dist/command-bus/job/job-processor.spec.js.map +1 -1
  22. package/dist/command-bus/rpc/rpc-coordinator.d.ts +39 -16
  23. package/dist/command-bus/rpc/rpc-coordinator.js +178 -93
  24. package/dist/command-bus/rpc/rpc-coordinator.js.map +1 -1
  25. package/dist/command-bus/rpc/rpc-coordinator.spec.js +64 -223
  26. package/dist/command-bus/rpc/rpc-coordinator.spec.js.map +1 -1
  27. package/dist/command-bus/types/index.d.ts +5 -4
  28. package/dist/command-bus/worker/index.d.ts +6 -1
  29. package/dist/command-bus/worker/index.js +8 -2
  30. package/dist/command-bus/worker/index.js.map +1 -1
  31. package/dist/command-bus/worker/worker-benchmark.d.ts +71 -0
  32. package/dist/command-bus/worker/worker-benchmark.js +203 -0
  33. package/dist/command-bus/worker/worker-benchmark.js.map +1 -0
  34. package/dist/command-bus/worker/worker-benchmark.spec.d.ts +1 -0
  35. package/dist/command-bus/worker/worker-benchmark.spec.js +310 -0
  36. package/dist/command-bus/worker/worker-benchmark.spec.js.map +1 -0
  37. package/dist/command-bus/worker/worker-metrics-collector.d.ts +98 -0
  38. package/dist/command-bus/worker/worker-metrics-collector.js +242 -0
  39. package/dist/command-bus/worker/worker-metrics-collector.js.map +1 -0
  40. package/dist/command-bus/worker/worker-orchestrator.d.ts +29 -4
  41. package/dist/command-bus/worker/worker-orchestrator.js +193 -27
  42. package/dist/command-bus/worker/worker-orchestrator.js.map +1 -1
  43. package/dist/command-bus/worker/worker-orchestrator.spec.js +477 -52
  44. package/dist/command-bus/worker/worker-orchestrator.spec.js.map +1 -1
  45. package/dist/examples/auto-config.demo.d.ts +9 -0
  46. package/dist/examples/auto-config.demo.js +106 -0
  47. package/dist/examples/auto-config.demo.js.map +1 -0
  48. package/dist/examples/rpc-throughput.demo.d.ts +5 -0
  49. package/dist/examples/rpc-throughput.demo.js +326 -0
  50. package/dist/examples/rpc-throughput.demo.js.map +1 -0
  51. package/dist/pp-command-bus-1.2.0.tgz +0 -0
  52. package/package.json +3 -2
  53. package/dist/pp-command-bus-1.0.3.tgz +0 -0
@@ -0,0 +1,203 @@
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 = 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-5000ms dla realistycznego benchmarku
107
+ * UWAGA: Nie wywołujemy prawdziwego handlera, tylko mierzymy overhead framework'a
108
+ * @returns Średni czas w ms
109
+ */
110
+ measureHandlerTime() {
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 start = Date.now();
117
+ // Symuluj overhead JobProcessor'a bez wywoływania prawdziwego handlera
118
+ // - Serializacja/deserializacja command
119
+ // - Rekonstrukcja dat
120
+ // - Logging
121
+ const serialized = JSON.stringify(testCommand);
122
+ const deserialized = JSON.parse(serialized);
123
+ command_1.default.reconstructDates(deserialized);
124
+ const frameworkOverhead = Date.now() - start;
125
+ // Symuluj losowy delay handlera (50-5000ms)
126
+ const randomDelay = this.getRandomDelay(50, 5000);
127
+ const totalDuration = frameworkOverhead + randomDelay;
128
+ if (totalDuration > 0) {
129
+ measurements.push(totalDuration);
130
+ }
131
+ }
132
+ // Jeśli nie udało się zmierzyć, zwróć fallback
133
+ if (measurements.length === 0) {
134
+ return 50;
135
+ }
136
+ return this.calculateAverage(measurements);
137
+ }
138
+ catch (error) {
139
+ this.logger.error('Błąd podczas pomiaru czasu handlera', {
140
+ commandName: this.commandName,
141
+ error: error instanceof Error ? error.message : String(error),
142
+ });
143
+ // Fallback: zakładamy średni czas
144
+ return 50;
145
+ }
146
+ }
147
+ /**
148
+ * Oblicza rekomendowane concurrency na podstawie metryk
149
+ */
150
+ calculateConcurrency(redisLatencyMs, handlerAvgTimeMs, systemInfo) {
151
+ const { cpuCount, freeMemoryGB } = systemInfo;
152
+ // Bazowy concurrency dla I/O-heavy workload
153
+ let baseConcurrency = cpuCount * 50;
154
+ // Korekta dla dostępnej pamięci RAM
155
+ if (freeMemoryGB < 2) {
156
+ baseConcurrency *= 0.3;
157
+ }
158
+ else if (freeMemoryGB < 4) {
159
+ baseConcurrency *= 0.5;
160
+ }
161
+ else if (freeMemoryGB >= 16) {
162
+ baseConcurrency *= 1.2;
163
+ }
164
+ let factor = 1.0;
165
+ // Korekta dla latencji Redis - bardziej agresywna
166
+ if (redisLatencyMs < 1) {
167
+ factor *= 1.5; // Bardzo szybki Redis
168
+ }
169
+ else if (redisLatencyMs > 10) {
170
+ factor *= 0.3; // Wolny Redis - mocniejsza redukcja
171
+ }
172
+ // Korekta dla czasu handlera - bardziej agresywna
173
+ if (handlerAvgTimeMs < 10) {
174
+ factor *= 1.2; // Szybki handler
175
+ }
176
+ else if (handlerAvgTimeMs > 100) {
177
+ factor *= 0.5; // Wolny handler - mocniejsza redukcja
178
+ }
179
+ const recommendedConcurrency = Math.round(baseConcurrency * factor);
180
+ // Zapewnij sensowne granice: min 10, max 2000
181
+ return Math.max(10, Math.min(2000, recommendedConcurrency));
182
+ }
183
+ /**
184
+ * Oblicza średnią z tablicy wartości
185
+ */
186
+ calculateAverage(values) {
187
+ if (values.length === 0)
188
+ return 0;
189
+ const sum = values.reduce((acc, val) => acc + val, 0);
190
+ return Number((sum / values.length).toFixed(2));
191
+ }
192
+ /**
193
+ * Generuje losowy delay w zadanym zakresie
194
+ * @param min - Minimalna wartość w ms
195
+ * @param max - Maksymalna wartość w ms
196
+ * @returns Losowy delay w ms
197
+ */
198
+ getRandomDelay(min, max) {
199
+ return Math.floor(Math.random() * (max - min + 1)) + min;
200
+ }
201
+ }
202
+ exports.default = WorkerBenchmark;
203
+ //# 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":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,310 @@
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 (overhead + symulowany delay)', () => __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 (minimum 50ms z symulowanego delay)
154
+ expect(result.handlerAvgTimeMs).toBeGreaterThanOrEqual(50);
155
+ // Benchmark nie powinien już wywoływać prawdziwego handlera
156
+ expect(mockJobProcessor.process).not.toHaveBeenCalled();
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 (symulowany delay)
162
+ expect(result.handlerAvgTimeMs).toBeGreaterThanOrEqual(50);
163
+ // Maksymalny średni czas nie powinien przekraczać 5000ms + overhead (~5010ms)
164
+ expect(result.handlerAvgTimeMs).toBeLessThanOrEqual(5100);
165
+ }));
166
+ it('powinien mierzyć overhead framework bez wywoływania handlera', () => __awaiter(void 0, void 0, void 0, function* () {
167
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
168
+ const result = yield benchmark.run();
169
+ // Weryfikuj że nie wywołano prawdziwego handlera
170
+ expect(mockJobProcessor.process).not.toHaveBeenCalled();
171
+ // Benchmark powinien zakończyć się pomyślnie
172
+ expect(result.handlerAvgTimeMs).toBeGreaterThan(0);
173
+ }));
174
+ it('powinien użyć fallback czasu (50ms) gdy wystąpi błąd podczas pomiaru', () => __awaiter(void 0, void 0, void 0, function* () {
175
+ // Mockuj JSON.stringify aby rzucił błąd
176
+ const originalStringify = JSON.stringify;
177
+ jest.spyOn(JSON, 'stringify').mockImplementation(() => {
178
+ throw new Error('Serialization error');
179
+ });
180
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
181
+ const result = yield benchmark.run();
182
+ // Fallback: 50ms
183
+ expect(result.handlerAvgTimeMs).toBe(50);
184
+ expect(mockLogger.error).toHaveBeenCalledWith('Błąd podczas pomiaru czasu handlera', expect.objectContaining({
185
+ commandName: 'TestCommand',
186
+ error: 'Serialization error',
187
+ }));
188
+ // Przywróć oryginalny stringify
189
+ JSON.stringify = originalStringify;
190
+ }));
191
+ });
192
+ describe('calculateConcurrency', () => {
193
+ it('powinien obliczyć bazowy concurrency (cpuCount * 50)', () => __awaiter(void 0, void 0, void 0, function* () {
194
+ // 8 cores * 50 = 400
195
+ os.availableParallelism.mockReturnValue(8);
196
+ os.freemem.mockReturnValue(8 * 1024 * 1024 * 1024); // 8GB
197
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
198
+ const result = yield benchmark.run();
199
+ // Bazowy: 8 * 50 = 400
200
+ // Z korektami powinien być w rozsądnym zakresie
201
+ expect(result.recommendedConcurrency).toBeGreaterThanOrEqual(10);
202
+ expect(result.recommendedConcurrency).toBeLessThanOrEqual(2000);
203
+ }));
204
+ it('powinien zastosować korektę dla niskiej RAM (< 2GB)', () => __awaiter(void 0, void 0, void 0, function* () {
205
+ os.availableParallelism.mockReturnValue(8);
206
+ os.freemem.mockReturnValue(1.5 * 1024 * 1024 * 1024); // 1.5GB
207
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
208
+ const result = yield benchmark.run();
209
+ // Bazowy: 8 * 50 = 400
210
+ // Korekta < 2GB: * 0.3 = 120
211
+ // Z innymi korektami może być jeszcze niższy lub wyższy
212
+ expect(result.recommendedConcurrency).toBeGreaterThanOrEqual(10);
213
+ }));
214
+ it('powinien zastosować korektę dla średniej RAM (< 4GB)', () => __awaiter(void 0, void 0, void 0, function* () {
215
+ os.availableParallelism.mockReturnValue(8);
216
+ os.freemem.mockReturnValue(3 * 1024 * 1024 * 1024); // 3GB
217
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
218
+ const result = yield benchmark.run();
219
+ // Bazowy: 8 * 50 = 400
220
+ // Korekta < 4GB: * 0.5 = 200
221
+ expect(result.recommendedConcurrency).toBeGreaterThanOrEqual(10);
222
+ }));
223
+ it('powinien zastosować korektę dla wysokiej RAM (>= 16GB)', () => __awaiter(void 0, void 0, void 0, function* () {
224
+ os.availableParallelism.mockReturnValue(8);
225
+ os.freemem.mockReturnValue(20 * 1024 * 1024 * 1024); // 20GB
226
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
227
+ const result = yield benchmark.run();
228
+ // Bazowy: 8 * 50 = 400
229
+ // Korekta >= 16GB: * 1.2 = 480
230
+ expect(result.recommendedConcurrency).toBeGreaterThanOrEqual(10);
231
+ }));
232
+ it('powinien zwiększyć concurrency dla szybkiego Redis (< 1ms)', () => __awaiter(void 0, void 0, void 0, function* () {
233
+ // Symuluj bardzo szybki Redis
234
+ mockRedis.ping.mockImplementation(() => Promise.resolve('PONG'));
235
+ mockRedis.set.mockImplementation(() => Promise.resolve('OK'));
236
+ mockRedis.get.mockImplementation(() => Promise.resolve('value'));
237
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
238
+ const result = yield benchmark.run();
239
+ // Redis latency powinno być < 1ms, co daje factor * 1.5
240
+ expect(result.redisLatencyMs).toBeLessThan(1);
241
+ expect(result.recommendedConcurrency).toBeGreaterThanOrEqual(10);
242
+ }));
243
+ it('powinien zmniejszyć concurrency dla wolnego Redis (> 10ms)', () => __awaiter(void 0, void 0, void 0, function* () {
244
+ // Symuluj wolny Redis - wszystkie operacje opóźnione
245
+ mockRedis.ping.mockImplementation(() => new Promise((resolve) => setTimeout(() => resolve('PONG'), 15)));
246
+ mockRedis.set.mockImplementation(() => new Promise((resolve) => setTimeout(() => resolve('OK'), 15)));
247
+ mockRedis.get.mockImplementation(() => new Promise((resolve) => setTimeout(() => resolve('value'), 15)));
248
+ // Ustaw wystarczające zasoby żeby nie było zbyt dużej redukcji
249
+ os.availableParallelism.mockReturnValue(8);
250
+ os.freemem.mockReturnValue(8 * 1024 * 1024 * 1024); // 8GB
251
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
252
+ const result = yield benchmark.run();
253
+ // Redis latency > 10ms, co daje factor * 0.3, ale limity zapewniają min 10
254
+ expect(result.redisLatencyMs).toBeGreaterThan(10);
255
+ expect(result.recommendedConcurrency).toBeGreaterThanOrEqual(10);
256
+ }));
257
+ it('powinien zastosować limity: min 10, max 2000', () => __awaiter(void 0, void 0, void 0, function* () {
258
+ // Przypadek 1: Bardzo niska konfiguracja
259
+ os.availableParallelism.mockReturnValue(1); // 1 core
260
+ os.freemem.mockReturnValue(0.5 * 1024 * 1024 * 1024); // 0.5GB
261
+ mockRedis.ping.mockImplementation(() => new Promise((resolve) => setTimeout(() => resolve('PONG'), 50)));
262
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
263
+ const result1 = yield benchmark.run();
264
+ // Minimum 10
265
+ expect(result1.recommendedConcurrency).toBeGreaterThanOrEqual(10);
266
+ // Przypadek 2: Bardzo wysoka konfiguracja
267
+ os.availableParallelism.mockReturnValue(64); // 64 cores
268
+ os.freemem.mockReturnValue(128 * 1024 * 1024 * 1024); // 128GB
269
+ mockRedis.ping.mockResolvedValue('PONG'); // Natychmiastowy ping
270
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
271
+ const result2 = yield benchmark.run();
272
+ // Maximum 2000
273
+ expect(result2.recommendedConcurrency).toBeLessThanOrEqual(2000);
274
+ }));
275
+ });
276
+ describe('calculateAverage', () => {
277
+ it('powinien obliczyć średnią z wartości', () => __awaiter(void 0, void 0, void 0, function* () {
278
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
279
+ const result = yield benchmark.run();
280
+ // Sprawdź że średnie są zaokrąglone do 2 miejsc po przecinku
281
+ expect(result.redisLatencyMs).toEqual(expect.any(Number));
282
+ expect(result.handlerAvgTimeMs).toEqual(expect.any(Number));
283
+ }));
284
+ });
285
+ describe('getRandomDelay', () => {
286
+ it('powinien generować losowy delay w zadanym zakresie', () => __awaiter(void 0, void 0, void 0, function* () {
287
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
288
+ const result = yield benchmark.run();
289
+ // Handler time powinien zawierać losowy delay 50-5000ms
290
+ expect(result.handlerAvgTimeMs).toBeGreaterThanOrEqual(50);
291
+ }));
292
+ });
293
+ describe('integracja z systemInfo', () => {
294
+ it('powinien zwrócić poprawne informacje o systemie', () => __awaiter(void 0, void 0, void 0, function* () {
295
+ os.availableParallelism.mockReturnValue(12);
296
+ os.freemem.mockReturnValue(10 * 1024 * 1024 * 1024);
297
+ os.totalmem.mockReturnValue(32 * 1024 * 1024 * 1024);
298
+ benchmark = new worker_benchmark_1.default('TestCommand', mockRedis, mockJobProcessor, mockLogger);
299
+ const result = yield benchmark.run();
300
+ expect(result.systemInfo).toEqual({
301
+ cpuCount: 12,
302
+ freeMemoryGB: expect.any(Number),
303
+ totalMemoryGB: expect.any(Number),
304
+ });
305
+ expect(result.systemInfo.freeMemoryGB).toBeCloseTo(10, 1);
306
+ expect(result.systemInfo.totalMemoryGB).toBeCloseTo(32, 1);
307
+ }));
308
+ });
309
+ });
310
+ //# 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,98 @@
1
+ import type { ILogger } from '../../shared/types';
2
+ /**
3
+ * Rekomendacja zmiany concurrency
4
+ */
5
+ interface ConcurrencyRecommendation {
6
+ shouldAdjust: boolean;
7
+ direction: 'increase' | 'decrease' | 'none';
8
+ reason: string;
9
+ currentMetrics: {
10
+ activeCount: number;
11
+ completedCount: number;
12
+ avgProcessingTimeMs: number;
13
+ };
14
+ }
15
+ /**
16
+ * Zbiera metryki workera w trybie event-driven
17
+ * Resetuje dane co 1 minutę (okno profilowania)
18
+ * Nie używa setInterval - bazuje na eventach jobów
19
+ */
20
+ export default class WorkerMetricsCollector {
21
+ private readonly commandName;
22
+ private readonly logger;
23
+ private readonly onConcurrencyRecommendation?;
24
+ /**
25
+ * Długość okna profilowania w ms (1 minuta)
26
+ */
27
+ private readonly PROFILING_WINDOW_MS;
28
+ /**
29
+ * Timestamp rozpoczęcia aktualnego okna profilowania
30
+ */
31
+ private profilingWindowStartTime;
32
+ /**
33
+ * Licznik ukończonych jobów w aktualnym oknie
34
+ */
35
+ private completedCount;
36
+ /**
37
+ * Licznik nieudanych jobów w aktualnym oknie
38
+ */
39
+ private failedCount;
40
+ /**
41
+ * Licznik aktywnie przetwarzanych jobów (lokalny counter)
42
+ */
43
+ private activeCount;
44
+ /**
45
+ * Czasy przetwarzania jobów w aktualnym oknie (ms)
46
+ */
47
+ private processingTimes;
48
+ /**
49
+ * Historia średnich wartości activeCount dla analizy trendów
50
+ * Zbierana przy każdym evencie completed/failed
51
+ */
52
+ private activeCountHistory;
53
+ private readonly maxActiveCountHistory;
54
+ constructor(commandName: string, logger: ILogger, onConcurrencyRecommendation?: ((recommendation: ConcurrencyRecommendation) => void) | undefined);
55
+ /**
56
+ * Wywołane gdy job zostaje aktywowany (rozpoczęty)
57
+ * @param jobId - ID joba
58
+ */
59
+ onJobActive(jobId: string): void;
60
+ /**
61
+ * Wywołane gdy job zostaje ukończony pomyślnie
62
+ * @param jobId - ID joba
63
+ * @param processingTimeMs - Czas przetwarzania w ms
64
+ */
65
+ onJobCompleted(jobId: string, processingTimeMs: number): void;
66
+ /**
67
+ * Wywołane gdy job kończy się niepowodzeniem
68
+ * @param jobId - ID joba
69
+ */
70
+ onJobFailed(jobId: string): void;
71
+ /**
72
+ * Sprawdza czy minęło okno profilowania (1 minuta)
73
+ * Jeśli tak, loguje podsumowanie, analizuje i resetuje
74
+ */
75
+ private checkWindowReset;
76
+ /**
77
+ * Wyświetla podsumowanie okna, analizuje metryki i resetuje liczniki
78
+ */
79
+ private displayMetricsAndReset;
80
+ /**
81
+ * Oblicza statystyki dla aktualnego okna profilowania
82
+ */
83
+ private calculateWindowStats;
84
+ /**
85
+ * Analizuje metryki i rekomenduje zmianę concurrency
86
+ * Bazuje na activeCount zamiast waiting (event-driven)
87
+ */
88
+ private analyzeAndRecommendConcurrency;
89
+ /**
90
+ * Zapisuje snapshot activeCount do historii dla analizy trendów
91
+ */
92
+ private recordActiveCountSnapshot;
93
+ /**
94
+ * Resetuje okno profilowania - czyści wszystkie zebrane metryki
95
+ */
96
+ private resetProfilingWindow;
97
+ }
98
+ export {};