pp-command-bus 1.5.0 → 2.0.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.
- package/README.md +400 -1219
- package/dist/command-bus/command-bus.spec.js +138 -359
- package/dist/command-bus/command-bus.spec.js.map +1 -1
- package/dist/command-bus/command.d.ts +3 -4
- package/dist/command-bus/command.js +3 -32
- package/dist/command-bus/command.js.map +1 -1
- package/dist/command-bus/config/command-bus-config.d.ts +80 -21
- package/dist/command-bus/config/command-bus-config.js +104 -58
- package/dist/command-bus/config/command-bus-config.js.map +1 -1
- package/dist/command-bus/config/command-bus-config.spec.js +174 -100
- package/dist/command-bus/config/command-bus-config.spec.js.map +1 -1
- package/dist/command-bus/index.d.ts +41 -50
- package/dist/command-bus/index.js +143 -127
- package/dist/command-bus/index.js.map +1 -1
- package/dist/command-bus/interceptors/index.d.ts +5 -0
- package/dist/command-bus/interceptors/index.js +22 -0
- package/dist/command-bus/interceptors/index.js.map +1 -0
- package/dist/command-bus/interceptors/interceptor.interface.d.ts +35 -0
- package/dist/command-bus/interceptors/interceptor.interface.js +3 -0
- package/dist/command-bus/interceptors/interceptor.interface.js.map +1 -0
- package/dist/command-bus/interceptors/performance-interceptor.d.ts +24 -0
- package/dist/command-bus/interceptors/performance-interceptor.js +86 -0
- package/dist/command-bus/interceptors/performance-interceptor.js.map +1 -0
- package/dist/command-bus/interceptors/performance-interceptor.spec.js +124 -0
- package/dist/command-bus/interceptors/performance-interceptor.spec.js.map +1 -0
- package/dist/command-bus/logging/command-logger.d.ts +2 -0
- package/dist/command-bus/logging/command-logger.js +7 -0
- package/dist/command-bus/logging/command-logger.js.map +1 -1
- package/dist/command-bus/logging/command-logger.spec.js +36 -0
- package/dist/command-bus/logging/command-logger.spec.js.map +1 -1
- package/dist/command-bus/serialization/index.d.ts +6 -0
- package/dist/command-bus/serialization/index.js +9 -0
- package/dist/command-bus/serialization/index.js.map +1 -0
- package/dist/command-bus/serialization/msgpack-serializer.d.ts +26 -0
- package/dist/command-bus/serialization/msgpack-serializer.js +70 -0
- package/dist/command-bus/serialization/msgpack-serializer.js.map +1 -0
- package/dist/command-bus/serialization/msgpack-serializer.spec.js +223 -0
- package/dist/command-bus/serialization/msgpack-serializer.spec.js.map +1 -0
- package/dist/command-bus/serialization/serializer.interface.d.ts +21 -0
- package/dist/command-bus/serialization/serializer.interface.js +3 -0
- package/dist/command-bus/serialization/serializer.interface.js.map +1 -0
- package/dist/command-bus/transport/consumer-loop.d.ts +45 -0
- package/dist/command-bus/transport/consumer-loop.js +90 -0
- package/dist/command-bus/transport/consumer-loop.js.map +1 -0
- package/dist/command-bus/transport/consumer-loop.spec.js +216 -0
- package/dist/command-bus/transport/consumer-loop.spec.js.map +1 -0
- package/dist/command-bus/transport/index.d.ts +21 -0
- package/dist/command-bus/transport/index.js +23 -0
- package/dist/command-bus/transport/index.js.map +1 -0
- package/dist/command-bus/transport/message-processor.d.ts +70 -0
- package/dist/command-bus/transport/message-processor.js +158 -0
- package/dist/command-bus/transport/message-processor.js.map +1 -0
- package/dist/command-bus/transport/message-processor.spec.js +185 -0
- package/dist/command-bus/transport/message-processor.spec.js.map +1 -0
- package/dist/command-bus/transport/pending-recovery.d.ts +54 -0
- package/dist/command-bus/transport/pending-recovery.js +139 -0
- package/dist/command-bus/transport/pending-recovery.js.map +1 -0
- package/dist/command-bus/transport/pending-recovery.spec.js +176 -0
- package/dist/command-bus/transport/pending-recovery.spec.js.map +1 -0
- package/dist/command-bus/transport/redis-codec.d.ts +24 -0
- package/dist/command-bus/transport/redis-codec.js +33 -0
- package/dist/command-bus/transport/redis-codec.js.map +1 -0
- package/dist/command-bus/transport/redis-codec.spec.js +53 -0
- package/dist/command-bus/transport/redis-codec.spec.js.map +1 -0
- package/dist/command-bus/transport/redis-streams-transport.d.ts +94 -0
- package/dist/command-bus/transport/redis-streams-transport.js +143 -0
- package/dist/command-bus/transport/redis-streams-transport.js.map +1 -0
- package/dist/command-bus/transport/redis-streams-transport.spec.js +420 -0
- package/dist/command-bus/transport/redis-streams-transport.spec.js.map +1 -0
- package/dist/command-bus/transport/rpc-handler.d.ts +39 -0
- package/dist/command-bus/transport/rpc-handler.js +87 -0
- package/dist/command-bus/transport/rpc-handler.js.map +1 -0
- package/dist/command-bus/transport/rpc-handler.spec.js +157 -0
- package/dist/command-bus/transport/rpc-handler.spec.js.map +1 -0
- package/dist/command-bus/transport/stream-consumer.d.ts +91 -0
- package/dist/command-bus/transport/stream-consumer.js +182 -0
- package/dist/command-bus/transport/stream-consumer.js.map +1 -0
- package/dist/command-bus/transport/stream-consumer.spec.js +284 -0
- package/dist/command-bus/transport/stream-consumer.spec.js.map +1 -0
- package/dist/command-bus/transport/stream-producer.d.ts +23 -0
- package/dist/command-bus/transport/stream-producer.js +70 -0
- package/dist/command-bus/transport/stream-producer.js.map +1 -0
- package/dist/command-bus/transport/stream-producer.spec.js +125 -0
- package/dist/command-bus/transport/stream-producer.spec.js.map +1 -0
- package/dist/command-bus/transport/transport.interface.d.ts +87 -0
- package/dist/command-bus/transport/transport.interface.js +3 -0
- package/dist/command-bus/transport/transport.interface.js.map +1 -0
- package/dist/command-bus/types/index.d.ts +0 -84
- package/dist/examples/rpc.demo.js +1 -1
- package/dist/examples/rpc.demo.js.map +1 -1
- package/dist/index.d.ts +8 -5
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/pp-command-bus-2.0.1.tgz +0 -0
- package/dist/shared/redis/connection-pool.d.ts +54 -0
- package/dist/shared/redis/connection-pool.js +123 -0
- package/dist/shared/redis/connection-pool.js.map +1 -0
- package/dist/shared/redis/connection-pool.spec.d.ts +1 -0
- package/dist/shared/redis/connection-pool.spec.js +114 -0
- package/dist/shared/redis/connection-pool.spec.js.map +1 -0
- package/dist/shared/redis/index.d.ts +5 -3
- package/dist/shared/redis/index.js +6 -4
- package/dist/shared/redis/index.js.map +1 -1
- package/dist/shared/redis/rpc-connection-pool.d.ts +61 -0
- package/dist/shared/redis/rpc-connection-pool.js +154 -0
- package/dist/shared/redis/rpc-connection-pool.js.map +1 -0
- package/dist/shared/redis/rpc-connection-pool.spec.d.ts +1 -0
- package/dist/shared/redis/rpc-connection-pool.spec.js +173 -0
- package/dist/shared/redis/rpc-connection-pool.spec.js.map +1 -0
- package/dist/shared/types.d.ts +0 -4
- package/dist/shared/utils/error-utils.d.ts +8 -0
- package/dist/shared/utils/error-utils.js +14 -0
- package/dist/shared/utils/error-utils.js.map +1 -0
- package/package.json +12 -12
- package/dist/command-bus/config/auto-config-optimizer.d.ts +0 -35
- package/dist/command-bus/config/auto-config-optimizer.js +0 -52
- package/dist/command-bus/config/auto-config-optimizer.js.map +0 -1
- package/dist/command-bus/config/auto-config-optimizer.spec.js +0 -42
- package/dist/command-bus/config/auto-config-optimizer.spec.js.map +0 -1
- package/dist/command-bus/job/index.d.ts +0 -6
- package/dist/command-bus/job/index.js +0 -15
- package/dist/command-bus/job/index.js.map +0 -1
- package/dist/command-bus/job/job-options-builder.d.ts +0 -21
- package/dist/command-bus/job/job-options-builder.js +0 -58
- package/dist/command-bus/job/job-options-builder.js.map +0 -1
- package/dist/command-bus/job/job-options-builder.spec.js +0 -156
- package/dist/command-bus/job/job-options-builder.spec.js.map +0 -1
- package/dist/command-bus/job/job-processor.d.ts +0 -39
- package/dist/command-bus/job/job-processor.js +0 -203
- package/dist/command-bus/job/job-processor.js.map +0 -1
- package/dist/command-bus/job/job-processor.spec.js +0 -436
- package/dist/command-bus/job/job-processor.spec.js.map +0 -1
- package/dist/command-bus/queue/index.d.ts +0 -5
- package/dist/command-bus/queue/index.js +0 -13
- package/dist/command-bus/queue/index.js.map +0 -1
- package/dist/command-bus/queue/queue-manager.d.ts +0 -56
- package/dist/command-bus/queue/queue-manager.js +0 -163
- package/dist/command-bus/queue/queue-manager.js.map +0 -1
- package/dist/command-bus/queue/queue-manager.spec.js +0 -371
- package/dist/command-bus/queue/queue-manager.spec.js.map +0 -1
- package/dist/command-bus/rpc/index.d.ts +0 -11
- package/dist/command-bus/rpc/index.js +0 -19
- package/dist/command-bus/rpc/index.js.map +0 -1
- package/dist/command-bus/rpc/payload-compression.service.d.ts +0 -50
- package/dist/command-bus/rpc/payload-compression.service.js +0 -215
- package/dist/command-bus/rpc/payload-compression.service.js.map +0 -1
- package/dist/command-bus/rpc/payload-compression.service.spec.js +0 -376
- package/dist/command-bus/rpc/payload-compression.service.spec.js.map +0 -1
- package/dist/command-bus/rpc/rpc-coordinator.d.ts +0 -96
- package/dist/command-bus/rpc/rpc-coordinator.js +0 -500
- package/dist/command-bus/rpc/rpc-coordinator.js.map +0 -1
- package/dist/command-bus/rpc/rpc-coordinator.spec.js +0 -621
- package/dist/command-bus/rpc/rpc-coordinator.spec.js.map +0 -1
- package/dist/command-bus/rpc/rpc-job-cancellation.service.d.ts +0 -82
- package/dist/command-bus/rpc/rpc-job-cancellation.service.js +0 -180
- package/dist/command-bus/rpc/rpc-job-cancellation.service.js.map +0 -1
- package/dist/command-bus/rpc/rpc-job-cancellation.service.spec.js +0 -286
- package/dist/command-bus/rpc/rpc-job-cancellation.service.spec.js.map +0 -1
- package/dist/command-bus/worker/index.d.ts +0 -10
- package/dist/command-bus/worker/index.js +0 -19
- package/dist/command-bus/worker/index.js.map +0 -1
- package/dist/command-bus/worker/worker-benchmark.d.ts +0 -71
- package/dist/command-bus/worker/worker-benchmark.js +0 -202
- package/dist/command-bus/worker/worker-benchmark.js.map +0 -1
- package/dist/command-bus/worker/worker-benchmark.spec.js +0 -310
- package/dist/command-bus/worker/worker-benchmark.spec.js.map +0 -1
- package/dist/command-bus/worker/worker-metrics-collector.d.ts +0 -98
- package/dist/command-bus/worker/worker-metrics-collector.js +0 -242
- package/dist/command-bus/worker/worker-metrics-collector.js.map +0 -1
- package/dist/command-bus/worker/worker-orchestrator.d.ts +0 -70
- package/dist/command-bus/worker/worker-orchestrator.js +0 -339
- package/dist/command-bus/worker/worker-orchestrator.js.map +0 -1
- package/dist/command-bus/worker/worker-orchestrator.spec.js +0 -712
- package/dist/command-bus/worker/worker-orchestrator.spec.js.map +0 -1
- package/dist/examples/auto-config.demo.d.ts +0 -9
- package/dist/examples/auto-config.demo.js +0 -106
- package/dist/examples/auto-config.demo.js.map +0 -1
- package/dist/examples/rpc-compression.demo.d.ts +0 -5
- package/dist/examples/rpc-compression.demo.js +0 -358
- package/dist/examples/rpc-compression.demo.js.map +0 -1
- package/dist/examples/rpc-resilience.demo.d.ts +0 -15
- package/dist/examples/rpc-resilience.demo.js +0 -233
- package/dist/examples/rpc-resilience.demo.js.map +0 -1
- package/dist/pp-command-bus-1.5.0.tgz +0 -0
- package/dist/shared/config/base-config.d.ts +0 -54
- package/dist/shared/config/base-config.js +0 -114
- package/dist/shared/config/base-config.js.map +0 -1
- package/dist/shared/config/base-config.spec.js +0 -204
- package/dist/shared/config/base-config.spec.js.map +0 -1
- package/dist/shared/config/index.d.ts +0 -1
- package/dist/shared/config/index.js +0 -9
- package/dist/shared/config/index.js.map +0 -1
- package/dist/shared/redis/redis-connection-factory.d.ts +0 -66
- package/dist/shared/redis/redis-connection-factory.js +0 -113
- package/dist/shared/redis/redis-connection-factory.js.map +0 -1
- /package/dist/command-bus/{config/auto-config-optimizer.spec.d.ts → interceptors/performance-interceptor.spec.d.ts} +0 -0
- /package/dist/command-bus/{job/job-options-builder.spec.d.ts → serialization/msgpack-serializer.spec.d.ts} +0 -0
- /package/dist/command-bus/{job/job-processor.spec.d.ts → transport/consumer-loop.spec.d.ts} +0 -0
- /package/dist/command-bus/{queue/queue-manager.spec.d.ts → transport/message-processor.spec.d.ts} +0 -0
- /package/dist/command-bus/{rpc/payload-compression.service.spec.d.ts → transport/pending-recovery.spec.d.ts} +0 -0
- /package/dist/command-bus/{rpc/rpc-coordinator.spec.d.ts → transport/redis-codec.spec.d.ts} +0 -0
- /package/dist/command-bus/{rpc/rpc-job-cancellation.service.spec.d.ts → transport/redis-streams-transport.spec.d.ts} +0 -0
- /package/dist/command-bus/{worker/worker-benchmark.spec.d.ts → transport/rpc-handler.spec.d.ts} +0 -0
- /package/dist/command-bus/{worker/worker-orchestrator.spec.d.ts → transport/stream-consumer.spec.d.ts} +0 -0
- /package/dist/{shared/config/base-config.spec.d.ts → command-bus/transport/stream-producer.spec.d.ts} +0 -0
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.WorkerBenchmark = exports.WorkerMetricsCollector = exports.WorkerOrchestrator = void 0;
|
|
7
|
-
/**
|
|
8
|
-
* Moduł zarządzania workerami BullMQ
|
|
9
|
-
* Eksportuje WorkerOrchestrator odpowiedzialny za lifecycle workerów,
|
|
10
|
-
* WorkerMetricsCollector dla zbierania metryk diagnostycznych
|
|
11
|
-
* oraz WorkerBenchmark dla automatycznej optymalizacji concurrency
|
|
12
|
-
*/
|
|
13
|
-
var worker_orchestrator_1 = require("./worker-orchestrator");
|
|
14
|
-
Object.defineProperty(exports, "WorkerOrchestrator", { enumerable: true, get: function () { return __importDefault(worker_orchestrator_1).default; } });
|
|
15
|
-
var worker_metrics_collector_1 = require("./worker-metrics-collector");
|
|
16
|
-
Object.defineProperty(exports, "WorkerMetricsCollector", { enumerable: true, get: function () { return __importDefault(worker_metrics_collector_1).default; } });
|
|
17
|
-
var worker_benchmark_1 = require("./worker-benchmark");
|
|
18
|
-
Object.defineProperty(exports, "WorkerBenchmark", { enumerable: true, get: function () { return __importDefault(worker_benchmark_1).default; } });
|
|
19
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/command-bus/worker/index.ts"],"names":[],"mappings":";;;;;;AAAA;;;;;GAKG;AACH,6DAAsE;AAA7D,0IAAA,OAAO,OAAsB;AACtC,uEAA+E;AAAtE,mJAAA,OAAO,OAA0B;AAC1C,uDAAgE;AAAvD,oIAAA,OAAO,OAAmB"}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import type { Redis } from 'ioredis';
|
|
2
|
-
import type { ILogger } from '../../shared/types';
|
|
3
|
-
import type JobProcessor from '../job/job-processor';
|
|
4
|
-
import { type SystemInfo } from '../config/auto-config-optimizer';
|
|
5
|
-
/**
|
|
6
|
-
* Wynik benchmarku workera
|
|
7
|
-
*/
|
|
8
|
-
export interface BenchmarkResult {
|
|
9
|
-
/**
|
|
10
|
-
* Średnia latencja Redis w ms (ping + set/get)
|
|
11
|
-
*/
|
|
12
|
-
redisLatencyMs: number;
|
|
13
|
-
/**
|
|
14
|
-
* Przepustowość workera w jobs/sec
|
|
15
|
-
*/
|
|
16
|
-
workerThroughputJobsPerSec: number;
|
|
17
|
-
/**
|
|
18
|
-
* Średni czas przetwarzania handlera w ms
|
|
19
|
-
*/
|
|
20
|
-
handlerAvgTimeMs: number;
|
|
21
|
-
/**
|
|
22
|
-
* Informacje o systemie (CPU, RAM)
|
|
23
|
-
*/
|
|
24
|
-
systemInfo: SystemInfo;
|
|
25
|
-
/**
|
|
26
|
-
* Rekomendowane concurrency obliczone na podstawie metryk
|
|
27
|
-
*/
|
|
28
|
-
recommendedConcurrency: number;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Szybki benchmark workera (~1-2s)
|
|
32
|
-
* Mierzy latencję Redis, przepustowość workera i czas przetwarzania handlera
|
|
33
|
-
*/
|
|
34
|
-
export default class WorkerBenchmark {
|
|
35
|
-
private readonly commandName;
|
|
36
|
-
private readonly redisConnection;
|
|
37
|
-
private readonly jobProcessor;
|
|
38
|
-
private readonly logger;
|
|
39
|
-
constructor(commandName: string, redisConnection: Redis, jobProcessor: JobProcessor, logger: ILogger);
|
|
40
|
-
/**
|
|
41
|
-
* Uruchamia benchmark i zwraca wyniki z rekomendowanym concurrency
|
|
42
|
-
*/
|
|
43
|
-
run(): Promise<BenchmarkResult>;
|
|
44
|
-
/**
|
|
45
|
-
* Mierzy latencję Redis (ping + set/get)
|
|
46
|
-
* @returns Średnia latencja w ms
|
|
47
|
-
*/
|
|
48
|
-
private measureRedisLatency;
|
|
49
|
-
/**
|
|
50
|
-
* Mierzy średni czas przetwarzania handlera
|
|
51
|
-
* Symuluje losowy delay 50-5000ms dla realistycznego benchmarku
|
|
52
|
-
* UWAGA: Nie wywołujemy prawdziwego handlera, tylko mierzymy overhead framework'a
|
|
53
|
-
* @returns Średni czas w ms
|
|
54
|
-
*/
|
|
55
|
-
private measureHandlerTime;
|
|
56
|
-
/**
|
|
57
|
-
* Oblicza rekomendowane concurrency na podstawie metryk
|
|
58
|
-
*/
|
|
59
|
-
private calculateConcurrency;
|
|
60
|
-
/**
|
|
61
|
-
* Oblicza średnią z tablicy wartości
|
|
62
|
-
*/
|
|
63
|
-
private calculateAverage;
|
|
64
|
-
/**
|
|
65
|
-
* Generuje losowy delay w zadanym zakresie
|
|
66
|
-
* @param min - Minimalna wartość w ms
|
|
67
|
-
* @param max - Maksymalna wartość w ms
|
|
68
|
-
* @returns Losowy delay w ms
|
|
69
|
-
*/
|
|
70
|
-
private getRandomDelay;
|
|
71
|
-
}
|
|
@@ -1,202 +0,0 @@
|
|
|
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(payload) {
|
|
23
|
-
super(payload);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Szybki benchmark workera (~1-2s)
|
|
28
|
-
* Mierzy latencję Redis, przepustowość workera i czas przetwarzania handlera
|
|
29
|
-
*/
|
|
30
|
-
class WorkerBenchmark {
|
|
31
|
-
constructor(commandName, redisConnection, jobProcessor, logger) {
|
|
32
|
-
this.commandName = commandName;
|
|
33
|
-
this.redisConnection = redisConnection;
|
|
34
|
-
this.jobProcessor = jobProcessor;
|
|
35
|
-
this.logger = logger;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Uruchamia benchmark i zwraca wyniki z rekomendowanym concurrency
|
|
39
|
-
*/
|
|
40
|
-
run() {
|
|
41
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
42
|
-
this.logger.log(`Rozpoczynam benchmark dla ${this.commandName}`, {
|
|
43
|
-
commandName: this.commandName,
|
|
44
|
-
timestamp: new Date().toISOString(),
|
|
45
|
-
});
|
|
46
|
-
const startTime = Date.now();
|
|
47
|
-
// Zbierz metryki
|
|
48
|
-
const redisLatencyMs = yield this.measureRedisLatency();
|
|
49
|
-
const handlerAvgTimeMs = this.measureHandlerTime();
|
|
50
|
-
const systemInfo = auto_config_optimizer_1.default.getSystemInfo();
|
|
51
|
-
// Oblicz rekomendowane concurrency
|
|
52
|
-
const recommendedConcurrency = this.calculateConcurrency(redisLatencyMs, handlerAvgTimeMs, systemInfo);
|
|
53
|
-
const totalTime = Date.now() - startTime;
|
|
54
|
-
const result = {
|
|
55
|
-
redisLatencyMs,
|
|
56
|
-
workerThroughputJobsPerSec: 0, // Pominiemy throughput test dla prostoty
|
|
57
|
-
handlerAvgTimeMs,
|
|
58
|
-
systemInfo,
|
|
59
|
-
recommendedConcurrency,
|
|
60
|
-
};
|
|
61
|
-
this.logger.log('Benchmark zakończony', Object.assign(Object.assign({ commandName: this.commandName }, result), { benchmarkDurationMs: totalTime, timestamp: new Date().toISOString() }));
|
|
62
|
-
return result;
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Mierzy latencję Redis (ping + set/get)
|
|
67
|
-
* @returns Średnia latencja w ms
|
|
68
|
-
*/
|
|
69
|
-
measureRedisLatency() {
|
|
70
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
71
|
-
const measurements = [];
|
|
72
|
-
try {
|
|
73
|
-
// 10 prób ping
|
|
74
|
-
for (let i = 0; i < 10; i++) {
|
|
75
|
-
const start = Date.now();
|
|
76
|
-
yield this.redisConnection.ping();
|
|
77
|
-
measurements.push(Date.now() - start);
|
|
78
|
-
}
|
|
79
|
-
// 10 prób set/get
|
|
80
|
-
for (let i = 0; i < 10; i++) {
|
|
81
|
-
const key = `{benchmark:${this.commandName}:${i}:${(0, crypto_1.randomUUID)()}}`;
|
|
82
|
-
const value = `test-value-${i}`;
|
|
83
|
-
const setStart = Date.now();
|
|
84
|
-
yield this.redisConnection.set(key, value);
|
|
85
|
-
measurements.push(Date.now() - setStart);
|
|
86
|
-
const getStart = Date.now();
|
|
87
|
-
yield this.redisConnection.get(key);
|
|
88
|
-
measurements.push(Date.now() - getStart);
|
|
89
|
-
yield this.redisConnection.del(key);
|
|
90
|
-
}
|
|
91
|
-
return this.calculateAverage(measurements);
|
|
92
|
-
}
|
|
93
|
-
catch (error) {
|
|
94
|
-
this.logger.error('Błąd podczas pomiaru latencji Redis', {
|
|
95
|
-
commandName: this.commandName,
|
|
96
|
-
error: error instanceof Error ? error.message : String(error),
|
|
97
|
-
});
|
|
98
|
-
// Fallback: zakładamy średnią latencję
|
|
99
|
-
return 5;
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Mierzy średni czas przetwarzania handlera
|
|
105
|
-
* Symuluje losowy delay 50-5000ms dla realistycznego benchmarku
|
|
106
|
-
* UWAGA: Nie wywołujemy prawdziwego handlera, tylko mierzymy overhead framework'a
|
|
107
|
-
* @returns Średni czas w ms
|
|
108
|
-
*/
|
|
109
|
-
measureHandlerTime() {
|
|
110
|
-
const measurements = [];
|
|
111
|
-
try {
|
|
112
|
-
// 100 wywołań testowych
|
|
113
|
-
for (let i = 0; i < 100; i++) {
|
|
114
|
-
const testCommand = new BenchmarkTestCommand({ testId: i });
|
|
115
|
-
const start = Date.now();
|
|
116
|
-
// Symuluj overhead JobProcessor'a bez wywoływania prawdziwego handlera
|
|
117
|
-
// - Serializacja/deserializacja command
|
|
118
|
-
// - Rekonstrukcja dat
|
|
119
|
-
// - Logging
|
|
120
|
-
const serialized = JSON.stringify(testCommand);
|
|
121
|
-
const deserialized = JSON.parse(serialized);
|
|
122
|
-
command_1.default.reconstructDates(deserialized);
|
|
123
|
-
const frameworkOverhead = Date.now() - start;
|
|
124
|
-
// Symuluj losowy delay handlera (50-5000ms)
|
|
125
|
-
const randomDelay = this.getRandomDelay(50, 5000);
|
|
126
|
-
const totalDuration = frameworkOverhead + randomDelay;
|
|
127
|
-
if (totalDuration > 0) {
|
|
128
|
-
measurements.push(totalDuration);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
// Jeśli nie udało się zmierzyć, zwróć fallback
|
|
132
|
-
if (measurements.length === 0) {
|
|
133
|
-
return 50;
|
|
134
|
-
}
|
|
135
|
-
return this.calculateAverage(measurements);
|
|
136
|
-
}
|
|
137
|
-
catch (error) {
|
|
138
|
-
this.logger.error('Błąd podczas pomiaru czasu handlera', {
|
|
139
|
-
commandName: this.commandName,
|
|
140
|
-
error: error instanceof Error ? error.message : String(error),
|
|
141
|
-
});
|
|
142
|
-
// Fallback: zakładamy średni czas
|
|
143
|
-
return 50;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Oblicza rekomendowane concurrency na podstawie metryk
|
|
148
|
-
*/
|
|
149
|
-
calculateConcurrency(redisLatencyMs, handlerAvgTimeMs, systemInfo) {
|
|
150
|
-
const { cpuCount, freeMemoryGB } = systemInfo;
|
|
151
|
-
// Bazowy concurrency dla I/O-heavy workload
|
|
152
|
-
let baseConcurrency = cpuCount * 50;
|
|
153
|
-
// Korekta dla dostępnej pamięci RAM
|
|
154
|
-
if (freeMemoryGB < 2) {
|
|
155
|
-
baseConcurrency *= 0.3;
|
|
156
|
-
}
|
|
157
|
-
else if (freeMemoryGB < 4) {
|
|
158
|
-
baseConcurrency *= 0.5;
|
|
159
|
-
}
|
|
160
|
-
else if (freeMemoryGB >= 16) {
|
|
161
|
-
baseConcurrency *= 1.2;
|
|
162
|
-
}
|
|
163
|
-
let factor = 1.0;
|
|
164
|
-
// Korekta dla latencji Redis - bardziej agresywna
|
|
165
|
-
if (redisLatencyMs < 1) {
|
|
166
|
-
factor *= 1.5; // Bardzo szybki Redis
|
|
167
|
-
}
|
|
168
|
-
else if (redisLatencyMs > 10) {
|
|
169
|
-
factor *= 0.3; // Wolny Redis - mocniejsza redukcja
|
|
170
|
-
}
|
|
171
|
-
// Korekta dla czasu handlera - bardziej agresywna
|
|
172
|
-
if (handlerAvgTimeMs < 10) {
|
|
173
|
-
factor *= 1.2; // Szybki handler
|
|
174
|
-
}
|
|
175
|
-
else if (handlerAvgTimeMs > 100) {
|
|
176
|
-
factor *= 0.5; // Wolny handler - mocniejsza redukcja
|
|
177
|
-
}
|
|
178
|
-
const recommendedConcurrency = Math.round(baseConcurrency * factor);
|
|
179
|
-
// Zapewnij sensowne granice: min 10, max 2000
|
|
180
|
-
return Math.max(10, Math.min(2000, recommendedConcurrency));
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Oblicza średnią z tablicy wartości
|
|
184
|
-
*/
|
|
185
|
-
calculateAverage(values) {
|
|
186
|
-
if (values.length === 0)
|
|
187
|
-
return 0;
|
|
188
|
-
const sum = values.reduce((acc, val) => acc + val, 0);
|
|
189
|
-
return Number((sum / values.length).toFixed(2));
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Generuje losowy delay w zadanym zakresie
|
|
193
|
-
* @param min - Minimalna wartość w ms
|
|
194
|
-
* @param max - Maksymalna wartość w ms
|
|
195
|
-
* @returns Losowy delay w ms
|
|
196
|
-
*/
|
|
197
|
-
getRandomDelay(min, max) {
|
|
198
|
-
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
exports.default = WorkerBenchmark;
|
|
202
|
-
//# sourceMappingURL=worker-benchmark.js.map
|
|
@@ -1 +0,0 @@
|
|
|
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,iBAA2B;IAC5D,YAAY,OAA2B;QACrC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,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,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACnD,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;;;;;OAKG;IACK,kBAAkB;QACxB,MAAM,YAAY,GAAa,EAAE,CAAC;QAElC,IAAI,CAAC;YACH,wBAAwB;YACxB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7B,MAAM,WAAW,GAAG,IAAI,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;gBAE5D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAEzB,uEAAuE;gBACvE,wCAAwC;gBACxC,sBAAsB;gBACtB,YAAY;gBACZ,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;gBAC/C,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBAC5C,iBAAO,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;gBAEvC,MAAM,iBAAiB,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;gBAE7C,4CAA4C;gBAC5C,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;gBAClD,MAAM,aAAa,GAAG,iBAAiB,GAAG,WAAW,CAAC;gBAEtD,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;oBACtB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;gBACnC,CAAC;YACH,CAAC;YAED,+CAA+C;YAC/C,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC9B,OAAO,EAAE,CAAC;YACZ,CAAC;YAED,OAAO,IAAI,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,qCAAqC,EAAE;gBACvD,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC,CAAC;YACH,kCAAkC;YAClC,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;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;AA7MD,kCA6MC"}
|
|
@@ -1,310 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"worker-benchmark.spec.js","sourceRoot":"","sources":["../../../src/command-bus/worker/worker-benchmark.spec.ts"],"names":[],"mappings":"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"}
|