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.
Files changed (205) hide show
  1. package/README.md +400 -1219
  2. package/dist/command-bus/command-bus.spec.js +138 -359
  3. package/dist/command-bus/command-bus.spec.js.map +1 -1
  4. package/dist/command-bus/command.d.ts +3 -4
  5. package/dist/command-bus/command.js +3 -32
  6. package/dist/command-bus/command.js.map +1 -1
  7. package/dist/command-bus/config/command-bus-config.d.ts +80 -21
  8. package/dist/command-bus/config/command-bus-config.js +104 -58
  9. package/dist/command-bus/config/command-bus-config.js.map +1 -1
  10. package/dist/command-bus/config/command-bus-config.spec.js +174 -100
  11. package/dist/command-bus/config/command-bus-config.spec.js.map +1 -1
  12. package/dist/command-bus/index.d.ts +41 -50
  13. package/dist/command-bus/index.js +143 -127
  14. package/dist/command-bus/index.js.map +1 -1
  15. package/dist/command-bus/interceptors/index.d.ts +5 -0
  16. package/dist/command-bus/interceptors/index.js +22 -0
  17. package/dist/command-bus/interceptors/index.js.map +1 -0
  18. package/dist/command-bus/interceptors/interceptor.interface.d.ts +35 -0
  19. package/dist/command-bus/interceptors/interceptor.interface.js +3 -0
  20. package/dist/command-bus/interceptors/interceptor.interface.js.map +1 -0
  21. package/dist/command-bus/interceptors/performance-interceptor.d.ts +24 -0
  22. package/dist/command-bus/interceptors/performance-interceptor.js +86 -0
  23. package/dist/command-bus/interceptors/performance-interceptor.js.map +1 -0
  24. package/dist/command-bus/interceptors/performance-interceptor.spec.js +124 -0
  25. package/dist/command-bus/interceptors/performance-interceptor.spec.js.map +1 -0
  26. package/dist/command-bus/logging/command-logger.d.ts +2 -0
  27. package/dist/command-bus/logging/command-logger.js +7 -0
  28. package/dist/command-bus/logging/command-logger.js.map +1 -1
  29. package/dist/command-bus/logging/command-logger.spec.js +36 -0
  30. package/dist/command-bus/logging/command-logger.spec.js.map +1 -1
  31. package/dist/command-bus/serialization/index.d.ts +6 -0
  32. package/dist/command-bus/serialization/index.js +9 -0
  33. package/dist/command-bus/serialization/index.js.map +1 -0
  34. package/dist/command-bus/serialization/msgpack-serializer.d.ts +26 -0
  35. package/dist/command-bus/serialization/msgpack-serializer.js +70 -0
  36. package/dist/command-bus/serialization/msgpack-serializer.js.map +1 -0
  37. package/dist/command-bus/serialization/msgpack-serializer.spec.js +223 -0
  38. package/dist/command-bus/serialization/msgpack-serializer.spec.js.map +1 -0
  39. package/dist/command-bus/serialization/serializer.interface.d.ts +21 -0
  40. package/dist/command-bus/serialization/serializer.interface.js +3 -0
  41. package/dist/command-bus/serialization/serializer.interface.js.map +1 -0
  42. package/dist/command-bus/transport/consumer-loop.d.ts +45 -0
  43. package/dist/command-bus/transport/consumer-loop.js +90 -0
  44. package/dist/command-bus/transport/consumer-loop.js.map +1 -0
  45. package/dist/command-bus/transport/consumer-loop.spec.js +216 -0
  46. package/dist/command-bus/transport/consumer-loop.spec.js.map +1 -0
  47. package/dist/command-bus/transport/index.d.ts +21 -0
  48. package/dist/command-bus/transport/index.js +23 -0
  49. package/dist/command-bus/transport/index.js.map +1 -0
  50. package/dist/command-bus/transport/message-processor.d.ts +70 -0
  51. package/dist/command-bus/transport/message-processor.js +158 -0
  52. package/dist/command-bus/transport/message-processor.js.map +1 -0
  53. package/dist/command-bus/transport/message-processor.spec.js +185 -0
  54. package/dist/command-bus/transport/message-processor.spec.js.map +1 -0
  55. package/dist/command-bus/transport/pending-recovery.d.ts +54 -0
  56. package/dist/command-bus/transport/pending-recovery.js +139 -0
  57. package/dist/command-bus/transport/pending-recovery.js.map +1 -0
  58. package/dist/command-bus/transport/pending-recovery.spec.js +176 -0
  59. package/dist/command-bus/transport/pending-recovery.spec.js.map +1 -0
  60. package/dist/command-bus/transport/redis-codec.d.ts +24 -0
  61. package/dist/command-bus/transport/redis-codec.js +33 -0
  62. package/dist/command-bus/transport/redis-codec.js.map +1 -0
  63. package/dist/command-bus/transport/redis-codec.spec.js +53 -0
  64. package/dist/command-bus/transport/redis-codec.spec.js.map +1 -0
  65. package/dist/command-bus/transport/redis-streams-transport.d.ts +94 -0
  66. package/dist/command-bus/transport/redis-streams-transport.js +143 -0
  67. package/dist/command-bus/transport/redis-streams-transport.js.map +1 -0
  68. package/dist/command-bus/transport/redis-streams-transport.spec.js +420 -0
  69. package/dist/command-bus/transport/redis-streams-transport.spec.js.map +1 -0
  70. package/dist/command-bus/transport/rpc-handler.d.ts +39 -0
  71. package/dist/command-bus/transport/rpc-handler.js +87 -0
  72. package/dist/command-bus/transport/rpc-handler.js.map +1 -0
  73. package/dist/command-bus/transport/rpc-handler.spec.js +157 -0
  74. package/dist/command-bus/transport/rpc-handler.spec.js.map +1 -0
  75. package/dist/command-bus/transport/stream-consumer.d.ts +91 -0
  76. package/dist/command-bus/transport/stream-consumer.js +182 -0
  77. package/dist/command-bus/transport/stream-consumer.js.map +1 -0
  78. package/dist/command-bus/transport/stream-consumer.spec.js +284 -0
  79. package/dist/command-bus/transport/stream-consumer.spec.js.map +1 -0
  80. package/dist/command-bus/transport/stream-producer.d.ts +23 -0
  81. package/dist/command-bus/transport/stream-producer.js +70 -0
  82. package/dist/command-bus/transport/stream-producer.js.map +1 -0
  83. package/dist/command-bus/transport/stream-producer.spec.js +125 -0
  84. package/dist/command-bus/transport/stream-producer.spec.js.map +1 -0
  85. package/dist/command-bus/transport/transport.interface.d.ts +87 -0
  86. package/dist/command-bus/transport/transport.interface.js +3 -0
  87. package/dist/command-bus/transport/transport.interface.js.map +1 -0
  88. package/dist/command-bus/types/index.d.ts +0 -84
  89. package/dist/examples/rpc.demo.js +1 -1
  90. package/dist/examples/rpc.demo.js.map +1 -1
  91. package/dist/index.d.ts +8 -5
  92. package/dist/index.js +6 -4
  93. package/dist/index.js.map +1 -1
  94. package/dist/pp-command-bus-2.0.1.tgz +0 -0
  95. package/dist/shared/redis/connection-pool.d.ts +54 -0
  96. package/dist/shared/redis/connection-pool.js +123 -0
  97. package/dist/shared/redis/connection-pool.js.map +1 -0
  98. package/dist/shared/redis/connection-pool.spec.d.ts +1 -0
  99. package/dist/shared/redis/connection-pool.spec.js +114 -0
  100. package/dist/shared/redis/connection-pool.spec.js.map +1 -0
  101. package/dist/shared/redis/index.d.ts +5 -3
  102. package/dist/shared/redis/index.js +6 -4
  103. package/dist/shared/redis/index.js.map +1 -1
  104. package/dist/shared/redis/rpc-connection-pool.d.ts +61 -0
  105. package/dist/shared/redis/rpc-connection-pool.js +154 -0
  106. package/dist/shared/redis/rpc-connection-pool.js.map +1 -0
  107. package/dist/shared/redis/rpc-connection-pool.spec.d.ts +1 -0
  108. package/dist/shared/redis/rpc-connection-pool.spec.js +173 -0
  109. package/dist/shared/redis/rpc-connection-pool.spec.js.map +1 -0
  110. package/dist/shared/types.d.ts +0 -4
  111. package/dist/shared/utils/error-utils.d.ts +8 -0
  112. package/dist/shared/utils/error-utils.js +14 -0
  113. package/dist/shared/utils/error-utils.js.map +1 -0
  114. package/package.json +12 -12
  115. package/dist/command-bus/config/auto-config-optimizer.d.ts +0 -35
  116. package/dist/command-bus/config/auto-config-optimizer.js +0 -52
  117. package/dist/command-bus/config/auto-config-optimizer.js.map +0 -1
  118. package/dist/command-bus/config/auto-config-optimizer.spec.js +0 -42
  119. package/dist/command-bus/config/auto-config-optimizer.spec.js.map +0 -1
  120. package/dist/command-bus/job/index.d.ts +0 -6
  121. package/dist/command-bus/job/index.js +0 -15
  122. package/dist/command-bus/job/index.js.map +0 -1
  123. package/dist/command-bus/job/job-options-builder.d.ts +0 -21
  124. package/dist/command-bus/job/job-options-builder.js +0 -58
  125. package/dist/command-bus/job/job-options-builder.js.map +0 -1
  126. package/dist/command-bus/job/job-options-builder.spec.js +0 -156
  127. package/dist/command-bus/job/job-options-builder.spec.js.map +0 -1
  128. package/dist/command-bus/job/job-processor.d.ts +0 -39
  129. package/dist/command-bus/job/job-processor.js +0 -203
  130. package/dist/command-bus/job/job-processor.js.map +0 -1
  131. package/dist/command-bus/job/job-processor.spec.js +0 -436
  132. package/dist/command-bus/job/job-processor.spec.js.map +0 -1
  133. package/dist/command-bus/queue/index.d.ts +0 -5
  134. package/dist/command-bus/queue/index.js +0 -13
  135. package/dist/command-bus/queue/index.js.map +0 -1
  136. package/dist/command-bus/queue/queue-manager.d.ts +0 -56
  137. package/dist/command-bus/queue/queue-manager.js +0 -163
  138. package/dist/command-bus/queue/queue-manager.js.map +0 -1
  139. package/dist/command-bus/queue/queue-manager.spec.js +0 -371
  140. package/dist/command-bus/queue/queue-manager.spec.js.map +0 -1
  141. package/dist/command-bus/rpc/index.d.ts +0 -11
  142. package/dist/command-bus/rpc/index.js +0 -19
  143. package/dist/command-bus/rpc/index.js.map +0 -1
  144. package/dist/command-bus/rpc/payload-compression.service.d.ts +0 -50
  145. package/dist/command-bus/rpc/payload-compression.service.js +0 -215
  146. package/dist/command-bus/rpc/payload-compression.service.js.map +0 -1
  147. package/dist/command-bus/rpc/payload-compression.service.spec.js +0 -376
  148. package/dist/command-bus/rpc/payload-compression.service.spec.js.map +0 -1
  149. package/dist/command-bus/rpc/rpc-coordinator.d.ts +0 -96
  150. package/dist/command-bus/rpc/rpc-coordinator.js +0 -500
  151. package/dist/command-bus/rpc/rpc-coordinator.js.map +0 -1
  152. package/dist/command-bus/rpc/rpc-coordinator.spec.js +0 -621
  153. package/dist/command-bus/rpc/rpc-coordinator.spec.js.map +0 -1
  154. package/dist/command-bus/rpc/rpc-job-cancellation.service.d.ts +0 -82
  155. package/dist/command-bus/rpc/rpc-job-cancellation.service.js +0 -180
  156. package/dist/command-bus/rpc/rpc-job-cancellation.service.js.map +0 -1
  157. package/dist/command-bus/rpc/rpc-job-cancellation.service.spec.js +0 -286
  158. package/dist/command-bus/rpc/rpc-job-cancellation.service.spec.js.map +0 -1
  159. package/dist/command-bus/worker/index.d.ts +0 -10
  160. package/dist/command-bus/worker/index.js +0 -19
  161. package/dist/command-bus/worker/index.js.map +0 -1
  162. package/dist/command-bus/worker/worker-benchmark.d.ts +0 -71
  163. package/dist/command-bus/worker/worker-benchmark.js +0 -202
  164. package/dist/command-bus/worker/worker-benchmark.js.map +0 -1
  165. package/dist/command-bus/worker/worker-benchmark.spec.js +0 -310
  166. package/dist/command-bus/worker/worker-benchmark.spec.js.map +0 -1
  167. package/dist/command-bus/worker/worker-metrics-collector.d.ts +0 -98
  168. package/dist/command-bus/worker/worker-metrics-collector.js +0 -242
  169. package/dist/command-bus/worker/worker-metrics-collector.js.map +0 -1
  170. package/dist/command-bus/worker/worker-orchestrator.d.ts +0 -70
  171. package/dist/command-bus/worker/worker-orchestrator.js +0 -339
  172. package/dist/command-bus/worker/worker-orchestrator.js.map +0 -1
  173. package/dist/command-bus/worker/worker-orchestrator.spec.js +0 -712
  174. package/dist/command-bus/worker/worker-orchestrator.spec.js.map +0 -1
  175. package/dist/examples/auto-config.demo.d.ts +0 -9
  176. package/dist/examples/auto-config.demo.js +0 -106
  177. package/dist/examples/auto-config.demo.js.map +0 -1
  178. package/dist/examples/rpc-compression.demo.d.ts +0 -5
  179. package/dist/examples/rpc-compression.demo.js +0 -358
  180. package/dist/examples/rpc-compression.demo.js.map +0 -1
  181. package/dist/examples/rpc-resilience.demo.d.ts +0 -15
  182. package/dist/examples/rpc-resilience.demo.js +0 -233
  183. package/dist/examples/rpc-resilience.demo.js.map +0 -1
  184. package/dist/pp-command-bus-1.5.0.tgz +0 -0
  185. package/dist/shared/config/base-config.d.ts +0 -54
  186. package/dist/shared/config/base-config.js +0 -114
  187. package/dist/shared/config/base-config.js.map +0 -1
  188. package/dist/shared/config/base-config.spec.js +0 -204
  189. package/dist/shared/config/base-config.spec.js.map +0 -1
  190. package/dist/shared/config/index.d.ts +0 -1
  191. package/dist/shared/config/index.js +0 -9
  192. package/dist/shared/config/index.js.map +0 -1
  193. package/dist/shared/redis/redis-connection-factory.d.ts +0 -66
  194. package/dist/shared/redis/redis-connection-factory.js +0 -113
  195. package/dist/shared/redis/redis-connection-factory.js.map +0 -1
  196. /package/dist/command-bus/{config/auto-config-optimizer.spec.d.ts → interceptors/performance-interceptor.spec.d.ts} +0 -0
  197. /package/dist/command-bus/{job/job-options-builder.spec.d.ts → serialization/msgpack-serializer.spec.d.ts} +0 -0
  198. /package/dist/command-bus/{job/job-processor.spec.d.ts → transport/consumer-loop.spec.d.ts} +0 -0
  199. /package/dist/command-bus/{queue/queue-manager.spec.d.ts → transport/message-processor.spec.d.ts} +0 -0
  200. /package/dist/command-bus/{rpc/payload-compression.service.spec.d.ts → transport/pending-recovery.spec.d.ts} +0 -0
  201. /package/dist/command-bus/{rpc/rpc-coordinator.spec.d.ts → transport/redis-codec.spec.d.ts} +0 -0
  202. /package/dist/command-bus/{rpc/rpc-job-cancellation.service.spec.d.ts → transport/redis-streams-transport.spec.d.ts} +0 -0
  203. /package/dist/command-bus/{worker/worker-benchmark.spec.d.ts → transport/rpc-handler.spec.d.ts} +0 -0
  204. /package/dist/command-bus/{worker/worker-orchestrator.spec.d.ts → transport/stream-consumer.spec.d.ts} +0 -0
  205. /package/dist/{shared/config/base-config.spec.d.ts → command-bus/transport/stream-producer.spec.d.ts} +0 -0
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Interfejs serializera dla CommandBus
3
+ * Odpowiada za konwersję danych do/z formatu binarnego (Buffer)
4
+ *
5
+ * Implementacje powinny obsługiwać natywne typy JS (Date, Buffer, nested objects)
6
+ * bez konieczności dodatkowej rekonstrukcji typów po deserializacji
7
+ */
8
+ export interface ISerializer {
9
+ /**
10
+ * Serializuje dane do formatu binarnego
11
+ * @param data - Dane do serializacji
12
+ * @returns Buffer z serializowanymi danymi
13
+ */
14
+ serialize(data: unknown): Buffer;
15
+ /**
16
+ * Deserializuje dane z formatu binarnego
17
+ * @param buffer - Buffer z serializowanymi danymi
18
+ * @returns Zdeserializowane dane
19
+ */
20
+ deserialize<T>(buffer: Buffer): T;
21
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=serializer.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serializer.interface.js","sourceRoot":"","sources":["../../../src/command-bus/serialization/serializer.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,45 @@
1
+ import type { Redis } from 'ioredis';
2
+ import type { ILogger } from '../../shared/types';
3
+ /**
4
+ * Callback wywoływany dla każdej wiadomości odczytanej ze strumienia
5
+ */
6
+ export type MessageCallback = (messageId: string, fields: string[]) => Promise<void>;
7
+ /**
8
+ * Konfiguracja ConsumerLoop
9
+ */
10
+ export interface ConsumerLoopOptions {
11
+ consumerId: string;
12
+ batchSize: number;
13
+ concurrency: number;
14
+ logger: ILogger;
15
+ }
16
+ /**
17
+ * Consumer loop — czyta wiadomości z Redis Streams i przekazuje do callbacka
18
+ *
19
+ * Odpowiedzialności:
20
+ * - while(running) loop z XREADGROUP BLOCK
21
+ * - Concurrency limiter (Promise.race + active Set)
22
+ * - Exponential backoff z jitter przy błędach
23
+ * - Czekanie na aktywne zadania przy shutdown
24
+ *
25
+ * NIE odpowiada za przetwarzanie wiadomości — to odpowiedzialność koordynatora/procesora
26
+ */
27
+ export declare class ConsumerLoop {
28
+ private readonly consumerId;
29
+ private readonly batchSize;
30
+ private readonly concurrency;
31
+ private readonly logger;
32
+ /** Flaga zatrzymania consumer loop */
33
+ running: boolean;
34
+ constructor(options: ConsumerLoopOptions);
35
+ /**
36
+ * Uruchamia consumer loop — czyta wiadomości z strumienia i przetwarza
37
+ * Concurrency limiter: przetwarza N wiadomości równolegle, czyta gdy wolne sloty
38
+ *
39
+ * @param conn - Dedykowane połączenie Redis (XREADGROUP BLOCK blokuje socket)
40
+ * @param streamName - Nazwa strumienia Redis
41
+ * @param groupName - Nazwa grupy konsumentów
42
+ * @param onMessage - Callback wywoływany dla każdej wiadomości
43
+ */
44
+ run(conn: Redis, streamName: string, groupName: string, onMessage: MessageCallback): Promise<void>;
45
+ }
@@ -0,0 +1,90 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.ConsumerLoop = void 0;
13
+ const error_utils_1 = require("../../shared/utils/error-utils");
14
+ /**
15
+ * Consumer loop — czyta wiadomości z Redis Streams i przekazuje do callbacka
16
+ *
17
+ * Odpowiedzialności:
18
+ * - while(running) loop z XREADGROUP BLOCK
19
+ * - Concurrency limiter (Promise.race + active Set)
20
+ * - Exponential backoff z jitter przy błędach
21
+ * - Czekanie na aktywne zadania przy shutdown
22
+ *
23
+ * NIE odpowiada za przetwarzanie wiadomości — to odpowiedzialność koordynatora/procesora
24
+ */
25
+ class ConsumerLoop {
26
+ constructor(options) {
27
+ /** Flaga zatrzymania consumer loop */
28
+ this.running = true;
29
+ this.consumerId = options.consumerId;
30
+ this.batchSize = options.batchSize;
31
+ this.concurrency = options.concurrency;
32
+ this.logger = options.logger;
33
+ }
34
+ /**
35
+ * Uruchamia consumer loop — czyta wiadomości z strumienia i przetwarza
36
+ * Concurrency limiter: przetwarza N wiadomości równolegle, czyta gdy wolne sloty
37
+ *
38
+ * @param conn - Dedykowane połączenie Redis (XREADGROUP BLOCK blokuje socket)
39
+ * @param streamName - Nazwa strumienia Redis
40
+ * @param groupName - Nazwa grupy konsumentów
41
+ * @param onMessage - Callback wywoływany dla każdej wiadomości
42
+ */
43
+ run(conn, streamName, groupName, onMessage) {
44
+ return __awaiter(this, void 0, void 0, function* () {
45
+ const active = new Set();
46
+ let consecutiveErrors = 0;
47
+ while (this.running) {
48
+ try {
49
+ while (active.size >= this.concurrency && this.running) {
50
+ yield Promise.race(active);
51
+ }
52
+ if (!this.running)
53
+ break;
54
+ const availableSlots = this.concurrency - active.size;
55
+ const count = Math.min(this.batchSize, availableSlots);
56
+ const result = yield conn.xreadgroup('GROUP', groupName, this.consumerId, 'COUNT', count, 'BLOCK', 5000, 'STREAMS', streamName, '>');
57
+ consecutiveErrors = 0;
58
+ if (!result)
59
+ continue;
60
+ const messages = result;
61
+ for (const [, streamMessages] of messages) {
62
+ for (const [messageId, fields] of streamMessages) {
63
+ const processing = onMessage(messageId, fields);
64
+ active.add(processing);
65
+ void processing.finally(() => active.delete(processing));
66
+ }
67
+ }
68
+ }
69
+ catch (error) {
70
+ if (!this.running)
71
+ break;
72
+ consecutiveErrors++;
73
+ this.logger.error('Błąd w consumer loop', {
74
+ streamName,
75
+ error: (0, error_utils_1.getErrorMessage)(error),
76
+ consecutiveErrors,
77
+ timestamp: new Date().toISOString(),
78
+ });
79
+ const backoff = Math.min(1000 * Math.pow(2, consecutiveErrors - 1), 30000) + Math.random() * 1000;
80
+ yield new Promise((r) => setTimeout(r, backoff));
81
+ }
82
+ }
83
+ if (active.size > 0) {
84
+ yield Promise.allSettled(active);
85
+ }
86
+ });
87
+ }
88
+ }
89
+ exports.ConsumerLoop = ConsumerLoop;
90
+ //# sourceMappingURL=consumer-loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consumer-loop.js","sourceRoot":"","sources":["../../../src/command-bus/transport/consumer-loop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,216 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const consumer_loop_1 = require("./consumer-loop");
13
+ /**
14
+ * Mock helpers
15
+ */
16
+ function createMockLogger() {
17
+ return {
18
+ log: jest.fn(),
19
+ error: jest.fn(),
20
+ warn: jest.fn(),
21
+ debug: jest.fn(),
22
+ };
23
+ }
24
+ /**
25
+ * Tworzy mock Redis connection z disconnect() który przerywa blocking operations
26
+ */
27
+ function createMockConnection() {
28
+ const pendingRejects = [];
29
+ return {
30
+ xreadgroup: jest.fn().mockImplementation(() => new Promise((_resolve, reject) => {
31
+ pendingRejects.push(reject);
32
+ })),
33
+ disconnect: jest.fn().mockImplementation(() => {
34
+ const disconnectError = new Error('Connection is closed.');
35
+ while (pendingRejects.length > 0) {
36
+ const reject = pendingRejects.shift();
37
+ if (reject)
38
+ reject(disconnectError);
39
+ }
40
+ }),
41
+ _pendingRejects: pendingRejects,
42
+ };
43
+ }
44
+ describe('ConsumerLoop', () => {
45
+ let loop;
46
+ let logger;
47
+ beforeEach(() => {
48
+ jest.clearAllMocks();
49
+ logger = createMockLogger();
50
+ loop = new consumer_loop_1.ConsumerLoop({
51
+ consumerId: 'test-consumer',
52
+ batchSize: 10,
53
+ concurrency: 5,
54
+ logger,
55
+ });
56
+ });
57
+ afterEach(() => {
58
+ loop.running = false;
59
+ });
60
+ describe('run()', () => {
61
+ it('powinien wywołać XREADGROUP z prawidłowymi parametrami', () => __awaiter(void 0, void 0, void 0, function* () {
62
+ const conn = createMockConnection();
63
+ const onMessage = jest.fn().mockResolvedValue(undefined);
64
+ // XREADGROUP zwraca jedną wiadomość, potem blocking
65
+ conn.xreadgroup.mockResolvedValueOnce([['cmd:Test', [['msg-1', ['data', 'payload']]]]]);
66
+ const runPromise = loop.run(conn, 'cmd:Test', 'workers', onMessage);
67
+ // Poczekaj na przetworzenie pierwszej wiadomości
68
+ yield new Promise((r) => setTimeout(r, 10));
69
+ // Zatrzymaj loop
70
+ loop.running = false;
71
+ conn.disconnect();
72
+ yield runPromise;
73
+ expect(conn.xreadgroup).toHaveBeenCalledWith('GROUP', 'workers', 'test-consumer', 'COUNT', expect.any(Number), 'BLOCK', 5000, 'STREAMS', 'cmd:Test', '>');
74
+ }));
75
+ it('powinien wywołać onMessage dla każdej wiadomości', () => __awaiter(void 0, void 0, void 0, function* () {
76
+ const conn = createMockConnection();
77
+ const onMessage = jest.fn().mockResolvedValue(undefined);
78
+ conn.xreadgroup.mockResolvedValueOnce([
79
+ [
80
+ 'cmd:Test',
81
+ [
82
+ ['msg-1', ['data', 'payload1']],
83
+ ['msg-2', ['data', 'payload2']],
84
+ ],
85
+ ],
86
+ ]);
87
+ const runPromise = loop.run(conn, 'cmd:Test', 'workers', onMessage);
88
+ yield new Promise((r) => setTimeout(r, 10));
89
+ loop.running = false;
90
+ conn.disconnect();
91
+ yield runPromise;
92
+ expect(onMessage).toHaveBeenCalledTimes(2);
93
+ expect(onMessage).toHaveBeenCalledWith('msg-1', ['data', 'payload1']);
94
+ expect(onMessage).toHaveBeenCalledWith('msg-2', ['data', 'payload2']);
95
+ }));
96
+ it('powinien zakończyć gracefully gdy running = false', () => __awaiter(void 0, void 0, void 0, function* () {
97
+ const conn = createMockConnection();
98
+ const onMessage = jest.fn().mockResolvedValue(undefined);
99
+ loop.running = false;
100
+ const runPromise = loop.run(conn, 'cmd:Test', 'workers', onMessage);
101
+ yield runPromise;
102
+ expect(onMessage).not.toHaveBeenCalled();
103
+ }));
104
+ it('powinien czekać na aktywne zadania przy shutdown', () => __awaiter(void 0, void 0, void 0, function* () {
105
+ const conn = createMockConnection();
106
+ let handlerResolve;
107
+ const handlerPromise = new Promise((resolve) => {
108
+ handlerResolve = resolve;
109
+ });
110
+ const onMessage = jest.fn().mockReturnValueOnce(handlerPromise);
111
+ conn.xreadgroup.mockResolvedValueOnce([['cmd:Test', [['msg-1', ['data', 'payload']]]]]);
112
+ const runPromise = loop.run(conn, 'cmd:Test', 'workers', onMessage);
113
+ // Poczekaj na start przetwarzania
114
+ yield new Promise((r) => setTimeout(r, 10));
115
+ // Zatrzymaj loop (ale handler jeszcze pracuje)
116
+ loop.running = false;
117
+ conn.disconnect();
118
+ // Handler jeszcze nie zakończony — run() powinno czekać
119
+ const raceResult = yield Promise.race([
120
+ runPromise.then(() => 'finished'),
121
+ new Promise((r) => setTimeout(r, 50)).then(() => 'timeout'),
122
+ ]);
123
+ expect(raceResult).toBe('timeout');
124
+ // Zakończ handler
125
+ handlerResolve();
126
+ yield runPromise;
127
+ }));
128
+ it('powinien zalogować błąd i kontynuować po błędzie XREADGROUP', () => __awaiter(void 0, void 0, void 0, function* () {
129
+ jest.useFakeTimers();
130
+ const conn = createMockConnection();
131
+ const onMessage = jest.fn().mockResolvedValue(undefined);
132
+ // Pierwszy call — error, drugi — null (timeout), trzeci — zatrzymujemy
133
+ conn.xreadgroup.mockRejectedValueOnce(new Error('Redis error')).mockResolvedValueOnce(null);
134
+ const runPromise = loop.run(conn, 'cmd:Test', 'workers', onMessage);
135
+ // Advance timer past backoff
136
+ yield jest.advanceTimersByTimeAsync(2000);
137
+ // Zatrzymaj loop
138
+ loop.running = false;
139
+ conn.disconnect();
140
+ yield jest.advanceTimersByTimeAsync(1000);
141
+ yield runPromise;
142
+ expect(logger.error).toHaveBeenCalledWith('Błąd w consumer loop', expect.objectContaining({
143
+ error: 'Redis error',
144
+ consecutiveErrors: 1,
145
+ }));
146
+ jest.useRealTimers();
147
+ }));
148
+ it('powinien stosować exponential backoff przy kolejnych błędach', () => __awaiter(void 0, void 0, void 0, function* () {
149
+ jest.useFakeTimers();
150
+ const conn = createMockConnection();
151
+ const onMessage = jest.fn().mockResolvedValue(undefined);
152
+ // 3 kolejne błędy
153
+ conn.xreadgroup
154
+ .mockRejectedValueOnce(new Error('error 1'))
155
+ .mockRejectedValueOnce(new Error('error 2'))
156
+ .mockRejectedValueOnce(new Error('error 3'));
157
+ const runPromise = loop.run(conn, 'cmd:Test', 'workers', onMessage);
158
+ // Advance past first backoff (~1s + jitter)
159
+ yield jest.advanceTimersByTimeAsync(2500);
160
+ // Advance past second backoff (~2s + jitter)
161
+ yield jest.advanceTimersByTimeAsync(3500);
162
+ // Advance past third backoff (~4s + jitter)
163
+ yield jest.advanceTimersByTimeAsync(5500);
164
+ loop.running = false;
165
+ conn.disconnect();
166
+ yield jest.advanceTimersByTimeAsync(1000);
167
+ yield runPromise;
168
+ expect(logger.error).toHaveBeenCalledTimes(3);
169
+ jest.useRealTimers();
170
+ }));
171
+ it('powinien zakończyć od razu przy błędzie gdy running = false', () => __awaiter(void 0, void 0, void 0, function* () {
172
+ const conn = createMockConnection();
173
+ const onMessage = jest.fn().mockResolvedValue(undefined);
174
+ // Symuluj disconnect error
175
+ conn.xreadgroup.mockRejectedValueOnce(new Error('Connection is closed.'));
176
+ loop.running = false;
177
+ const runPromise = loop.run(conn, 'cmd:Test', 'workers', onMessage);
178
+ yield runPromise;
179
+ // Nie powinien logować błędu (running = false = graceful shutdown)
180
+ expect(logger.error).not.toHaveBeenCalled();
181
+ }));
182
+ it('powinien limitować concurrency do skonfigurowanego limitu', () => __awaiter(void 0, void 0, void 0, function* () {
183
+ const smallLoop = new consumer_loop_1.ConsumerLoop({
184
+ consumerId: 'test-consumer',
185
+ batchSize: 10,
186
+ concurrency: 2,
187
+ logger,
188
+ });
189
+ const conn = createMockConnection();
190
+ const handlerResolves = [];
191
+ const onMessage = jest.fn().mockImplementation(() => new Promise((resolve) => {
192
+ handlerResolves.push(resolve);
193
+ }));
194
+ // Zwróć 5 wiadomości naraz
195
+ conn.xreadgroup.mockResolvedValueOnce([
196
+ [
197
+ 'cmd:Test',
198
+ [
199
+ ['msg-1', ['data', 'p1']],
200
+ ['msg-2', ['data', 'p2']],
201
+ ],
202
+ ],
203
+ ]);
204
+ const runPromise = smallLoop.run(conn, 'cmd:Test', 'workers', onMessage);
205
+ yield new Promise((r) => setTimeout(r, 20));
206
+ // Callback powinien być wywołany 2 razy (concurrency = 2)
207
+ expect(onMessage).toHaveBeenCalledTimes(2);
208
+ // Cleanup
209
+ handlerResolves.forEach((r) => r());
210
+ smallLoop.running = false;
211
+ conn.disconnect();
212
+ yield runPromise;
213
+ }));
214
+ });
215
+ });
216
+ //# sourceMappingURL=consumer-loop.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consumer-loop.spec.js","sourceRoot":"","sources":["../../../src/command-bus/transport/consumer-loop.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Moduł transportu dla CommandBus
3
+ *
4
+ * Eksportuje interfejsy segregowane (ISP) i fasadę RedisStreamsTransport
5
+ * oraz poszczególne komponenty dla zaawansowanego użycia
6
+ */
7
+ export type { ITransport, IStreamProducer, IStreamConsumer, IRpcTransport, IClosable, ConsumerHandler, RpcMessageMetadata, } from './transport.interface';
8
+ export { default as RedisStreamsTransport } from './redis-streams-transport';
9
+ export type { RedisStreamsTransportOptions } from './redis-streams-transport';
10
+ export { RedisCodec } from './redis-codec';
11
+ export { StreamProducer } from './stream-producer';
12
+ export { StreamConsumer } from './stream-consumer';
13
+ export type { StreamConsumerOptions } from './stream-consumer';
14
+ export { MessageProcessor } from './message-processor';
15
+ export type { MessageProcessorOptions, RpcResponder } from './message-processor';
16
+ export { ConsumerLoop } from './consumer-loop';
17
+ export type { ConsumerLoopOptions, MessageCallback } from './consumer-loop';
18
+ export { RpcHandler } from './rpc-handler';
19
+ export type { RpcEnvelope } from './rpc-handler';
20
+ export { PendingRecovery } from './pending-recovery';
21
+ export type { PendingRecoveryOptions } from './pending-recovery';
@@ -0,0 +1,23 @@
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.PendingRecovery = exports.RpcHandler = exports.ConsumerLoop = exports.MessageProcessor = exports.StreamConsumer = exports.StreamProducer = exports.RedisCodec = exports.RedisStreamsTransport = void 0;
7
+ var redis_streams_transport_1 = require("./redis-streams-transport");
8
+ Object.defineProperty(exports, "RedisStreamsTransport", { enumerable: true, get: function () { return __importDefault(redis_streams_transport_1).default; } });
9
+ var redis_codec_1 = require("./redis-codec");
10
+ Object.defineProperty(exports, "RedisCodec", { enumerable: true, get: function () { return redis_codec_1.RedisCodec; } });
11
+ var stream_producer_1 = require("./stream-producer");
12
+ Object.defineProperty(exports, "StreamProducer", { enumerable: true, get: function () { return stream_producer_1.StreamProducer; } });
13
+ var stream_consumer_1 = require("./stream-consumer");
14
+ Object.defineProperty(exports, "StreamConsumer", { enumerable: true, get: function () { return stream_consumer_1.StreamConsumer; } });
15
+ var message_processor_1 = require("./message-processor");
16
+ Object.defineProperty(exports, "MessageProcessor", { enumerable: true, get: function () { return message_processor_1.MessageProcessor; } });
17
+ var consumer_loop_1 = require("./consumer-loop");
18
+ Object.defineProperty(exports, "ConsumerLoop", { enumerable: true, get: function () { return consumer_loop_1.ConsumerLoop; } });
19
+ var rpc_handler_1 = require("./rpc-handler");
20
+ Object.defineProperty(exports, "RpcHandler", { enumerable: true, get: function () { return rpc_handler_1.RpcHandler; } });
21
+ var pending_recovery_1 = require("./pending-recovery");
22
+ Object.defineProperty(exports, "PendingRecovery", { enumerable: true, get: function () { return pending_recovery_1.PendingRecovery; } });
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/command-bus/transport/index.ts"],"names":[],"mappings":";;;;;;AAeA,qEAA6E;AAApE,iJAAA,OAAO,OAAyB;AAEzC,6CAA2C;AAAlC,yGAAA,UAAU,OAAA;AACnB,qDAAmD;AAA1C,iHAAA,cAAc,OAAA;AACvB,qDAAmD;AAA1C,iHAAA,cAAc,OAAA;AAEvB,yDAAuD;AAA9C,qHAAA,gBAAgB,OAAA;AAEzB,iDAA+C;AAAtC,6GAAA,YAAY,OAAA;AAErB,6CAA2C;AAAlC,yGAAA,UAAU,OAAA;AAEnB,uDAAqD;AAA5C,mHAAA,eAAe,OAAA"}
@@ -0,0 +1,70 @@
1
+ import type { ILogger } from '../../shared/types';
2
+ import type { ISerializer } from '../serialization/serializer.interface';
3
+ import type { ConsumerHandler } from './transport.interface';
4
+ import type RedisConnectionPool from '../../shared/redis/connection-pool';
5
+ import type { ICommandInterceptor } from '../interceptors';
6
+ /**
7
+ * Typ callbacka do wysyłania odpowiedzi RPC
8
+ */
9
+ export type RpcResponder = (responseKey: string, data: Buffer, ttl: number) => Promise<void>;
10
+ /**
11
+ * Konfiguracja MessageProcessor
12
+ */
13
+ export interface MessageProcessorOptions {
14
+ pool: RedisConnectionPool;
15
+ serializer: ISerializer;
16
+ logger: ILogger;
17
+ batchSize: number;
18
+ maxRetained: number;
19
+ rpcRespond: RpcResponder;
20
+ interceptor?: ICommandInterceptor;
21
+ }
22
+ /**
23
+ * Procesor wiadomości — parsuje, waliduje, przetwarza i potwierdza wiadomości
24
+ *
25
+ * Odpowiedzialności:
26
+ * - Parsowanie fields → fieldMap
27
+ * - Walidacja danych wejściowych (H4)
28
+ * - Detekcja RPC via marker field
29
+ * - Wywołanie handlera
30
+ * - XACK + throttled XTRIM (H2: per-stream counters)
31
+ * - Wysyłanie odpowiedzi RPC
32
+ *
33
+ * NIE odpowiada za deduplicację — to odpowiedzialność koordynatora (StreamConsumer)
34
+ */
35
+ export declare class MessageProcessor {
36
+ private readonly pool;
37
+ private readonly serializer;
38
+ private readonly logger;
39
+ private readonly batchSize;
40
+ private readonly maxRetained;
41
+ private readonly rpcRespond;
42
+ private readonly interceptor?;
43
+ /** H2: Liczniki wiadomości od ostatniego XTRIM — per strumień */
44
+ private readonly xtrimCounters;
45
+ constructor(options: MessageProcessorOptions);
46
+ /**
47
+ * Czyści stan counters — wywoływane przy close()
48
+ */
49
+ reset(): void;
50
+ /**
51
+ * Przetwarza wiadomość — parsuje fields, wykrywa RPC, wywołuje handler, XACK/XTRIM
52
+ *
53
+ * Błędy propagują do callera (koordynatora) — nie łapie wewnętrznie
54
+ *
55
+ * @param streamName - Nazwa strumienia Redis
56
+ * @param groupName - Nazwa grupy konsumentów
57
+ * @param messageId - ID wiadomości
58
+ * @param fields - Tablica pól ze strumienia [key, value, key, value, ...]
59
+ * @param handler - Handler przetwarzający dane komendy
60
+ */
61
+ process(streamName: string, groupName: string, messageId: string, fields: string[], handler: ConsumerHandler): Promise<void>;
62
+ /**
63
+ * Ekstrakcja commandId z commandData (deserializacja metadata)
64
+ */
65
+ private extractCommandId;
66
+ /**
67
+ * Ekstrakcja nazwy komendy ze streamName (usunięcie prefiksu 'cmd:')
68
+ */
69
+ private extractCommandName;
70
+ }