pp-command-bus 1.5.0 → 2.0.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.
- 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 +75 -21
- package/dist/command-bus/config/command-bus-config.js +99 -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 +39 -52
- package/dist/command-bus/index.js +133 -126
- package/dist/command-bus/index.js.map +1 -1
- 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 +59 -0
- package/dist/command-bus/transport/message-processor.js +111 -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 +91 -0
- package/dist/command-bus/transport/redis-streams-transport.js +134 -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 +89 -0
- package/dist/command-bus/transport/stream-consumer.js +181 -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.0.tgz +0 -0
- package/dist/shared/redis/connection-pool.d.ts +54 -0
- package/dist/shared/redis/connection-pool.js +117 -0
- package/dist/shared/redis/connection-pool.js.map +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 → serialization/msgpack-serializer.spec.d.ts} +0 -0
- /package/dist/command-bus/{job/job-options-builder.spec.d.ts → transport/consumer-loop.spec.d.ts} +0 -0
- /package/dist/command-bus/{job/job-processor.spec.d.ts → transport/message-processor.spec.d.ts} +0 -0
- /package/dist/command-bus/{queue/queue-manager.spec.d.ts → transport/pending-recovery.spec.d.ts} +0 -0
- /package/dist/command-bus/{rpc/payload-compression.service.spec.d.ts → transport/redis-codec.spec.d.ts} +0 -0
- /package/dist/command-bus/{rpc/rpc-coordinator.spec.d.ts → transport/redis-streams-transport.spec.d.ts} +0 -0
- /package/dist/command-bus/{rpc/rpc-job-cancellation.service.spec.d.ts → transport/rpc-handler.spec.d.ts} +0 -0
- /package/dist/command-bus/{worker/worker-benchmark.spec.d.ts → transport/stream-consumer.spec.d.ts} +0 -0
- /package/dist/command-bus/{worker/worker-orchestrator.spec.d.ts → transport/stream-producer.spec.d.ts} +0 -0
- /package/dist/shared/{config/base-config.spec.d.ts → redis/connection-pool.spec.d.ts} +0 -0
|
@@ -1,621 +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 rpc_coordinator_1 = __importDefault(require("./rpc-coordinator"));
|
|
16
|
-
const command_1 = __importDefault(require("../command"));
|
|
17
|
-
describe('RpcCoordinator - Shared Subscriber Pattern z Redis Pub/Sub', () => {
|
|
18
|
-
let rpcCoordinator;
|
|
19
|
-
let mockLogger;
|
|
20
|
-
let mockRedisConnection;
|
|
21
|
-
let mockSharedSubscriber;
|
|
22
|
-
let mockCompressionService;
|
|
23
|
-
let mockCancellationService;
|
|
24
|
-
let mockRemoveJobCallback;
|
|
25
|
-
let processInstanceId;
|
|
26
|
-
// Mock Command class for testing
|
|
27
|
-
class TestCommand extends command_1.default {
|
|
28
|
-
constructor(payload) {
|
|
29
|
-
super(payload);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
beforeEach(() => {
|
|
33
|
-
var _a, _b;
|
|
34
|
-
jest.clearAllMocks();
|
|
35
|
-
mockLogger = {
|
|
36
|
-
log: jest.fn(),
|
|
37
|
-
error: jest.fn(),
|
|
38
|
-
warn: jest.fn(),
|
|
39
|
-
debug: jest.fn(),
|
|
40
|
-
};
|
|
41
|
-
// Mock Shared Subscriber
|
|
42
|
-
mockSharedSubscriber = {
|
|
43
|
-
psubscribe: jest
|
|
44
|
-
.fn()
|
|
45
|
-
.mockImplementation((_pattern, callback) => {
|
|
46
|
-
// Wywołaj callback natychmiast jeśli został przekazany
|
|
47
|
-
if (callback) {
|
|
48
|
-
setImmediate(() => callback(null, 1));
|
|
49
|
-
}
|
|
50
|
-
return Promise.resolve(undefined);
|
|
51
|
-
}),
|
|
52
|
-
punsubscribe: jest.fn().mockResolvedValue(undefined),
|
|
53
|
-
on: jest.fn().mockReturnThis(),
|
|
54
|
-
once: jest.fn().mockImplementation((event, handler) => {
|
|
55
|
-
// Automatycznie wywołaj handler 'ready' natychmiast
|
|
56
|
-
if (event === 'ready') {
|
|
57
|
-
setImmediate(() => handler());
|
|
58
|
-
}
|
|
59
|
-
return mockSharedSubscriber;
|
|
60
|
-
}),
|
|
61
|
-
removeAllListeners: jest.fn().mockReturnThis(),
|
|
62
|
-
quit: jest.fn().mockResolvedValue(undefined),
|
|
63
|
-
};
|
|
64
|
-
// Mock Redis connection
|
|
65
|
-
mockRedisConnection = {
|
|
66
|
-
duplicate: jest.fn().mockReturnValue(mockSharedSubscriber),
|
|
67
|
-
};
|
|
68
|
-
// Mock PayloadCompressionService
|
|
69
|
-
mockCompressionService = {
|
|
70
|
-
compress: jest.fn().mockResolvedValue({ data: '{}', compressed: false }),
|
|
71
|
-
decompress: jest.fn().mockImplementation((message) => {
|
|
72
|
-
return Promise.resolve(JSON.parse(message));
|
|
73
|
-
}),
|
|
74
|
-
};
|
|
75
|
-
// Mock RpcJobCancellationService
|
|
76
|
-
mockCancellationService = {
|
|
77
|
-
markAsCancelled: jest.fn().mockResolvedValue(undefined),
|
|
78
|
-
isCancelled: jest.fn().mockResolvedValue(false),
|
|
79
|
-
clearCancellation: jest.fn().mockResolvedValue(undefined),
|
|
80
|
-
tryRemoveJob: jest.fn().mockResolvedValue(false),
|
|
81
|
-
};
|
|
82
|
-
// Mock RemoveJobCallback
|
|
83
|
-
mockRemoveJobCallback = jest.fn().mockResolvedValue(false);
|
|
84
|
-
rpcCoordinator = new rpc_coordinator_1.default(mockLogger, mockRedisConnection, mockCompressionService, mockCancellationService, mockRemoveJobCallback);
|
|
85
|
-
// Ekstraktuj processInstanceId z logów debug
|
|
86
|
-
const debugCalls = mockLogger.debug.mock.calls;
|
|
87
|
-
const initCall = debugCalls.find((call) => call[0] === 'Inicjalizacja RpcCoordinator');
|
|
88
|
-
processInstanceId = (_b = (_a = initCall === null || initCall === void 0 ? void 0 : initCall[1]) === null || _a === void 0 ? void 0 : _a.processInstanceId) !== null && _b !== void 0 ? _b : 'test-process-id';
|
|
89
|
-
});
|
|
90
|
-
afterEach(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
91
|
-
// Zamknij RpcCoordinator
|
|
92
|
-
yield rpcCoordinator.close();
|
|
93
|
-
// Wyczyść wszystkie pending promises
|
|
94
|
-
yield new Promise((resolve) => setImmediate(resolve));
|
|
95
|
-
}));
|
|
96
|
-
describe('Konstrukcja i inicjalizacja', () => {
|
|
97
|
-
it('powinno utworzyć shared subscriber przy konstrukcji', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
98
|
-
// Verify: duplicate() called once dla shared subscriber
|
|
99
|
-
expect(mockRedisConnection.duplicate).toHaveBeenCalledTimes(1);
|
|
100
|
-
// Poczekaj na async ready event
|
|
101
|
-
yield new Promise((resolve) => setImmediate(resolve));
|
|
102
|
-
// Verify: psubscribe z pattern zawierającym processInstanceId
|
|
103
|
-
expect(mockSharedSubscriber.psubscribe).toHaveBeenCalledTimes(1);
|
|
104
|
-
const pattern = mockSharedSubscriber.psubscribe.mock.calls[0][0];
|
|
105
|
-
expect(pattern).toMatch(/^rpc:response:[0-9a-f-]{36}:\*$/); // UUID pattern
|
|
106
|
-
expect(pattern).toBe(`rpc:response:${processInstanceId}:*`);
|
|
107
|
-
}));
|
|
108
|
-
it('powinno zarejestrować handlery pmessage i error', () => {
|
|
109
|
-
// Verify: pmessage handler zarejestrowany
|
|
110
|
-
const pmessageCalls = mockSharedSubscriber.on.mock.calls.filter((call) => call[0] === 'pmessage');
|
|
111
|
-
expect(pmessageCalls).toHaveLength(1);
|
|
112
|
-
// Verify: error handler zarejestrowany
|
|
113
|
-
const errorCalls = mockSharedSubscriber.on.mock.calls.filter((call) => call[0] === 'error');
|
|
114
|
-
expect(errorCalls).toHaveLength(1);
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
describe('Gotowość subscribera - waitForSubscriberReady', () => {
|
|
118
|
-
it('powinno poczekać na gotowość subscribera przed rejestrowaniem call', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
119
|
-
// Given
|
|
120
|
-
const correlationId = 'ready-test-123';
|
|
121
|
-
const commandName = 'TestCommand';
|
|
122
|
-
const timeout = 100;
|
|
123
|
-
const responseChannel = `rpc:response:${processInstanceId}:${correlationId}`;
|
|
124
|
-
// Symuluj odpowiedź RPC natychmiast (subscriber już gotowy dzięki mock)
|
|
125
|
-
setTimeout(() => {
|
|
126
|
-
var _a;
|
|
127
|
-
const pmessageHandler = (_a = mockSharedSubscriber.on.mock.calls.find((call) => call[0] === 'pmessage')) === null || _a === void 0 ? void 0 : _a[1];
|
|
128
|
-
if (pmessageHandler) {
|
|
129
|
-
const wrapper = {
|
|
130
|
-
data: JSON.stringify({
|
|
131
|
-
correlationId,
|
|
132
|
-
result: { success: true },
|
|
133
|
-
error: null,
|
|
134
|
-
}),
|
|
135
|
-
compressed: false,
|
|
136
|
-
};
|
|
137
|
-
pmessageHandler(`rpc:response:${processInstanceId}:*`, responseChannel, JSON.stringify(wrapper));
|
|
138
|
-
}
|
|
139
|
-
}, 10);
|
|
140
|
-
// When
|
|
141
|
-
const promise = rpcCoordinator.registerCall(correlationId, commandName, timeout);
|
|
142
|
-
// Then
|
|
143
|
-
yield expect(promise).resolves.toEqual({ success: true });
|
|
144
|
-
}));
|
|
145
|
-
it('powinno rzucić wyjątek timeout gdy subscriber nie jest gotowy w ciągu 5s', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
146
|
-
// Use fake timers dla tego testu
|
|
147
|
-
jest.useFakeTimers();
|
|
148
|
-
try {
|
|
149
|
-
// Given: Utwórz nowy coordinator z subscriber który NIGDY nie będzie gotowy
|
|
150
|
-
const slowSubscriber = {
|
|
151
|
-
psubscribe: jest.fn().mockImplementation(() => {
|
|
152
|
-
// NIE wywołujemy callback - subscriber nigdy nie będzie gotowy
|
|
153
|
-
return Promise.resolve(undefined);
|
|
154
|
-
}),
|
|
155
|
-
on: jest.fn().mockReturnThis(),
|
|
156
|
-
once: jest.fn().mockReturnThis(), // NIE wywołujemy 'ready' event
|
|
157
|
-
removeAllListeners: jest.fn().mockReturnThis(),
|
|
158
|
-
quit: jest.fn().mockResolvedValue(undefined),
|
|
159
|
-
};
|
|
160
|
-
const slowRedisConnection = {
|
|
161
|
-
duplicate: jest.fn().mockReturnValue(slowSubscriber),
|
|
162
|
-
};
|
|
163
|
-
const slowCoordinator = new rpc_coordinator_1.default(mockLogger, slowRedisConnection, mockCompressionService);
|
|
164
|
-
const correlationId = 'timeout-subscriber-test';
|
|
165
|
-
const commandName = 'TestCommand';
|
|
166
|
-
const timeout = 100; // Timeout dla RPC call (nie subscriber ready)
|
|
167
|
-
// When
|
|
168
|
-
const promise = slowCoordinator.registerCall(correlationId, commandName, timeout);
|
|
169
|
-
// Fast-forward time
|
|
170
|
-
jest.advanceTimersByTime(5000);
|
|
171
|
-
// Then
|
|
172
|
-
yield expect(promise).rejects.toThrow('Subscriber timeout: nie udało się nawiązać połączenia w ciągu 5000ms');
|
|
173
|
-
// Cleanup
|
|
174
|
-
yield slowCoordinator.close().catch(() => {
|
|
175
|
-
/* ignore */
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
finally {
|
|
179
|
-
// Przywróć rzeczywiste timery
|
|
180
|
-
jest.useRealTimers();
|
|
181
|
-
}
|
|
182
|
-
}));
|
|
183
|
-
});
|
|
184
|
-
describe('registerCall - shared subscriber', () => {
|
|
185
|
-
it('powinno użyć shared subscriber zamiast tworzyć nowe połączenie', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
186
|
-
// Given
|
|
187
|
-
const correlationId = 'test-correlation-123';
|
|
188
|
-
const commandName = 'TestCommand';
|
|
189
|
-
const timeout = 100;
|
|
190
|
-
const responseChannel = `rpc:response:${processInstanceId}:${correlationId}`;
|
|
191
|
-
// Symuluj odpowiedź RPC przez pmessage handler
|
|
192
|
-
setTimeout(() => {
|
|
193
|
-
var _a;
|
|
194
|
-
const pmessageHandler = (_a = mockSharedSubscriber.on.mock.calls.find((call) => call[0] === 'pmessage')) === null || _a === void 0 ? void 0 : _a[1];
|
|
195
|
-
if (pmessageHandler) {
|
|
196
|
-
// Wrapper z metadanymi kompresji
|
|
197
|
-
const wrapper = {
|
|
198
|
-
data: JSON.stringify({
|
|
199
|
-
correlationId,
|
|
200
|
-
result: { success: true },
|
|
201
|
-
error: null,
|
|
202
|
-
}),
|
|
203
|
-
compressed: false,
|
|
204
|
-
};
|
|
205
|
-
pmessageHandler(`rpc:response:${processInstanceId}:*`, responseChannel, JSON.stringify(wrapper));
|
|
206
|
-
}
|
|
207
|
-
}, 10);
|
|
208
|
-
// When
|
|
209
|
-
const promise = rpcCoordinator.registerCall(correlationId, commandName, timeout);
|
|
210
|
-
// Then
|
|
211
|
-
yield expect(promise).resolves.toEqual({ success: true });
|
|
212
|
-
// Verify: NIE wywołano duplicate() ponownie (używa shared subscriber)
|
|
213
|
-
expect(mockRedisConnection.duplicate).toHaveBeenCalledTimes(1);
|
|
214
|
-
// Verify: NIE wywołano subscribe/unsubscribe per call (używa psubscribe)
|
|
215
|
-
expect(mockSharedSubscriber.psubscribe).toHaveBeenCalledTimes(1); // Tylko przy konstrukcji
|
|
216
|
-
}));
|
|
217
|
-
it('powinno reject przy timeout', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
218
|
-
// Given
|
|
219
|
-
const correlationId = 'timeout-test';
|
|
220
|
-
const commandName = 'TestCommand';
|
|
221
|
-
const timeout = 50; // Krótki timeout
|
|
222
|
-
// When & Then
|
|
223
|
-
yield expect(rpcCoordinator.registerCall(correlationId, commandName, timeout)).rejects.toThrow('RPC timeout');
|
|
224
|
-
}));
|
|
225
|
-
it('powinno reject przy błędzie w odpowiedzi', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
226
|
-
// Given
|
|
227
|
-
const correlationId = 'error-test';
|
|
228
|
-
const commandName = 'TestCommand';
|
|
229
|
-
const timeout = 100;
|
|
230
|
-
const responseChannel = `rpc:response:${processInstanceId}:${correlationId}`;
|
|
231
|
-
// Symuluj odpowiedź z błędem
|
|
232
|
-
setTimeout(() => {
|
|
233
|
-
var _a;
|
|
234
|
-
const pmessageHandler = (_a = mockSharedSubscriber.on.mock.calls.find((call) => call[0] === 'pmessage')) === null || _a === void 0 ? void 0 : _a[1];
|
|
235
|
-
if (pmessageHandler) {
|
|
236
|
-
const wrapper = {
|
|
237
|
-
data: JSON.stringify({
|
|
238
|
-
correlationId,
|
|
239
|
-
result: null,
|
|
240
|
-
error: 'Test error',
|
|
241
|
-
}),
|
|
242
|
-
compressed: false,
|
|
243
|
-
};
|
|
244
|
-
pmessageHandler(`rpc:response:${processInstanceId}:*`, responseChannel, JSON.stringify(wrapper));
|
|
245
|
-
}
|
|
246
|
-
}, 10);
|
|
247
|
-
// When & Then
|
|
248
|
-
yield expect(rpcCoordinator.registerCall(correlationId, commandName, timeout)).rejects.toThrow('Test error');
|
|
249
|
-
}));
|
|
250
|
-
});
|
|
251
|
-
describe('prepareRpcCommand', () => {
|
|
252
|
-
it('powinno dodać metadata z responseChannel zawierającym processInstanceId', () => {
|
|
253
|
-
// Given
|
|
254
|
-
const command = new TestCommand({ value: 42 });
|
|
255
|
-
const responseChannel = `rpc:response:${processInstanceId}:${command.__id}`;
|
|
256
|
-
// When
|
|
257
|
-
const result = rpcCoordinator.prepareRpcCommand(command);
|
|
258
|
-
// Then
|
|
259
|
-
expect(result.__rpcMetadata).toBeDefined();
|
|
260
|
-
expect(result.__rpcMetadata.correlationId).toBe(command.__id);
|
|
261
|
-
expect(result.__rpcMetadata.responseChannel).toBe(responseChannel);
|
|
262
|
-
expect(result.__rpcMetadata.responseChannel).toContain(processInstanceId);
|
|
263
|
-
expect(result.__rpcMetadata.timestamp).toBeDefined();
|
|
264
|
-
});
|
|
265
|
-
});
|
|
266
|
-
describe('Izolacja processInstanceId', () => {
|
|
267
|
-
it('powinno ignorować wiadomości z innym processInstanceId', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
268
|
-
// Given
|
|
269
|
-
const correlationId = 'isolation-test';
|
|
270
|
-
const commandName = 'TestCommand';
|
|
271
|
-
const timeout = 100;
|
|
272
|
-
const wrongProcessId = 'wrong-process-id-123';
|
|
273
|
-
// Symuluj odpowiedź z INNYM processInstanceId
|
|
274
|
-
setTimeout(() => {
|
|
275
|
-
var _a;
|
|
276
|
-
const pmessageHandler = (_a = mockSharedSubscriber.on.mock.calls.find((call) => call[0] === 'pmessage')) === null || _a === void 0 ? void 0 : _a[1];
|
|
277
|
-
if (pmessageHandler) {
|
|
278
|
-
const wrapper = {
|
|
279
|
-
data: JSON.stringify({
|
|
280
|
-
correlationId,
|
|
281
|
-
result: { wrong: true },
|
|
282
|
-
error: null,
|
|
283
|
-
}),
|
|
284
|
-
compressed: false,
|
|
285
|
-
};
|
|
286
|
-
pmessageHandler(`rpc:response:${wrongProcessId}:*`, `rpc:response:${wrongProcessId}:${correlationId}`, JSON.stringify(wrapper));
|
|
287
|
-
}
|
|
288
|
-
}, 10);
|
|
289
|
-
// When
|
|
290
|
-
const promise = rpcCoordinator.registerCall(correlationId, commandName, timeout);
|
|
291
|
-
// Then: Powinno timeout (wiadomość zignorowana)
|
|
292
|
-
yield expect(promise).rejects.toThrow('RPC timeout');
|
|
293
|
-
// Verify: Log warning o wiadomości dla innego procesu
|
|
294
|
-
expect(mockLogger.warn).toHaveBeenCalledWith('Otrzymano wiadomość dla innego procesu', expect.objectContaining({
|
|
295
|
-
processInstanceId,
|
|
296
|
-
receivedProcessId: wrongProcessId,
|
|
297
|
-
correlationId,
|
|
298
|
-
}));
|
|
299
|
-
}));
|
|
300
|
-
it('powinno ignorować wiadomości dla nieistniejących pending calls', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
301
|
-
var _a;
|
|
302
|
-
// Given
|
|
303
|
-
const nonExistentCorrelationId = 'non-existent-123';
|
|
304
|
-
const responseChannel = `rpc:response:${processInstanceId}:${nonExistentCorrelationId}`;
|
|
305
|
-
// Symuluj odpowiedź dla nieistniejącego call
|
|
306
|
-
const pmessageHandler = (_a = mockSharedSubscriber.on.mock.calls.find((call) => call[0] === 'pmessage')) === null || _a === void 0 ? void 0 : _a[1];
|
|
307
|
-
if (pmessageHandler) {
|
|
308
|
-
const wrapper = {
|
|
309
|
-
data: JSON.stringify({
|
|
310
|
-
correlationId: nonExistentCorrelationId,
|
|
311
|
-
result: { data: 'test' },
|
|
312
|
-
error: null,
|
|
313
|
-
}),
|
|
314
|
-
compressed: false,
|
|
315
|
-
};
|
|
316
|
-
pmessageHandler(`rpc:response:${processInstanceId}:*`, responseChannel, JSON.stringify(wrapper));
|
|
317
|
-
}
|
|
318
|
-
// Wait for async handling
|
|
319
|
-
yield new Promise((resolve) => setTimeout(resolve, 50));
|
|
320
|
-
// Verify: Log warning o nieistniejącym pending call
|
|
321
|
-
expect(mockLogger.warn).toHaveBeenCalledWith('Otrzymano odpowiedź dla nieistniejącego RPC call', expect.objectContaining({
|
|
322
|
-
processInstanceId,
|
|
323
|
-
correlationId: nonExistentCorrelationId,
|
|
324
|
-
}));
|
|
325
|
-
}));
|
|
326
|
-
});
|
|
327
|
-
describe('Concurrent RPC calls - Shared Subscriber', () => {
|
|
328
|
-
it('powinno obsłużyć 16 jednoczesnych RPC calls używając 1 shared subscriber', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
329
|
-
// Given
|
|
330
|
-
const concurrentCalls = 16;
|
|
331
|
-
const timeout = 200;
|
|
332
|
-
const responseDelay = 50;
|
|
333
|
-
// When: Wystartuj 16 równoległych RPC calls
|
|
334
|
-
const promises = Array.from({ length: concurrentCalls }, (_, index) => {
|
|
335
|
-
const correlationId = `concurrent-test-${index}`;
|
|
336
|
-
const commandName = 'ConcurrentTestCommand';
|
|
337
|
-
const responseChannel = `rpc:response:${processInstanceId}:${correlationId}`;
|
|
338
|
-
// Symuluj odpowiedź RPC dla każdego call
|
|
339
|
-
setTimeout(() => {
|
|
340
|
-
var _a;
|
|
341
|
-
const pmessageHandler = (_a = mockSharedSubscriber.on.mock.calls.find((call) => call[0] === 'pmessage')) === null || _a === void 0 ? void 0 : _a[1];
|
|
342
|
-
if (pmessageHandler) {
|
|
343
|
-
const wrapper = {
|
|
344
|
-
data: JSON.stringify({
|
|
345
|
-
correlationId,
|
|
346
|
-
result: { index, success: true },
|
|
347
|
-
error: null,
|
|
348
|
-
}),
|
|
349
|
-
compressed: false,
|
|
350
|
-
};
|
|
351
|
-
pmessageHandler(`rpc:response:${processInstanceId}:*`, responseChannel, JSON.stringify(wrapper));
|
|
352
|
-
}
|
|
353
|
-
}, responseDelay);
|
|
354
|
-
return rpcCoordinator.registerCall(correlationId, commandName, timeout);
|
|
355
|
-
});
|
|
356
|
-
// Then: Wszystkie 16 calls powinno się zakończyć sukcesem
|
|
357
|
-
const results = yield Promise.all(promises);
|
|
358
|
-
// Weryfikacja: wszystkie wyniki są poprawne
|
|
359
|
-
expect(results).toHaveLength(concurrentCalls);
|
|
360
|
-
results.forEach((result, index) => {
|
|
361
|
-
expect(result).toEqual({ index, success: true });
|
|
362
|
-
});
|
|
363
|
-
// Weryfikacja: TYLKO 1 duplicate() (shared subscriber)
|
|
364
|
-
expect(mockRedisConnection.duplicate).toHaveBeenCalledTimes(1);
|
|
365
|
-
// Weryfikacja: TYLKO 1 psubscribe (przy konstrukcji)
|
|
366
|
-
expect(mockSharedSubscriber.psubscribe).toHaveBeenCalledTimes(1);
|
|
367
|
-
}), 10000);
|
|
368
|
-
it('powinno obsłużyć race condition - odpowiedź publikowana natychmiast po rejestracji', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
369
|
-
var _a;
|
|
370
|
-
// Given: Worker bardzo szybki - publikuje odpowiedź natychmiast po rejestracji
|
|
371
|
-
const correlationId = 'race-condition-test';
|
|
372
|
-
const commandName = 'FastCommand';
|
|
373
|
-
const timeout = 100;
|
|
374
|
-
const responseChannel = `rpc:response:${processInstanceId}:${correlationId}`;
|
|
375
|
-
// When: Rejestruj call i natychmiast po tym publikuj odpowiedź
|
|
376
|
-
const resultPromise = rpcCoordinator.registerCall(correlationId, commandName, timeout);
|
|
377
|
-
// Poczekaj minimalny czas na rejestrację pending call w Map
|
|
378
|
-
// (registerCall() jest async ze względu na waitForSubscriberReady)
|
|
379
|
-
yield new Promise((resolve) => setTimeout(resolve, 5));
|
|
380
|
-
// Symuluj NATYCHMIASTOWĄ odpowiedź po rejestracji
|
|
381
|
-
const pmessageHandler = (_a = mockSharedSubscriber.on.mock.calls.find((call) => call[0] === 'pmessage')) === null || _a === void 0 ? void 0 : _a[1];
|
|
382
|
-
if (pmessageHandler) {
|
|
383
|
-
const wrapper = {
|
|
384
|
-
data: JSON.stringify({
|
|
385
|
-
correlationId,
|
|
386
|
-
result: { veryFast: true },
|
|
387
|
-
error: null,
|
|
388
|
-
}),
|
|
389
|
-
compressed: false,
|
|
390
|
-
};
|
|
391
|
-
pmessageHandler(`rpc:response:${processInstanceId}:*`, responseChannel, JSON.stringify(wrapper));
|
|
392
|
-
}
|
|
393
|
-
const result = yield resultPromise;
|
|
394
|
-
// Then: Powinna dotrzeć odpowiedź (shared subscriber zawsze gotowy)
|
|
395
|
-
expect(result).toEqual({ veryFast: true });
|
|
396
|
-
// Verify: Brak timeout
|
|
397
|
-
expect(mockLogger.error).not.toHaveBeenCalledWith('RPC timeout', expect.any(Object));
|
|
398
|
-
}));
|
|
399
|
-
});
|
|
400
|
-
describe('close()', () => {
|
|
401
|
-
it('powinno reject wszystkie pending calls przy zamykaniu', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
402
|
-
// Given: Zarejestruj 3 pending calls
|
|
403
|
-
const promises = Array.from({ length: 3 }, (_, index) => {
|
|
404
|
-
const correlationId = `close-test-${index}`;
|
|
405
|
-
return rpcCoordinator
|
|
406
|
-
.registerCall(correlationId, 'TestCommand', 1000)
|
|
407
|
-
.catch((error) => ({ rejected: true, error: error.message }));
|
|
408
|
-
});
|
|
409
|
-
// Wait for calls to register
|
|
410
|
-
yield new Promise((resolve) => setTimeout(resolve, 50));
|
|
411
|
-
// When: Zamknij coordinator
|
|
412
|
-
yield rpcCoordinator.close();
|
|
413
|
-
// Then: Wszystkie calls zostały rejected
|
|
414
|
-
const results = yield Promise.all(promises);
|
|
415
|
-
results.forEach((result) => {
|
|
416
|
-
expect(result).toEqual({
|
|
417
|
-
rejected: true,
|
|
418
|
-
error: 'RpcCoordinator is closing',
|
|
419
|
-
});
|
|
420
|
-
});
|
|
421
|
-
// Verify: Zamknięcie shared subscriber
|
|
422
|
-
expect(mockSharedSubscriber.punsubscribe).toHaveBeenCalledWith(`rpc:response:${processInstanceId}:*`);
|
|
423
|
-
expect(mockSharedSubscriber.quit).toHaveBeenCalled();
|
|
424
|
-
}));
|
|
425
|
-
});
|
|
426
|
-
describe('setJobId() - powiązanie pending call z jobem BullMQ', () => {
|
|
427
|
-
it('powinno ustawić jobId i queueName dla istniejącego pending call', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
428
|
-
// Given
|
|
429
|
-
const correlationId = 'set-job-id-test';
|
|
430
|
-
const commandName = 'TestCommand';
|
|
431
|
-
const timeout = 200;
|
|
432
|
-
const jobId = 'job-123';
|
|
433
|
-
const queueName = 'TestQueue';
|
|
434
|
-
const responseChannel = `rpc:response:${processInstanceId}:${correlationId}`;
|
|
435
|
-
// Symuluj odpowiedź RPC
|
|
436
|
-
setTimeout(() => {
|
|
437
|
-
var _a;
|
|
438
|
-
const pmessageHandler = (_a = mockSharedSubscriber.on.mock.calls.find((call) => call[0] === 'pmessage')) === null || _a === void 0 ? void 0 : _a[1];
|
|
439
|
-
if (pmessageHandler) {
|
|
440
|
-
const wrapper = {
|
|
441
|
-
data: JSON.stringify({
|
|
442
|
-
correlationId,
|
|
443
|
-
result: { success: true },
|
|
444
|
-
error: null,
|
|
445
|
-
}),
|
|
446
|
-
compressed: false,
|
|
447
|
-
};
|
|
448
|
-
pmessageHandler(`rpc:response:${processInstanceId}:*`, responseChannel, JSON.stringify(wrapper));
|
|
449
|
-
}
|
|
450
|
-
}, 50);
|
|
451
|
-
// When
|
|
452
|
-
const promise = rpcCoordinator.registerCall(correlationId, commandName, timeout);
|
|
453
|
-
// Poczekaj na rejestrację pending call
|
|
454
|
-
yield new Promise((resolve) => setTimeout(resolve, 10));
|
|
455
|
-
// Ustaw jobId
|
|
456
|
-
rpcCoordinator.setJobId(correlationId, jobId, queueName);
|
|
457
|
-
// Then
|
|
458
|
-
yield expect(promise).resolves.toEqual({ success: true });
|
|
459
|
-
}));
|
|
460
|
-
it('powinno ignorować setJobId dla nieistniejącego pending call', () => {
|
|
461
|
-
// Given
|
|
462
|
-
const nonExistentCorrelationId = 'non-existent-123';
|
|
463
|
-
const jobId = 'job-456';
|
|
464
|
-
const queueName = 'TestQueue';
|
|
465
|
-
// When & Then - nie powinno rzucić błędu
|
|
466
|
-
expect(() => {
|
|
467
|
-
rpcCoordinator.setJobId(nonExistentCorrelationId, jobId, queueName);
|
|
468
|
-
}).not.toThrow();
|
|
469
|
-
// Verify: zalogowano debug
|
|
470
|
-
expect(mockLogger.debug).toHaveBeenCalledWith(expect.stringContaining('Próba ustawienia jobId dla nieistniejącego pending call'), expect.objectContaining({ correlationId: nonExistentCorrelationId }));
|
|
471
|
-
});
|
|
472
|
-
});
|
|
473
|
-
describe('Cancellation przy timeout', () => {
|
|
474
|
-
it('powinno wywołać markAsCancelled przy timeout', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
475
|
-
// Given
|
|
476
|
-
const correlationId = 'cancellation-test';
|
|
477
|
-
const commandName = 'TestCommand';
|
|
478
|
-
const timeout = 50;
|
|
479
|
-
// When
|
|
480
|
-
yield expect(rpcCoordinator.registerCall(correlationId, commandName, timeout)).rejects.toThrow('RPC timeout');
|
|
481
|
-
// Poczekaj na async handleTimeout
|
|
482
|
-
yield new Promise((resolve) => setTimeout(resolve, 10));
|
|
483
|
-
// Then
|
|
484
|
-
expect(mockCancellationService.markAsCancelled).toHaveBeenCalledWith(correlationId);
|
|
485
|
-
}));
|
|
486
|
-
it('powinno wywołać tryRemoveJob gdy jobId jest ustawione', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
487
|
-
// Given
|
|
488
|
-
const correlationId = 'remove-job-test';
|
|
489
|
-
const commandName = 'TestCommand';
|
|
490
|
-
const timeout = 100;
|
|
491
|
-
const jobId = 'job-to-remove-789';
|
|
492
|
-
const queueName = 'TestQueueRemove';
|
|
493
|
-
// When
|
|
494
|
-
const promise = rpcCoordinator.registerCall(correlationId, commandName, timeout);
|
|
495
|
-
// Poczekaj na rejestrację i ustaw jobId
|
|
496
|
-
yield new Promise((resolve) => setTimeout(resolve, 10));
|
|
497
|
-
rpcCoordinator.setJobId(correlationId, jobId, queueName);
|
|
498
|
-
// Czekaj na timeout
|
|
499
|
-
yield expect(promise).rejects.toThrow('RPC timeout');
|
|
500
|
-
// Poczekaj na async handleTimeout
|
|
501
|
-
yield new Promise((resolve) => setTimeout(resolve, 20));
|
|
502
|
-
// Then
|
|
503
|
-
expect(mockCancellationService.markAsCancelled).toHaveBeenCalledWith(correlationId);
|
|
504
|
-
expect(mockCancellationService.tryRemoveJob).toHaveBeenCalledWith(jobId, queueName, mockRemoveJobCallback);
|
|
505
|
-
}));
|
|
506
|
-
it('powinno wywołać clearCancellation gdy job został usunięty', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
507
|
-
// Given
|
|
508
|
-
const correlationId = 'clear-after-remove-test';
|
|
509
|
-
const commandName = 'TestCommand';
|
|
510
|
-
const timeout = 100;
|
|
511
|
-
const jobId = 'job-removed-successfully';
|
|
512
|
-
const queueName = 'TestQueueClear';
|
|
513
|
-
// Symuluj pomyślne usunięcie joba
|
|
514
|
-
mockCancellationService.tryRemoveJob.mockResolvedValue(true);
|
|
515
|
-
// When
|
|
516
|
-
const promise = rpcCoordinator.registerCall(correlationId, commandName, timeout);
|
|
517
|
-
yield new Promise((resolve) => setTimeout(resolve, 10));
|
|
518
|
-
rpcCoordinator.setJobId(correlationId, jobId, queueName);
|
|
519
|
-
yield expect(promise).rejects.toThrow('RPC timeout');
|
|
520
|
-
yield new Promise((resolve) => setTimeout(resolve, 20));
|
|
521
|
-
// Then
|
|
522
|
-
expect(mockCancellationService.clearCancellation).toHaveBeenCalledWith(correlationId);
|
|
523
|
-
}));
|
|
524
|
-
it('NIE powinno wywołać clearCancellation gdy job nie został usunięty', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
525
|
-
// Given
|
|
526
|
-
const correlationId = 'no-clear-test';
|
|
527
|
-
const commandName = 'TestCommand';
|
|
528
|
-
const timeout = 100;
|
|
529
|
-
const jobId = 'job-not-removed';
|
|
530
|
-
const queueName = 'TestQueueNoClear';
|
|
531
|
-
// Symuluj nieudane usunięcie joba (już przetwarzany)
|
|
532
|
-
mockCancellationService.tryRemoveJob.mockResolvedValue(false);
|
|
533
|
-
// When
|
|
534
|
-
const promise = rpcCoordinator.registerCall(correlationId, commandName, timeout);
|
|
535
|
-
yield new Promise((resolve) => setTimeout(resolve, 10));
|
|
536
|
-
rpcCoordinator.setJobId(correlationId, jobId, queueName);
|
|
537
|
-
yield expect(promise).rejects.toThrow('RPC timeout');
|
|
538
|
-
yield new Promise((resolve) => setTimeout(resolve, 20));
|
|
539
|
-
// Then - clearCancellation NIE wywołane
|
|
540
|
-
expect(mockCancellationService.clearCancellation).not.toHaveBeenCalled();
|
|
541
|
-
}));
|
|
542
|
-
it('NIE powinno wywołać tryRemoveJob gdy jobId nie jest ustawione', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
543
|
-
// Given
|
|
544
|
-
const correlationId = 'no-job-id-test';
|
|
545
|
-
const commandName = 'TestCommand';
|
|
546
|
-
const timeout = 50;
|
|
547
|
-
// When - NIE ustawiamy jobId
|
|
548
|
-
yield expect(rpcCoordinator.registerCall(correlationId, commandName, timeout)).rejects.toThrow('RPC timeout');
|
|
549
|
-
yield new Promise((resolve) => setTimeout(resolve, 10));
|
|
550
|
-
// Then - markAsCancelled wywołane, ale tryRemoveJob NIE
|
|
551
|
-
expect(mockCancellationService.markAsCancelled).toHaveBeenCalledWith(correlationId);
|
|
552
|
-
expect(mockCancellationService.tryRemoveJob).not.toHaveBeenCalled();
|
|
553
|
-
}));
|
|
554
|
-
it('powinno obsłużyć błędy cancellation service gracefully', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
555
|
-
// Given
|
|
556
|
-
const correlationId = 'error-handling-test';
|
|
557
|
-
const commandName = 'TestCommand';
|
|
558
|
-
const timeout = 50;
|
|
559
|
-
// Symuluj błąd w cancellation service
|
|
560
|
-
mockCancellationService.markAsCancelled.mockRejectedValue(new Error('Redis error'));
|
|
561
|
-
// When - nie powinno zmienić zachowania timeout
|
|
562
|
-
yield expect(rpcCoordinator.registerCall(correlationId, commandName, timeout)).rejects.toThrow('RPC timeout');
|
|
563
|
-
// Then - błąd obsłużony, nie propagowany
|
|
564
|
-
// (test przechodzi jeśli nie ma unhandled rejection)
|
|
565
|
-
}));
|
|
566
|
-
});
|
|
567
|
-
describe('Logowanie reconnect', () => {
|
|
568
|
-
it('powinno logować INFO po udanym reconnect', () => {
|
|
569
|
-
var _a, _b;
|
|
570
|
-
// Given: Pobierz handlery eventów
|
|
571
|
-
const onCalls = mockSharedSubscriber.on.mock.calls;
|
|
572
|
-
const reconnectingHandler = (_a = onCalls.find((call) => call[0] === 'reconnecting')) === null || _a === void 0 ? void 0 : _a[1];
|
|
573
|
-
const readyHandler = (_b = onCalls.find((call) => call[0] === 'ready')) === null || _b === void 0 ? void 0 : _b[1];
|
|
574
|
-
expect(reconnectingHandler).toBeDefined();
|
|
575
|
-
expect(readyHandler).toBeDefined();
|
|
576
|
-
// When: Symuluj reconnect
|
|
577
|
-
reconnectingHandler();
|
|
578
|
-
readyHandler();
|
|
579
|
-
// Then: Powinno zalogować INFO (logger.log) o ponownym połączeniu
|
|
580
|
-
expect(mockLogger.log).toHaveBeenCalledWith('Shared subscriber RPC - ponowne łączenie', expect.objectContaining({
|
|
581
|
-
processInstanceId,
|
|
582
|
-
}));
|
|
583
|
-
expect(mockLogger.log).toHaveBeenCalledWith('Shared subscriber RPC - ponownie połączony', expect.objectContaining({
|
|
584
|
-
processInstanceId,
|
|
585
|
-
reconnected: true,
|
|
586
|
-
}));
|
|
587
|
-
});
|
|
588
|
-
it('NIE powinno logować INFO przy pierwszym ready (bez reconnecting)', () => {
|
|
589
|
-
var _a;
|
|
590
|
-
// Given: Pobierz handler ready
|
|
591
|
-
const onCalls = mockSharedSubscriber.on.mock.calls;
|
|
592
|
-
const readyHandler = (_a = onCalls.find((call) => call[0] === 'ready')) === null || _a === void 0 ? void 0 : _a[1];
|
|
593
|
-
expect(readyHandler).toBeDefined();
|
|
594
|
-
// Wyczyść poprzednie wywołania
|
|
595
|
-
mockLogger.log.mockClear();
|
|
596
|
-
// When: Wywołaj ready BEZ wcześniejszego reconnecting
|
|
597
|
-
readyHandler();
|
|
598
|
-
// Then: NIE powinno logować "ponownie połączony"
|
|
599
|
-
expect(mockLogger.log).not.toHaveBeenCalledWith('Shared subscriber RPC - ponownie połączony', expect.any(Object));
|
|
600
|
-
});
|
|
601
|
-
it('powinno resetować flagę isReconnecting po logowaniu', () => {
|
|
602
|
-
var _a, _b;
|
|
603
|
-
// Given: Pobierz handlery eventów
|
|
604
|
-
const onCalls = mockSharedSubscriber.on.mock.calls;
|
|
605
|
-
const reconnectingHandler = (_a = onCalls.find((call) => call[0] === 'reconnecting')) === null || _a === void 0 ? void 0 : _a[1];
|
|
606
|
-
const readyHandler = (_b = onCalls.find((call) => call[0] === 'ready')) === null || _b === void 0 ? void 0 : _b[1];
|
|
607
|
-
expect(reconnectingHandler).toBeDefined();
|
|
608
|
-
expect(readyHandler).toBeDefined();
|
|
609
|
-
// When: Symuluj reconnect
|
|
610
|
-
reconnectingHandler();
|
|
611
|
-
readyHandler();
|
|
612
|
-
// Wyczyść wywołania
|
|
613
|
-
mockLogger.log.mockClear();
|
|
614
|
-
// Drugie wywołanie ready (bez reconnecting)
|
|
615
|
-
readyHandler();
|
|
616
|
-
// Then: Drugie ready NIE loguje INFO (flaga zresetowana)
|
|
617
|
-
expect(mockLogger.log).not.toHaveBeenCalledWith('Shared subscriber RPC - ponownie połączony', expect.any(Object));
|
|
618
|
-
});
|
|
619
|
-
});
|
|
620
|
-
});
|
|
621
|
-
//# sourceMappingURL=rpc-coordinator.spec.js.map
|