pp-command-bus 1.4.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.
Files changed (195) hide show
  1. package/README.md +402 -1113
  2. package/dist/command-bus/command-bus.spec.js +144 -370
  3. package/dist/command-bus/command-bus.spec.js.map +1 -1
  4. package/dist/command-bus/command.d.ts +23 -5
  5. package/dist/command-bus/command.js +20 -34
  6. package/dist/command-bus/command.js.map +1 -1
  7. package/dist/command-bus/config/command-bus-config.d.ts +75 -21
  8. package/dist/command-bus/config/command-bus-config.js +99 -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 +39 -52
  13. package/dist/command-bus/index.js +133 -126
  14. package/dist/command-bus/index.js.map +1 -1
  15. package/dist/command-bus/logging/command-logger.d.ts +2 -0
  16. package/dist/command-bus/logging/command-logger.js +7 -0
  17. package/dist/command-bus/logging/command-logger.js.map +1 -1
  18. package/dist/command-bus/logging/command-logger.spec.js +49 -14
  19. package/dist/command-bus/logging/command-logger.spec.js.map +1 -1
  20. package/dist/command-bus/serialization/index.d.ts +6 -0
  21. package/dist/command-bus/serialization/index.js +9 -0
  22. package/dist/command-bus/serialization/index.js.map +1 -0
  23. package/dist/command-bus/serialization/msgpack-serializer.d.ts +26 -0
  24. package/dist/command-bus/serialization/msgpack-serializer.js +70 -0
  25. package/dist/command-bus/serialization/msgpack-serializer.js.map +1 -0
  26. package/dist/command-bus/serialization/msgpack-serializer.spec.js +223 -0
  27. package/dist/command-bus/serialization/msgpack-serializer.spec.js.map +1 -0
  28. package/dist/command-bus/serialization/serializer.interface.d.ts +21 -0
  29. package/dist/command-bus/serialization/serializer.interface.js +3 -0
  30. package/dist/command-bus/serialization/serializer.interface.js.map +1 -0
  31. package/dist/command-bus/transport/consumer-loop.d.ts +45 -0
  32. package/dist/command-bus/transport/consumer-loop.js +90 -0
  33. package/dist/command-bus/transport/consumer-loop.js.map +1 -0
  34. package/dist/command-bus/transport/consumer-loop.spec.js +216 -0
  35. package/dist/command-bus/transport/consumer-loop.spec.js.map +1 -0
  36. package/dist/command-bus/transport/index.d.ts +21 -0
  37. package/dist/command-bus/transport/index.js +23 -0
  38. package/dist/command-bus/transport/index.js.map +1 -0
  39. package/dist/command-bus/transport/message-processor.d.ts +59 -0
  40. package/dist/command-bus/transport/message-processor.js +111 -0
  41. package/dist/command-bus/transport/message-processor.js.map +1 -0
  42. package/dist/command-bus/transport/message-processor.spec.js +185 -0
  43. package/dist/command-bus/transport/message-processor.spec.js.map +1 -0
  44. package/dist/command-bus/transport/pending-recovery.d.ts +54 -0
  45. package/dist/command-bus/transport/pending-recovery.js +139 -0
  46. package/dist/command-bus/transport/pending-recovery.js.map +1 -0
  47. package/dist/command-bus/transport/pending-recovery.spec.js +176 -0
  48. package/dist/command-bus/transport/pending-recovery.spec.js.map +1 -0
  49. package/dist/command-bus/transport/redis-codec.d.ts +24 -0
  50. package/dist/command-bus/transport/redis-codec.js +33 -0
  51. package/dist/command-bus/transport/redis-codec.js.map +1 -0
  52. package/dist/command-bus/transport/redis-codec.spec.js +53 -0
  53. package/dist/command-bus/transport/redis-codec.spec.js.map +1 -0
  54. package/dist/command-bus/transport/redis-streams-transport.d.ts +91 -0
  55. package/dist/command-bus/transport/redis-streams-transport.js +134 -0
  56. package/dist/command-bus/transport/redis-streams-transport.js.map +1 -0
  57. package/dist/command-bus/transport/redis-streams-transport.spec.js +420 -0
  58. package/dist/command-bus/transport/redis-streams-transport.spec.js.map +1 -0
  59. package/dist/command-bus/transport/rpc-handler.d.ts +39 -0
  60. package/dist/command-bus/transport/rpc-handler.js +87 -0
  61. package/dist/command-bus/transport/rpc-handler.js.map +1 -0
  62. package/dist/command-bus/transport/rpc-handler.spec.js +157 -0
  63. package/dist/command-bus/transport/rpc-handler.spec.js.map +1 -0
  64. package/dist/command-bus/transport/stream-consumer.d.ts +89 -0
  65. package/dist/command-bus/transport/stream-consumer.js +181 -0
  66. package/dist/command-bus/transport/stream-consumer.js.map +1 -0
  67. package/dist/command-bus/transport/stream-consumer.spec.js +284 -0
  68. package/dist/command-bus/transport/stream-consumer.spec.js.map +1 -0
  69. package/dist/command-bus/transport/stream-producer.d.ts +23 -0
  70. package/dist/command-bus/transport/stream-producer.js +70 -0
  71. package/dist/command-bus/transport/stream-producer.js.map +1 -0
  72. package/dist/command-bus/transport/stream-producer.spec.js +125 -0
  73. package/dist/command-bus/transport/stream-producer.spec.js.map +1 -0
  74. package/dist/command-bus/transport/transport.interface.d.ts +87 -0
  75. package/dist/command-bus/transport/transport.interface.js +3 -0
  76. package/dist/command-bus/transport/transport.interface.js.map +1 -0
  77. package/dist/command-bus/types/index.d.ts +9 -80
  78. package/dist/examples/rpc-throughput.demo.js +24 -22
  79. package/dist/examples/rpc-throughput.demo.js.map +1 -1
  80. package/dist/examples/rpc.demo.js +47 -53
  81. package/dist/examples/rpc.demo.js.map +1 -1
  82. package/dist/index.d.ts +8 -5
  83. package/dist/index.js +6 -4
  84. package/dist/index.js.map +1 -1
  85. package/dist/pp-command-bus-2.0.0.tgz +0 -0
  86. package/dist/shared/redis/connection-pool.d.ts +54 -0
  87. package/dist/shared/redis/connection-pool.js +117 -0
  88. package/dist/shared/redis/connection-pool.js.map +1 -0
  89. package/dist/shared/redis/connection-pool.spec.js +114 -0
  90. package/dist/shared/redis/connection-pool.spec.js.map +1 -0
  91. package/dist/shared/redis/index.d.ts +5 -3
  92. package/dist/shared/redis/index.js +6 -4
  93. package/dist/shared/redis/index.js.map +1 -1
  94. package/dist/shared/redis/rpc-connection-pool.d.ts +61 -0
  95. package/dist/shared/redis/rpc-connection-pool.js +154 -0
  96. package/dist/shared/redis/rpc-connection-pool.js.map +1 -0
  97. package/dist/shared/redis/rpc-connection-pool.spec.d.ts +1 -0
  98. package/dist/shared/redis/rpc-connection-pool.spec.js +173 -0
  99. package/dist/shared/redis/rpc-connection-pool.spec.js.map +1 -0
  100. package/dist/shared/types.d.ts +0 -4
  101. package/dist/shared/utils/error-utils.d.ts +8 -0
  102. package/dist/shared/utils/error-utils.js +14 -0
  103. package/dist/shared/utils/error-utils.js.map +1 -0
  104. package/package.json +12 -12
  105. package/dist/command-bus/config/auto-config-optimizer.d.ts +0 -35
  106. package/dist/command-bus/config/auto-config-optimizer.js +0 -52
  107. package/dist/command-bus/config/auto-config-optimizer.js.map +0 -1
  108. package/dist/command-bus/config/auto-config-optimizer.spec.js +0 -42
  109. package/dist/command-bus/config/auto-config-optimizer.spec.js.map +0 -1
  110. package/dist/command-bus/job/index.d.ts +0 -6
  111. package/dist/command-bus/job/index.js +0 -15
  112. package/dist/command-bus/job/index.js.map +0 -1
  113. package/dist/command-bus/job/job-options-builder.d.ts +0 -21
  114. package/dist/command-bus/job/job-options-builder.js +0 -58
  115. package/dist/command-bus/job/job-options-builder.js.map +0 -1
  116. package/dist/command-bus/job/job-options-builder.spec.js +0 -156
  117. package/dist/command-bus/job/job-options-builder.spec.js.map +0 -1
  118. package/dist/command-bus/job/job-processor.d.ts +0 -39
  119. package/dist/command-bus/job/job-processor.js +0 -203
  120. package/dist/command-bus/job/job-processor.js.map +0 -1
  121. package/dist/command-bus/job/job-processor.spec.js +0 -437
  122. package/dist/command-bus/job/job-processor.spec.js.map +0 -1
  123. package/dist/command-bus/queue/index.d.ts +0 -5
  124. package/dist/command-bus/queue/index.js +0 -13
  125. package/dist/command-bus/queue/index.js.map +0 -1
  126. package/dist/command-bus/queue/queue-manager.d.ts +0 -56
  127. package/dist/command-bus/queue/queue-manager.js +0 -163
  128. package/dist/command-bus/queue/queue-manager.js.map +0 -1
  129. package/dist/command-bus/queue/queue-manager.spec.js +0 -371
  130. package/dist/command-bus/queue/queue-manager.spec.js.map +0 -1
  131. package/dist/command-bus/rpc/index.d.ts +0 -11
  132. package/dist/command-bus/rpc/index.js +0 -19
  133. package/dist/command-bus/rpc/index.js.map +0 -1
  134. package/dist/command-bus/rpc/payload-compression.service.d.ts +0 -51
  135. package/dist/command-bus/rpc/payload-compression.service.js +0 -218
  136. package/dist/command-bus/rpc/payload-compression.service.js.map +0 -1
  137. package/dist/command-bus/rpc/payload-compression.service.spec.js +0 -379
  138. package/dist/command-bus/rpc/payload-compression.service.spec.js.map +0 -1
  139. package/dist/command-bus/rpc/rpc-coordinator.d.ts +0 -96
  140. package/dist/command-bus/rpc/rpc-coordinator.js +0 -500
  141. package/dist/command-bus/rpc/rpc-coordinator.js.map +0 -1
  142. package/dist/command-bus/rpc/rpc-coordinator.spec.js +0 -622
  143. package/dist/command-bus/rpc/rpc-coordinator.spec.js.map +0 -1
  144. package/dist/command-bus/rpc/rpc-job-cancellation.service.d.ts +0 -82
  145. package/dist/command-bus/rpc/rpc-job-cancellation.service.js +0 -180
  146. package/dist/command-bus/rpc/rpc-job-cancellation.service.js.map +0 -1
  147. package/dist/command-bus/rpc/rpc-job-cancellation.service.spec.js +0 -286
  148. package/dist/command-bus/rpc/rpc-job-cancellation.service.spec.js.map +0 -1
  149. package/dist/command-bus/worker/index.d.ts +0 -10
  150. package/dist/command-bus/worker/index.js +0 -19
  151. package/dist/command-bus/worker/index.js.map +0 -1
  152. package/dist/command-bus/worker/worker-benchmark.d.ts +0 -71
  153. package/dist/command-bus/worker/worker-benchmark.js +0 -203
  154. package/dist/command-bus/worker/worker-benchmark.js.map +0 -1
  155. package/dist/command-bus/worker/worker-benchmark.spec.js +0 -310
  156. package/dist/command-bus/worker/worker-benchmark.spec.js.map +0 -1
  157. package/dist/command-bus/worker/worker-metrics-collector.d.ts +0 -98
  158. package/dist/command-bus/worker/worker-metrics-collector.js +0 -242
  159. package/dist/command-bus/worker/worker-metrics-collector.js.map +0 -1
  160. package/dist/command-bus/worker/worker-orchestrator.d.ts +0 -70
  161. package/dist/command-bus/worker/worker-orchestrator.js +0 -339
  162. package/dist/command-bus/worker/worker-orchestrator.js.map +0 -1
  163. package/dist/command-bus/worker/worker-orchestrator.spec.js +0 -712
  164. package/dist/command-bus/worker/worker-orchestrator.spec.js.map +0 -1
  165. package/dist/examples/auto-config.demo.d.ts +0 -9
  166. package/dist/examples/auto-config.demo.js +0 -106
  167. package/dist/examples/auto-config.demo.js.map +0 -1
  168. package/dist/examples/rpc-compression.demo.d.ts +0 -5
  169. package/dist/examples/rpc-compression.demo.js +0 -363
  170. package/dist/examples/rpc-compression.demo.js.map +0 -1
  171. package/dist/examples/rpc-resilience.demo.d.ts +0 -11
  172. package/dist/examples/rpc-resilience.demo.js +0 -235
  173. package/dist/examples/rpc-resilience.demo.js.map +0 -1
  174. package/dist/pp-command-bus-1.4.0.tgz +0 -0
  175. package/dist/shared/config/base-config.d.ts +0 -54
  176. package/dist/shared/config/base-config.js +0 -114
  177. package/dist/shared/config/base-config.js.map +0 -1
  178. package/dist/shared/config/base-config.spec.js +0 -204
  179. package/dist/shared/config/base-config.spec.js.map +0 -1
  180. package/dist/shared/config/index.d.ts +0 -1
  181. package/dist/shared/config/index.js +0 -9
  182. package/dist/shared/config/index.js.map +0 -1
  183. package/dist/shared/redis/redis-connection-factory.d.ts +0 -66
  184. package/dist/shared/redis/redis-connection-factory.js +0 -113
  185. package/dist/shared/redis/redis-connection-factory.js.map +0 -1
  186. /package/dist/command-bus/{config/auto-config-optimizer.spec.d.ts → serialization/msgpack-serializer.spec.d.ts} +0 -0
  187. /package/dist/command-bus/{job/job-options-builder.spec.d.ts → transport/consumer-loop.spec.d.ts} +0 -0
  188. /package/dist/command-bus/{job/job-processor.spec.d.ts → transport/message-processor.spec.d.ts} +0 -0
  189. /package/dist/command-bus/{queue/queue-manager.spec.d.ts → transport/pending-recovery.spec.d.ts} +0 -0
  190. /package/dist/command-bus/{rpc/payload-compression.service.spec.d.ts → transport/redis-codec.spec.d.ts} +0 -0
  191. /package/dist/command-bus/{rpc/rpc-coordinator.spec.d.ts → transport/redis-streams-transport.spec.d.ts} +0 -0
  192. /package/dist/command-bus/{rpc/rpc-job-cancellation.service.spec.d.ts → transport/rpc-handler.spec.d.ts} +0 -0
  193. /package/dist/command-bus/{worker/worker-benchmark.spec.d.ts → transport/stream-consumer.spec.d.ts} +0 -0
  194. /package/dist/command-bus/{worker/worker-orchestrator.spec.d.ts → transport/stream-producer.spec.d.ts} +0 -0
  195. /package/dist/shared/{config/base-config.spec.d.ts → redis/connection-pool.spec.d.ts} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-processor.spec.js","sourceRoot":"","sources":["../../../src/command-bus/transport/message-processor.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import type { ILogger } from '../../shared/types';
