pp-command-bus 1.2.0 → 1.2.2
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/dist/command-bus/command-bus.spec.js +13 -0
- package/dist/command-bus/command-bus.spec.js.map +1 -1
- package/dist/command-bus/config/command-bus-config.d.ts +6 -0
- package/dist/command-bus/config/command-bus-config.js +4 -0
- package/dist/command-bus/config/command-bus-config.js.map +1 -1
- package/dist/command-bus/index.js +7 -5
- package/dist/command-bus/index.js.map +1 -1
- package/dist/command-bus/job/job-processor.d.ts +5 -2
- package/dist/command-bus/job/job-processor.js +15 -4
- package/dist/command-bus/job/job-processor.js.map +1 -1
- package/dist/command-bus/job/job-processor.spec.js +26 -8
- package/dist/command-bus/job/job-processor.spec.js.map +1 -1
- package/dist/command-bus/rpc/index.d.ts +3 -0
- package/dist/command-bus/rpc/index.js +4 -1
- package/dist/command-bus/rpc/index.js.map +1 -1
- package/dist/command-bus/rpc/payload-compression.service.d.ts +32 -0
- package/dist/command-bus/rpc/payload-compression.service.js +109 -0
- package/dist/command-bus/rpc/payload-compression.service.js.map +1 -0
- package/dist/command-bus/rpc/payload-compression.service.spec.d.ts +1 -0
- package/dist/command-bus/rpc/payload-compression.service.spec.js +233 -0
- package/dist/command-bus/rpc/payload-compression.service.spec.js.map +1 -0
- package/dist/command-bus/rpc/rpc-coordinator.d.ts +45 -27
- package/dist/command-bus/rpc/rpc-coordinator.js +255 -178
- package/dist/command-bus/rpc/rpc-coordinator.js.map +1 -1
- package/dist/command-bus/rpc/rpc-coordinator.spec.js +246 -31
- package/dist/command-bus/rpc/rpc-coordinator.spec.js.map +1 -1
- package/dist/command-bus/types/index.d.ts +14 -2
- package/dist/pp-command-bus-1.2.2.tgz +0 -0
- package/package.json +1 -1
- package/dist/pp-command-bus-1.2.0.tgz +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payload-compression.service.js","sourceRoot":"","sources":["../../../src/command-bus/rpc/payload-compression.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,233 @@
|
|
|
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 payload_compression_service_1 = __importDefault(require("./payload-compression.service"));
|
|
16
|
+
/**
|
|
17
|
+
* Testy dla PayloadCompressionService
|
|
18
|
+
* Testuje kompresję gzip dla payloadów RPC >threshold
|
|
19
|
+
*/
|
|
20
|
+
describe('PayloadCompressionService', () => {
|
|
21
|
+
let service;
|
|
22
|
+
let mockLogger;
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
mockLogger = {
|
|
25
|
+
debug: jest.fn(),
|
|
26
|
+
log: jest.fn(),
|
|
27
|
+
warn: jest.fn(),
|
|
28
|
+
error: jest.fn(),
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
describe('compress()', () => {
|
|
32
|
+
it('nie kompresuje payloadu mniejszego niż threshold (1KB)', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
33
|
+
// Arrange
|
|
34
|
+
service = new payload_compression_service_1.default(1024, mockLogger);
|
|
35
|
+
const smallPayload = { correlationId: 'test-123', result: 'ok', error: null };
|
|
36
|
+
// Act
|
|
37
|
+
const { data, compressed } = yield service.compress(smallPayload);
|
|
38
|
+
// Assert
|
|
39
|
+
expect(compressed).toBe(false);
|
|
40
|
+
expect(data).toBe(JSON.stringify(smallPayload));
|
|
41
|
+
expect(mockLogger.debug).toHaveBeenCalledWith(expect.stringContaining('Payload NIE skompresowany'), expect.objectContaining({
|
|
42
|
+
originalSize: expect.any(Number),
|
|
43
|
+
threshold: 1024,
|
|
44
|
+
}));
|
|
45
|
+
}));
|
|
46
|
+
it('kompresuje payload większy niż threshold (1KB)', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
47
|
+
// Arrange
|
|
48
|
+
service = new payload_compression_service_1.default(1024, mockLogger);
|
|
49
|
+
// Utwórz duży payload >1KB
|
|
50
|
+
const largePayload = {
|
|
51
|
+
correlationId: 'test-456',
|
|
52
|
+
result: Array.from({ length: 100 }, (_, i) => ({
|
|
53
|
+
id: i,
|
|
54
|
+
name: `Item ${i}`,
|
|
55
|
+
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
|
56
|
+
})),
|
|
57
|
+
error: null,
|
|
58
|
+
};
|
|
59
|
+
// Act
|
|
60
|
+
const { data, compressed } = yield service.compress(largePayload);
|
|
61
|
+
// Assert
|
|
62
|
+
expect(compressed).toBe(true);
|
|
63
|
+
expect(data).not.toBe(JSON.stringify(largePayload)); // Skompresowane
|
|
64
|
+
expect(typeof data).toBe('string'); // Base64 string
|
|
65
|
+
expect(mockLogger.debug).toHaveBeenCalledWith(expect.stringContaining('Payload skompresowany'), expect.objectContaining({
|
|
66
|
+
originalSize: expect.any(Number),
|
|
67
|
+
compressedSize: expect.any(Number),
|
|
68
|
+
compressionRatio: expect.any(String),
|
|
69
|
+
}));
|
|
70
|
+
}));
|
|
71
|
+
it('używa niestandardowego threshold (512 bytes)', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
72
|
+
// Arrange
|
|
73
|
+
service = new payload_compression_service_1.default(512, mockLogger);
|
|
74
|
+
const mediumPayload = {
|
|
75
|
+
correlationId: 'test-789',
|
|
76
|
+
result: Array.from({ length: 30 }, (_, i) => ({
|
|
77
|
+
id: i,
|
|
78
|
+
data: 'test data item with more content to exceed 512 bytes threshold',
|
|
79
|
+
})),
|
|
80
|
+
error: null,
|
|
81
|
+
};
|
|
82
|
+
// Act
|
|
83
|
+
const { compressed } = yield service.compress(mediumPayload);
|
|
84
|
+
// Assert - ten payload jest >512B więc powinien być skompresowany
|
|
85
|
+
expect(compressed).toBe(true);
|
|
86
|
+
}));
|
|
87
|
+
it('zawsze kompresuje gdy threshold=0', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
88
|
+
// Arrange
|
|
89
|
+
service = new payload_compression_service_1.default(0, mockLogger);
|
|
90
|
+
const tinyPayload = { result: 'ok' };
|
|
91
|
+
// Act
|
|
92
|
+
const { compressed } = yield service.compress(tinyPayload);
|
|
93
|
+
// Assert
|
|
94
|
+
expect(compressed).toBe(true);
|
|
95
|
+
}));
|
|
96
|
+
it('oblicza compression ratio poprawnie', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
97
|
+
// Arrange
|
|
98
|
+
service = new payload_compression_service_1.default(100, mockLogger);
|
|
99
|
+
const payload = {
|
|
100
|
+
data: Array.from({ length: 50 }, () => 'repeated text for compression test '),
|
|
101
|
+
};
|
|
102
|
+
// Act
|
|
103
|
+
yield service.compress(payload);
|
|
104
|
+
// Assert
|
|
105
|
+
expect(mockLogger.debug).toHaveBeenCalledWith(expect.stringContaining('Payload skompresowany'), expect.objectContaining({
|
|
106
|
+
compressionRatio: expect.stringMatching(/\d+%/), // Format: "XX%"
|
|
107
|
+
}));
|
|
108
|
+
}));
|
|
109
|
+
});
|
|
110
|
+
describe('decompress()', () => {
|
|
111
|
+
it('dekompresuje payload gdy compressed=true', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
112
|
+
// Arrange
|
|
113
|
+
service = new payload_compression_service_1.default(100, mockLogger);
|
|
114
|
+
const originalPayload = {
|
|
115
|
+
correlationId: 'test-999',
|
|
116
|
+
result: {
|
|
117
|
+
status: 'success',
|
|
118
|
+
data: Array.from({ length: 20 }, (_, i) => ({
|
|
119
|
+
id: i,
|
|
120
|
+
value: `item-${i}`,
|
|
121
|
+
description: 'some longer text to make payload bigger',
|
|
122
|
+
})),
|
|
123
|
+
},
|
|
124
|
+
error: null,
|
|
125
|
+
};
|
|
126
|
+
// Najpierw skompresuj
|
|
127
|
+
const { data: compressedData, compressed } = yield service.compress(originalPayload);
|
|
128
|
+
expect(compressed).toBe(true);
|
|
129
|
+
// Act - dekompresuj
|
|
130
|
+
const decompressed = yield service.decompress(compressedData, true);
|
|
131
|
+
// Assert
|
|
132
|
+
expect(decompressed).toEqual(originalPayload);
|
|
133
|
+
}));
|
|
134
|
+
it('parsuje JSON gdy compressed=false', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
135
|
+
// Arrange
|
|
136
|
+
service = new payload_compression_service_1.default(10000, mockLogger); // Bardzo wysoki threshold
|
|
137
|
+
const originalPayload = {
|
|
138
|
+
correlationId: 'test-111',
|
|
139
|
+
result: 'simple result',
|
|
140
|
+
error: null,
|
|
141
|
+
};
|
|
142
|
+
// Kompresuj (ale nie zostanie skompresowany bo <10KB)
|
|
143
|
+
const { data, compressed } = yield service.compress(originalPayload);
|
|
144
|
+
expect(compressed).toBe(false);
|
|
145
|
+
// Act - dekompresuj
|
|
146
|
+
const decompressed = yield service.decompress(data, false);
|
|
147
|
+
// Assert
|
|
148
|
+
expect(decompressed).toEqual(originalPayload);
|
|
149
|
+
}));
|
|
150
|
+
it('rzuca błąd gdy corrupted gzip data', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
151
|
+
// Arrange
|
|
152
|
+
service = new payload_compression_service_1.default(1024, mockLogger);
|
|
153
|
+
const corruptedData = 'invalid-base64-gzip-data!!!';
|
|
154
|
+
// Act & Assert
|
|
155
|
+
yield expect(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
156
|
+
yield service.decompress(corruptedData, true);
|
|
157
|
+
})).rejects.toThrow('Failed to decompress payload');
|
|
158
|
+
expect(mockLogger.error).toHaveBeenCalledWith(expect.stringContaining('Błąd dekompresji'), expect.any(Object));
|
|
159
|
+
}));
|
|
160
|
+
it('rzuca błąd gdy invalid JSON (compressed=false)', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
161
|
+
// Arrange
|
|
162
|
+
service = new payload_compression_service_1.default(1024, mockLogger);
|
|
163
|
+
const invalidJson = '{invalid json}';
|
|
164
|
+
// Act & Assert
|
|
165
|
+
yield expect(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
166
|
+
yield service.decompress(invalidJson, false);
|
|
167
|
+
})).rejects.toThrow();
|
|
168
|
+
}));
|
|
169
|
+
});
|
|
170
|
+
describe('edge cases', () => {
|
|
171
|
+
it('obsługuje pusty payload', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
172
|
+
// Arrange
|
|
173
|
+
service = new payload_compression_service_1.default(1024, mockLogger);
|
|
174
|
+
const emptyPayload = {};
|
|
175
|
+
// Act
|
|
176
|
+
const { data, compressed } = yield service.compress(emptyPayload);
|
|
177
|
+
const decompressed = yield service.decompress(data, compressed);
|
|
178
|
+
// Assert
|
|
179
|
+
expect(decompressed).toEqual(emptyPayload);
|
|
180
|
+
}));
|
|
181
|
+
it('obsługuje payload z null i undefined', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
182
|
+
// Arrange
|
|
183
|
+
service = new payload_compression_service_1.default(1024, mockLogger);
|
|
184
|
+
const payload = { result: null, error: undefined };
|
|
185
|
+
// Act
|
|
186
|
+
const { data, compressed } = yield service.compress(payload);
|
|
187
|
+
const decompressed = yield service.decompress(data, compressed);
|
|
188
|
+
// Assert
|
|
189
|
+
expect(decompressed).toEqual({ result: null, error: undefined });
|
|
190
|
+
}));
|
|
191
|
+
it('obsługuje payload z obiektami zagnieżdżonymi', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
192
|
+
// Arrange
|
|
193
|
+
service = new payload_compression_service_1.default(100, mockLogger);
|
|
194
|
+
const nestedPayload = {
|
|
195
|
+
level1: {
|
|
196
|
+
level2: {
|
|
197
|
+
level3: {
|
|
198
|
+
data: [1, 2, 3],
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
// Act
|
|
204
|
+
const { data, compressed } = yield service.compress(nestedPayload);
|
|
205
|
+
const decompressed = yield service.decompress(data, compressed);
|
|
206
|
+
// Assert
|
|
207
|
+
expect(decompressed).toEqual(nestedPayload);
|
|
208
|
+
}));
|
|
209
|
+
it('osiąga compression ratio >50% dla typowego JSON', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
210
|
+
// Arrange
|
|
211
|
+
service = new payload_compression_service_1.default(100, mockLogger);
|
|
212
|
+
const typicalPayload = {
|
|
213
|
+
correlationId: 'abc-123',
|
|
214
|
+
result: Array.from({ length: 50 }, (_, i) => ({
|
|
215
|
+
id: i,
|
|
216
|
+
name: `User ${i}`,
|
|
217
|
+
email: `user${i}@example.com`,
|
|
218
|
+
active: true,
|
|
219
|
+
})),
|
|
220
|
+
error: null,
|
|
221
|
+
};
|
|
222
|
+
// Act
|
|
223
|
+
const { data, compressed } = yield service.compress(typicalPayload);
|
|
224
|
+
// Assert
|
|
225
|
+
expect(compressed).toBe(true);
|
|
226
|
+
const originalSize = Buffer.byteLength(JSON.stringify(typicalPayload), 'utf8');
|
|
227
|
+
const compressedSize = Buffer.byteLength(data, 'utf8');
|
|
228
|
+
const ratio = ((originalSize - compressedSize) / originalSize) * 100;
|
|
229
|
+
expect(ratio).toBeGreaterThan(50); // >50% redukcja
|
|
230
|
+
}));
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
//# sourceMappingURL=payload-compression.service.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payload-compression.service.spec.js","sourceRoot":"","sources":["../../../src/command-bus/rpc/payload-compression.service.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,47 +2,67 @@ import type { Redis } from 'ioredis';
|
|
|
2
2
|
import type { ILogger } from '../../shared/types';
|
|
3
3
|
import type { RpcMetadata } from '../types';
|
|
4
4
|
import type Command from '../command';
|
|
5
|
+
import type PayloadCompressionService from './payload-compression.service';
|
|
5
6
|
/**
|
|
6
7
|
* Zarządza lifecycle wywołań RPC przez Redis Pub/Sub
|
|
7
|
-
*
|
|
8
|
-
*
|
|
8
|
+
* Używa shared subscriber z pattern matching dla izolacji między procesami
|
|
9
|
+
* Multiplexing odpowiedzi przez Map<correlationId, PendingCall>
|
|
10
|
+
*
|
|
11
|
+
* Architektura: Jeden shared subscriber per proces
|
|
12
|
+
* - Eliminuje race conditions (subscriber zawsze gotowy)
|
|
13
|
+
* - Jedno połączenie Redis zamiast N per RPC call
|
|
14
|
+
* - Pattern: rpc:response:{processId}:* dla izolacji między replikami
|
|
15
|
+
* - Multiplexing przez Map dla routingu odpowiedzi do promises
|
|
9
16
|
*/
|
|
10
17
|
export default class RpcCoordinator {
|
|
11
18
|
private readonly logger;
|
|
12
19
|
private readonly redisConnection;
|
|
20
|
+
private readonly compressionService;
|
|
13
21
|
/**
|
|
14
|
-
*
|
|
15
|
-
* Maksymalnie 20 subscribers w puli dla optymalizacji pamięci
|
|
22
|
+
* UUID procesu Node.js (współdzielony przez wszystkie instancje w procesie)
|
|
16
23
|
*/
|
|
17
|
-
private
|
|
24
|
+
private readonly processInstanceId;
|
|
18
25
|
/**
|
|
19
|
-
*
|
|
26
|
+
* Shared subscriber dla wszystkich RPC calls w tym procesie
|
|
20
27
|
*/
|
|
21
|
-
private
|
|
22
|
-
constructor(logger: ILogger, redisConnection: Redis);
|
|
28
|
+
private sharedSubscriber;
|
|
23
29
|
/**
|
|
24
|
-
*
|
|
25
|
-
* @returns Redis subscriber instance
|
|
30
|
+
* Mapa pending RPC calls - routing odpowiedzi do promises
|
|
26
31
|
*/
|
|
27
|
-
private
|
|
32
|
+
private pendingCalls;
|
|
28
33
|
/**
|
|
29
|
-
*
|
|
30
|
-
* @param subscriber - Subscriber do zwrócenia
|
|
34
|
+
* Czy subscriber jest gotowy (psubscribe zakończony)
|
|
31
35
|
*/
|
|
32
|
-
private
|
|
36
|
+
private isSubscriberReady;
|
|
37
|
+
/**
|
|
38
|
+
* Promise dla oczekiwania na gotowość subscribera
|
|
39
|
+
*/
|
|
40
|
+
private subscriberReadyPromise;
|
|
41
|
+
constructor(logger: ILogger, redisConnection: Redis, compressionService: PayloadCompressionService);
|
|
42
|
+
/**
|
|
43
|
+
* Konfiguruje shared subscriber dla wszystkich RPC calls
|
|
44
|
+
* Pattern subscribe: rpc:response:{processId}:* dla izolacji między procesami
|
|
45
|
+
* Multiplexing: pmessage handler routuje do odpowiednich pending calls
|
|
46
|
+
*/
|
|
47
|
+
private setupSharedSubscriber;
|
|
33
48
|
/**
|
|
34
49
|
* Przygotowuje komendę RPC z odpowiednimi metadanymi
|
|
35
50
|
* @param command - Komenda do wysłania
|
|
36
|
-
* @param responseChannel - Nazwa kanału Redis Pub/Sub dla odpowiedzi
|
|
51
|
+
* @param responseChannel - Nazwa kanału Redis Pub/Sub dla odpowiedzi (z processInstanceId)
|
|
37
52
|
* @returns Komenda z metadanymi RPC
|
|
38
53
|
*/
|
|
39
54
|
prepareRpcCommand<T extends Command>(command: T, responseChannel: string): T & {
|
|
40
55
|
__rpcMetadata: RpcMetadata;
|
|
41
56
|
};
|
|
42
57
|
/**
|
|
43
|
-
* Rejestruje nowe wywołanie RPC z timeout przez
|
|
44
|
-
*
|
|
45
|
-
*
|
|
58
|
+
* Rejestruje nowe wywołanie RPC z timeout przez shared subscriber
|
|
59
|
+
* Dodaje pending call do Map i zwraca promise
|
|
60
|
+
* Subscriber jest zawsze gotowy (subskrybuje przy konstrukcji) - zero race conditions
|
|
61
|
+
*
|
|
62
|
+
* Architektura: Shared subscriber + multiplexing
|
|
63
|
+
* - Brak race conditions (subscriber gotowy przed pierwszym call)
|
|
64
|
+
* - Jedno połączenie Redis per proces
|
|
65
|
+
* - Routing przez Map<correlationId, PendingCall>
|
|
46
66
|
*
|
|
47
67
|
* @param correlationId - Unikalny ID wywołania
|
|
48
68
|
* @param commandName - Nazwa komendy
|
|
@@ -51,18 +71,16 @@ export default class RpcCoordinator {
|
|
|
51
71
|
*/
|
|
52
72
|
registerCall<T>(correlationId: string, commandName: string, timeout: number): Promise<T>;
|
|
53
73
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* Fail-safe - nie rzuca błędów, tylko loguje
|
|
74
|
+
* Obsługuje wiadomość RPC z Redis Pub/Sub (pmessage handler)
|
|
75
|
+
* Ekstraktuje correlationId, znajduje pending call, dekompresuje i resolve/reject
|
|
57
76
|
*
|
|
58
|
-
* @param
|
|
59
|
-
* @param
|
|
60
|
-
* @param correlationId - ID wywołania (dla logowania)
|
|
77
|
+
* @param channel - Pełna nazwa kanału: rpc:response:{processId}:{correlationId}
|
|
78
|
+
* @param message - Skompresowana odpowiedź RPC (JSON)
|
|
61
79
|
*/
|
|
62
|
-
private
|
|
80
|
+
private handleRpcMessage;
|
|
63
81
|
/**
|
|
64
|
-
* Zamyka
|
|
65
|
-
*
|
|
82
|
+
* Zamyka RpcCoordinator i czyści zasoby
|
|
83
|
+
* Reject wszystkie pending calls i zamknij shared subscriber
|
|
66
84
|
*/
|
|
67
85
|
close(): Promise<void>;
|
|
68
86
|
}
|