2
+ import type { ConsumerHandler } from './transport.interface';
3
+ import type RedisConnectionPool from '../../shared/redis/connection-pool';
4
+ import type { StreamConsumer } from './stream-consumer';
5
+ /**
6
+ * Konfiguracja PendingRecovery
7
+ */
8
+ export interface PendingRecoveryOptions {
9
+ pool: RedisConnectionPool;
10
+ logger: ILogger;
11
+ consumerId: string;
12
+ maxAttempts: number;
13
+ claimTimeout: number;
14
+ }
15
+ /**
16
+ * Recovery pending wiadomości — XPENDING/XCLAIM natywny mechanizm retry
17
+ *
18
+ * Odpowiedzialności:
19
+ * - Periodyczne sprawdzanie stalled wiadomości (XPENDING)
20
+ * - Przejmowanie ich (XCLAIM) i przekazywanie do StreamConsumer.processMessage()
21
+ * - Dead letter dla wiadomości które przekroczyły maxAttempts
22
+ * - Scheduling (setInterval/clearInterval)
23
+ */
24
+ export declare class PendingRecovery {
25
+ private readonly pool;
26
+ private readonly logger;
27
+ private readonly consumerId;
28
+ private readonly maxAttempts;
29
+ private readonly claimTimeout;
30
+ /** Intervaly recovery — do graceful shutdown */
31
+ private readonly recoveryIntervals;
32
+ constructor(options: PendingRecoveryOptions);
33
+ /**
34
+ * Uruchamia periodyczny recovery dla strumienia
35
+ * @param streamName - Nazwa strumienia Redis
36
+ * @param groupName - Nazwa grupy konsumentów
37
+ * @param handler - Handler przetwarzający wiadomości
38
+ * @param consumer - Referencja do StreamConsumer (processMessage)
39
+ */
40
+ start(streamName: string, groupName: string, handler: ConsumerHandler, consumer: StreamConsumer): void;
41
+ /**
42
+ * Zatrzymuje wszystkie recovery intervals
43
+ */
44
+ stop(): void;
45
+ /**
46
+ * Sprawdza i przejmuje stalled wiadomości
47
+ *
48
+ * XCLAIM zwraca dane wiadomości — recovery sam je przetwarza via consumer.processMessage()
49
+ * (consumer loop czyta '>' = tylko nowe, nie widzi XCLAIM'owanych)
50
+ *
51
+ * Używa pool connections (NIE dedykowane consumer conn — zajęte przez XREADGROUP BLOCK)
52
+ */
53
+ private recoverPending;
54
+ }
@@ -0,0 +1,139 @@
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.PendingRecovery = void 0;
13
+ const error_utils_1 = require("../../shared/utils/error-utils");
14
+ /**
15
+ * Recovery pending wiadomości — XPENDING/XCLAIM natywny mechanizm retry
16
+ *
17
+ * Odpowiedzialności:
18
+ * - Periodyczne sprawdzanie stalled wiadomości (XPENDING)
19
+ * - Przejmowanie ich (XCLAIM) i przekazywanie do StreamConsumer.processMessage()
20
+ * - Dead letter dla wiadomości które przekroczyły maxAttempts
21
+ * - Scheduling (setInterval/clearInterval)
22
+ */
23
+ class PendingRecovery {
24
+ constructor(options) {
25
+ /** Intervaly recovery — do graceful shutdown */
26
+ this.recoveryIntervals = [];
27
+ this.pool = options.pool;
28
+ this.logger = options.logger;
29
+ this.consumerId = options.consumerId;
30
+ this.maxAttempts = options.maxAttempts;
31
+ this.claimTimeout = options.claimTimeout;
32
+ }
33
+ /**
34
+ * Uruchamia periodyczny recovery dla strumienia
35
+ * @param streamName - Nazwa strumienia Redis
36
+ * @param groupName - Nazwa grupy konsumentów
37
+ * @param handler - Handler przetwarzający wiadomości
38
+ * @param consumer - Referencja do StreamConsumer (processMessage)
39
+ */
40
+ start(streamName, groupName, handler, consumer) {
41
+ const interval = setInterval(() => {
42
+ void this.recoverPending(streamName, groupName, handler, consumer);
43
+ }, this.claimTimeout);
44
+ this.recoveryIntervals.push(interval);
45
+ }
46
+ /**
47
+ * Zatrzymuje wszystkie recovery intervals
48
+ */
49
+ stop() {
50
+ for (const interval of this.recoveryIntervals) {
51
+ clearInterval(interval);
52
+ }
53
+ this.recoveryIntervals.length = 0;
54
+ }
55
+ /**
56
+ * Sprawdza i przejmuje stalled wiadomości
57
+ *
58
+ * XCLAIM zwraca dane wiadomości — recovery sam je przetwarza via consumer.processMessage()
59
+ * (consumer loop czyta '>' = tylko nowe, nie widzi XCLAIM'owanych)
60
+ *
61
+ * Używa pool connections (NIE dedykowane consumer conn — zajęte przez XREADGROUP BLOCK)
62
+ */
63
+ recoverPending(streamName, groupName, handler, consumer) {
64
+ return __awaiter(this, void 0, void 0, function* () {
65
+ try {
66
+ const conn = this.pool.next();
67
+ const pending = yield conn.xpending(streamName, groupName, '-', '+', 10);
68
+ if (!Array.isArray(pending) || pending.length === 0)
69
+ return;
70
+ for (const entry of pending) {
71
+ // entry = [messageId, consumer, idleTime, deliveryCount]
72
+ const pendingEntry = entry;
73
+ const [messageId, , idleTime, deliveryCount] = pendingEntry;
74
+ if (idleTime > this.claimTimeout && deliveryCount < this.maxAttempts) {
75
+ // Przejmij stalled wiadomość — XCLAIM zwraca dane wiadomości
76
+ const claimed = (yield this.pool
77
+ .next()
78
+ .xclaim(streamName, groupName, this.consumerId, this.claimTimeout, messageId));
79
+ this.logger.debug('Przejęto stalled wiadomość', {
80
+ streamName,
81
+ messageId,
82
+ deliveryCount,
83
+ idleTime,
84
+ timestamp: new Date().toISOString(),
85
+ });
86
+ // XCLAIM zwraca [[messageId, [field, value, ...]]] — przetwórz i czekaj na wynik
87
+ if (Array.isArray(claimed) && claimed.length > 0) {
88
+ const recoveryPromises = [];
89
+ for (const [claimedId, fields] of claimed) {
90
+ if (fields && fields.length >= 2) {
91
+ recoveryPromises.push(consumer
92
+ .processMessage(streamName, groupName, claimedId, fields, handler)
93
+ .catch((err) => this.logger.error('Błąd recovery wiadomości', {
94
+ streamName,
95
+ messageId: claimedId,
96
+ error: (0, error_utils_1.getErrorMessage)(err),
97
+ })));
98
+ }
99
+ }
100
+ yield Promise.allSettled(recoveryPromises);
101
+ }
102
+ }
103
+ else if (deliveryCount >= this.maxAttempts) {
104
+ // D3: Dead Letter Stream — XCLAIM + XADD do DLQ przed XACK
105
+ const claimed = (yield this.pool
106
+ .next()
107
+ .xclaim(streamName, groupName, this.consumerId, 0, messageId));
108
+ if (Array.isArray(claimed) && claimed.length > 0) {
109
+ const [, fields] = claimed[0];
110
+ if (fields && fields.length >= 2) {
111
+ yield this.pool
112
+ .next()
113
+ .xadd(`dlq:${streamName}`, '*', ...fields, 'original_stream', streamName, 'delivery_count', String(deliveryCount));
114
+ }
115
+ }
116
+ yield this.pool.next().xack(streamName, groupName, messageId);
117
+ this.logger.error('Wiadomość przeniesiona do Dead Letter Queue', {
118
+ streamName,
119
+ dlqStream: `dlq:${streamName}`,
120
+ messageId,
121
+ deliveryCount,
122
+ maxAttempts: this.maxAttempts,
123
+ timestamp: new Date().toISOString(),
124
+ });
125
+ }
126
+ }
127
+ }
128
+ catch (error) {
129
+ this.logger.error('Błąd recovery pending wiadomości', {
130
+ streamName,
131
+ error: (0, error_utils_1.getErrorMessage)(error),
132
+ timestamp: new Date().toISOString(),
133
+ });
134
+ }
135
+ });
136
+ }
137
+ }
138
+ exports.PendingRecovery = PendingRecovery;
139
+ //# sourceMappingURL=pending-recovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pending-recovery.js","sourceRoot":"","sources":["../../../src/command-bus/transport/pending-recovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,176 @@
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 pending_recovery_1 = require("./pending-recovery");
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
+ function createMockConnection() {
25
+ return {
26
+ xpending: jest.fn().mockResolvedValue([]),
27
+ xclaim: jest.fn().mockResolvedValue([]),
28
+ xack: jest.fn().mockResolvedValue(1),
29
+ xadd: jest.fn().mockResolvedValue('1700000000000-0'),
30
+ };
31
+ }
32
+ function createMockPool() {
33
+ const conn = createMockConnection();
34
+ return {
35
+ pool: { next: jest.fn().mockReturnValue(conn) },
36
+ conn,
37
+ };
38
+ }
39
+ function createMockConsumer() {
40
+ return {
41
+ processMessage: jest.fn().mockResolvedValue(undefined),
42
+ processing: new Map(),
43
+ };
44
+ }
45
+ describe('PendingRecovery', () => {
46
+ let recovery;
47
+ let logger;
48
+ let mockConn;
49
+ let mockPool;
50
+ let mockConsumer;
51
+ beforeEach(() => {
52
+ jest.clearAllMocks();
53
+ jest.useFakeTimers();
54
+ logger = createMockLogger();
55
+ const poolMock = createMockPool();
56
+ mockPool = poolMock.pool;
57
+ mockConn = poolMock.conn;
58
+ mockConsumer = createMockConsumer();
59
+ recovery = new pending_recovery_1.PendingRecovery({
60
+ pool: mockPool,
61
+ logger,
62
+ consumerId: 'test-consumer',
63
+ maxAttempts: 3,
64
+ claimTimeout: 30000,
65
+ });
66
+ });
67
+ afterEach(() => {
68
+ recovery.stop();
69
+ jest.useRealTimers();
70
+ });
71
+ describe('start/stop', () => {
72
+ it('powinien uruchomić periodyczny recovery', () => {
73
+ const handler = jest.fn();
74
+ recovery.start('cmd:Test', 'workers', handler, mockConsumer);
75
+ expect(recovery['recoveryIntervals'].length).toBe(1);
76
+ });
77
+ it('powinien zatrzymać recovery intervals', () => {
78
+ const handler = jest.fn();
79
+ recovery.start('cmd:Test', 'workers', handler, mockConsumer);
80
+ recovery.start('cmd:Other', 'workers', handler, mockConsumer);
81
+ expect(recovery['recoveryIntervals'].length).toBe(2);
82
+ recovery.stop();
83
+ expect(recovery['recoveryIntervals'].length).toBe(0);
84
+ });
85
+ it('powinien wywołać recoverPending co claimTimeout', () => {
86
+ const handler = jest.fn();
87
+ recovery.start('cmd:Test', 'workers', handler, mockConsumer);
88
+ // Advance timer o 3 interwały
89
+ jest.advanceTimersByTime(90000); // 3 * 30000
90
+ // XPENDING powinien być wywołany 3 razy
91
+ expect(mockConn.xpending).toHaveBeenCalledTimes(3);
92
+ });
93
+ });
94
+ describe('recoverPending()', () => {
95
+ /**
96
+ * Dostęp do prywatnej metody recoverPending przez casting
97
+ */
98
+ const callRecoverPending = () => __awaiter(void 0, void 0, void 0, function* () {
99
+ const any = recovery;
100
+ yield any['recoverPending']('cmd:Test', 'workers', jest.fn(), mockConsumer);
101
+ });
102
+ it('powinien nie robić nic gdy brak pending wiadomości', () => __awaiter(void 0, void 0, void 0, function* () {
103
+ mockConn.xpending.mockResolvedValue([]);
104
+ yield callRecoverPending();
105
+ expect(mockConn.xclaim).not.toHaveBeenCalled();
106
+ expect(mockConn.xack).not.toHaveBeenCalled();
107
+ }));
108
+ it('powinien przejąć stalled wiadomość przez XCLAIM', () => __awaiter(void 0, void 0, void 0, function* () {
109
+ const testPayload = Buffer.from('recovered-data').toString('base64');
110
+ mockConn.xpending.mockResolvedValue([
111
+ ['msg-1', 'consumer-old', 60000, 1], // idleTime > claimTimeout, deliveryCount < maxAttempts
112
+ ]);
113
+ mockConn.xclaim.mockResolvedValue([['msg-1', ['data', testPayload]]]);
114
+ yield callRecoverPending();
115
+ expect(mockConn.xclaim).toHaveBeenCalledWith('cmd:Test', 'workers', 'test-consumer', 30000, 'msg-1');
116
+ expect(mockConsumer.processMessage).toHaveBeenCalledWith('cmd:Test', 'workers', 'msg-1', ['data', testPayload], expect.any(Function));
117
+ }));
118
+ it('powinien przenieść do DLQ po maxAttempts (D3)', () => __awaiter(void 0, void 0, void 0, function* () {
119
+ const testPayload = Buffer.from('dead-data').toString('base64');
120
+ mockConn.xpending.mockResolvedValue([
121
+ ['msg-dead', 'consumer-old', 60000, 3], // deliveryCount >= maxAttempts
122
+ ]);
123
+ // XCLAIM zwraca dane wiadomości do przeniesienia do DLQ
124
+ mockConn.xclaim.mockResolvedValue([['msg-dead', ['data', testPayload]]]);
125
+ yield callRecoverPending();
126
+ // XCLAIM powinien być wywołany (żeby pobrać dane do DLQ)
127
+ expect(mockConn.xclaim).toHaveBeenCalled();
128
+ // XADD do dlq: strumienia
129
+ expect(mockConn.xadd).toHaveBeenCalledWith('dlq:cmd:Test', '*', 'data', testPayload, 'original_stream', 'cmd:Test', 'delivery_count', '3');
130
+ // XACK po przeniesieniu do DLQ
131
+ expect(mockConn.xack).toHaveBeenCalledWith('cmd:Test', 'workers', 'msg-dead');
132
+ expect(logger.error).toHaveBeenCalledWith('Wiadomość przeniesiona do Dead Letter Queue', expect.objectContaining({
133
+ messageId: 'msg-dead',
134
+ dlqStream: 'dlq:cmd:Test',
135
+ deliveryCount: 3,
136
+ }));
137
+ }));
138
+ it('nie powinien przejmować wiadomości z idleTime < claimTimeout', () => __awaiter(void 0, void 0, void 0, function* () {
139
+ mockConn.xpending.mockResolvedValue([
140
+ ['msg-young', 'consumer-other', 5000, 1], // idleTime (5s) < claimTimeout (30s)
141
+ ]);
142
+ yield callRecoverPending();
143
+ expect(mockConn.xclaim).not.toHaveBeenCalled();
144
+ expect(mockConn.xack).not.toHaveBeenCalled();
145
+ }));
146
+ it('powinien zalogować błąd przy wyjątku', () => __awaiter(void 0, void 0, void 0, function* () {
147
+ mockConn.xpending.mockRejectedValue(new Error('Redis connection error'));
148
+ yield callRecoverPending();
149
+ expect(logger.error).toHaveBeenCalledWith('Błąd recovery pending wiadomości', expect.objectContaining({ error: 'Redis connection error' }));
150
+ }));
151
+ it('powinien obsłużyć pusty wynik XCLAIM', () => __awaiter(void 0, void 0, void 0, function* () {
152
+ mockConn.xpending.mockResolvedValue([['msg-1', 'consumer-old', 60000, 1]]);
153
+ mockConn.xclaim.mockResolvedValue([]);
154
+ yield callRecoverPending();
155
+ // processMessage NIE powinien być wywołany (brak danych w XCLAIM)
156
+ expect(mockConsumer.processMessage).not.toHaveBeenCalled();
157
+ }));
158
+ it('powinien obsłużyć wiele pending wiadomości', () => __awaiter(void 0, void 0, void 0, function* () {
159
+ const testPayload = Buffer.from('data').toString('base64');
160
+ mockConn.xpending.mockResolvedValue([
161
+ ['msg-1', 'consumer-old', 60000, 1],
162
+ ['msg-2', 'consumer-old', 60000, 2],
163
+ ['msg-dead', 'consumer-old', 60000, 5], // Dead letter
164
+ ]);
165
+ mockConn.xclaim.mockResolvedValue([['msg-claimed', ['data', testPayload]]]);
166
+ yield callRecoverPending();
167
+ // XCLAIM: msg-1, msg-2 (recovery) + msg-dead (DLQ pobieranie danych) = 3
168
+ expect(mockConn.xclaim).toHaveBeenCalledTimes(3);
169
+ // XADD do DLQ
170
+ expect(mockConn.xadd).toHaveBeenCalledWith('dlq:cmd:Test', '*', expect.anything(), expect.anything(), 'original_stream', 'cmd:Test', 'delivery_count', '5');
171
+ // XACK dla dead letter
172
+ expect(mockConn.xack).toHaveBeenCalledWith('cmd:Test', 'workers', 'msg-dead');
173
+ }));
174
+ });
175
+ });
176
+ //# sourceMappingURL=pending-recovery.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pending-recovery.spec.js","sourceRoot":"","sources":["../../../src/command-bus/transport/pending-recovery.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Kodek Redis — enkapsulacja kodowania/dekodowania binarnych danych
3
+ *
4
+ * ioredis dekoduje string responses jako UTF-8, co korumpuje surowe bajty msgpack.
5
+ * Base64 zapewnia bezpieczne przechowywanie binarnych danych w Redis Streams.
6
+ *
7
+ * Warianty *Buffer() (np. xreadgroupBuffer) nie są praktyczne — zwracają Buffer
8
+ * dla WSZYSTKICH pól (nazwy strumieni, messageId, klucze), co komplikuje parsowanie
9
+ * zagnieżdżonej struktury XREADGROUP.
10
+ */
11
+ export declare class RedisCodec {
12
+ /**
13
+ * Koduje dane binarne do bezpiecznego formatu dla Redis
14
+ * @param data - Surowe dane binarne
15
+ * @returns Zakodowany string (base64)
16
+ */
17
+ static encode(data: Buffer): string;
18
+ /**
19
+ * Dekoduje dane z Redis do formatu binarnego
20
+ * @param encoded - Zakodowany string (base64)
21
+ * @returns Surowe dane binarne
22
+ */
23
+ static decode(encoded: string): Buffer;
24
+ }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RedisCodec = void 0;
4
+ /**
5
+ * Kodek Redis — enkapsulacja kodowania/dekodowania binarnych danych
6
+ *
7
+ * ioredis dekoduje string responses jako UTF-8, co korumpuje surowe bajty msgpack.
8
+ * Base64 zapewnia bezpieczne przechowywanie binarnych danych w Redis Streams.
9
+ *
10
+ * Warianty *Buffer() (np. xreadgroupBuffer) nie są praktyczne — zwracają Buffer
11
+ * dla WSZYSTKICH pól (nazwy strumieni, messageId, klucze), co komplikuje parsowanie
12
+ * zagnieżdżonej struktury XREADGROUP.
13
+ */
14
+ class RedisCodec {
15
+ /**
16
+ * Koduje dane binarne do bezpiecznego formatu dla Redis
17
+ * @param data - Surowe dane binarne
18
+ * @returns Zakodowany string (base64)
19
+ */
20
+ static encode(data) {
21
+ return data.toString('base64');
22
+ }
23
+ /**
24
+ * Dekoduje dane z Redis do formatu binarnego
25
+ * @param encoded - Zakodowany string (base64)
26
+ * @returns Surowe dane binarne
27
+ */
28
+ static decode(encoded) {
29
+ return Buffer.from(encoded, 'base64');
30
+ }
31
+ }
32
+ exports.RedisCodec = RedisCodec;
33
+ //# sourceMappingURL=redis-codec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis-codec.js","sourceRoot":"","sources":["../../../src/command-bus/transport/redis-codec.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;GASG;AACH,MAAa,UAAU;IACrB;;;;OAIG;IACH,MAAM,CAAC,MAAM,CAAC,IAAY;QACxB,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,MAAM,CAAC,OAAe;QAC3B,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACxC,CAAC;CACF;AAlBD,gCAkBC"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const redis_codec_1 = require("./redis-codec");
4
+ describe('RedisCodec', () => {
5
+ describe('encode/decode roundtrip', () => {
6
+ it('powinien zakodować i zdekodować dane binarne bez utraty', () => {
7
+ const original = Buffer.from('Jan Kowalski, ul. Długa 15, Warszawa');
8
+ const encoded = redis_codec_1.RedisCodec.encode(original);
9
+ const decoded = redis_codec_1.RedisCodec.decode(encoded);
10
+ expect(decoded).toEqual(original);
11
+ });
12
+ it('powinien obsłużyć pusty Buffer', () => {
13
+ const original = Buffer.alloc(0);
14
+ const encoded = redis_codec_1.RedisCodec.encode(original);
15
+ const decoded = redis_codec_1.RedisCodec.decode(encoded);
16
+ expect(decoded).toEqual(original);
17
+ expect(decoded.length).toBe(0);
18
+ });
19
+ it('powinien obsłużyć dane binarne z null bytes', () => {
20
+ const original = Buffer.from([0x00, 0x01, 0xff, 0x00, 0xab]);
21
+ const encoded = redis_codec_1.RedisCodec.encode(original);
22
+ const decoded = redis_codec_1.RedisCodec.decode(encoded);
23
+ expect(decoded).toEqual(original);
24
+ });
25
+ it('powinien obsłużyć duże dane (1MB)', () => {
26
+ const original = Buffer.alloc(1024 * 1024, 0xab);
27
+ const encoded = redis_codec_1.RedisCodec.encode(original);
28
+ const decoded = redis_codec_1.RedisCodec.decode(encoded);
29
+ expect(decoded).toEqual(original);
30
+ });
31
+ });
32
+ describe('encode()', () => {
33
+ it('powinien zwrócić string base64', () => {
34
+ const data = Buffer.from('test');
35
+ const encoded = redis_codec_1.RedisCodec.encode(data);
36
+ expect(typeof encoded).toBe('string');
37
+ // Walidacja formatu base64
38
+ expect(encoded).toMatch(/^[A-Za-z0-9+/]*={0,2}$/);
39
+ });
40
+ });
41
+ describe('decode()', () => {
42
+ it('powinien zdekodować prawidłowy base64 string', () => {
43
+ const base64 = Buffer.from('Anna Nowak').toString('base64');
44
+ const decoded = redis_codec_1.RedisCodec.decode(base64);
45
+ expect(decoded.toString()).toBe('Anna Nowak');
46
+ });
47
+ it('powinien zwrócić pusty Buffer dla pustego stringa', () => {
48
+ const decoded = redis_codec_1.RedisCodec.decode('');
49
+ expect(decoded.length).toBe(0);
50
+ });
51
+ });
52
+ });
53
+ //# sourceMappingURL=redis-codec.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis-codec.spec.js","sourceRoot":"","sources":["../../../src/command-bus/transport/redis-codec.spec.ts"],"names":[],"mappings":";;AAAA,+CAA2C;AAE3C,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACvC,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;YACjE,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;YACrE,MAAM,OAAO,GAAG,wBAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC5C,MAAM,OAAO,GAAG,wBAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAE3C,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACjC,MAAM,OAAO,GAAG,wBAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC5C,MAAM,OAAO,GAAG,wBAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAE3C,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAClC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;YACrD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;YAC7D,MAAM,OAAO,GAAG,wBAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC5C,MAAM,OAAO,GAAG,wBAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAE3C,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;YAC3C,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,EAAE,IAAI,CAAC,CAAC;YACjD,MAAM,OAAO,GAAG,wBAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC5C,MAAM,OAAO,GAAG,wBAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAE3C,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;QACxB,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACjC,MAAM,OAAO,GAAG,wBAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAExC,MAAM,CAAC,OAAO,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACtC,2BAA2B;YAC3B,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;QACxB,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;YACtD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC5D,MAAM,OAAO,GAAG,wBAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAE1C,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;YAC3D,MAAM,OAAO,GAAG,wBAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACtC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,91 @@
1
+ import type { ILogger } from '../../shared/types';
2
+ import type { ISerializer } from '../serialization/serializer.interface';
3
+ import type { ITransport, ConsumerHandler } from './transport.interface';
4
+ import type RedisConnectionPool from '../../shared/redis/connection-pool';
5
+ import type RpcConnectionPool from '../../shared/redis/rpc-connection-pool';
6
+ /**
7
+ * Opcje konfiguracji RedisStreamsTransport
8
+ */
9
+ export interface RedisStreamsTransportOptions {
10
+ /** Pula połączeń Redis (round-robin, non-blocking ops) */
11
+ pool: RedisConnectionPool;
12
+ /** Pula połączeń RPC (bounded, lazy, blocking BRPOP) */
13
+ rpcPool: RpcConnectionPool;
14
+ /** Serializer do konwersji RPC metadata */
15
+ serializer: ISerializer;
16
+ /** Logger */
17
+ logger: ILogger;
18
+ /** Maksymalna liczba wiadomości w strumieniu (XTRIM ~) */
19
+ maxRetained: number;
20
+ /** Maksymalna liczba prób przetworzenia wiadomości */
21
+ maxAttempts: number;
22
+ /** Czas po którym stalled wiadomość jest przejmowana (ms) */
23
+ claimTimeout: number;
24
+ /** Liczba wiadomości pobieranych w jednym XREADGROUP */
25
+ batchSize: number;
26
+ /** Maksymalna liczba wiadomości przetwarzanych równolegle per konsument */
27
+ concurrency: number;
28
+ }
29
+ /**
30
+ * Fasada transportu Redis Streams dla CommandBus
31
+ *
32
+ * Kompozycja 4 komponentów z jasno rozdzielonymi odpowiedzialnościami:
33
+ * - StreamProducer: enqueue / enqueueBatch (XADD)
34
+ * - StreamConsumer: consume / consumerLoop / processMessage
35
+ * - RpcHandler: rpcCall / rpcRespond (LPUSH/BRPOP)
36
+ * - PendingRecovery: XPENDING / XCLAIM / dead letter
37
+ *
38
+ * Zachowuje publiczne API ITransport — zero zmian dla CommandBus
39
+ */
40
+ export default class RedisStreamsTransport implements ITransport {
41
+ private readonly pool;
42
+ private readonly rpcPool;
43
+ private readonly logger;
44
+ /** Komponenty fasady */
45
+ private readonly producer;
46
+ private readonly consumer;
47
+ private readonly rpc;
48
+ private readonly recovery;
49
+ /** Identyfikator procesu (dla consumer name) */
50
+ private readonly consumerId;
51
+ constructor(options: RedisStreamsTransportOptions);
52
+ /**
53
+ * Dodaje komendę do strumienia (fire-and-forget)
54
+ * Deleguje do StreamProducer
55
+ */
56
+ enqueue(streamName: string, data: Buffer): Promise<string>;
57
+ /**
58
+ * Dodaje wiele komend w jednym pipeline
59
+ * Deleguje do StreamProducer
60
+ */
61
+ enqueueBatch(entries: Array<{
62
+ streamName: string;
63
+ data: Buffer;
64
+ }>): Promise<string[]>;
65
+ /**
66
+ * Rejestruje konsumenta dla strumienia z consumer group
67
+ * Deleguje do StreamConsumer + uruchamia PendingRecovery
68
+ */
69
+ consume(streamName: string, groupName: string, handler: ConsumerHandler): Promise<void>;
70
+ /**
71
+ * RPC: wysyła request do strumienia i czeka na odpowiedź via BRPOP
72
+ * Deleguje do RpcHandler
73
+ */
74
+ rpcCall(commandName: string, data: Buffer, timeout: number): Promise<Buffer>;
75
+ /**
76
+ * RPC: odpowiada na request przez LPUSH + EXPIRE
77
+ * Deleguje do RpcHandler
78
+ */
79
+ rpcRespond(responseKey: string, data: Buffer, ttl: number): Promise<void>;
80
+ /**
81
+ * Zamyka transport gracefully
82
+ *
83
+ * Kolejność:
84
+ * 1. Zatrzymaj consumer.running (przerywa consumer loops)
85
+ * 2. Zatrzymaj recovery intervals
86
+ * 3. Zamknij dedykowane połączenia konsumentów (przerywa XREADGROUP BLOCK)
87
+ * 4. Czekaj na zakończenie consumer loops (active tasks kończą processMessage)
88
+ * 5. Zamknij pule połączeń
89
+ */
90
+ close(): Promise<void>;
91
+ }