pp-command-bus 1.5.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) 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 +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 +36 -0
  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 +0 -84
  78. package/dist/examples/rpc.demo.js +1 -1
  79. package/dist/examples/rpc.demo.js.map +1 -1
  80. package/dist/index.d.ts +8 -5
  81. package/dist/index.js +6 -4
  82. package/dist/index.js.map +1 -1
  83. package/dist/pp-command-bus-2.0.0.tgz +0 -0
  84. package/dist/shared/redis/connection-pool.d.ts +54 -0
  85. package/dist/shared/redis/connection-pool.js +117 -0
  86. package/dist/shared/redis/connection-pool.js.map +1 -0
  87. package/dist/shared/redis/connection-pool.spec.js +114 -0
  88. package/dist/shared/redis/connection-pool.spec.js.map +1 -0
  89. package/dist/shared/redis/index.d.ts +5 -3
  90. package/dist/shared/redis/index.js +6 -4
  91. package/dist/shared/redis/index.js.map +1 -1
  92. package/dist/shared/redis/rpc-connection-pool.d.ts +61 -0
  93. package/dist/shared/redis/rpc-connection-pool.js +154 -0
  94. package/dist/shared/redis/rpc-connection-pool.js.map +1 -0
  95. package/dist/shared/redis/rpc-connection-pool.spec.d.ts +1 -0
  96. package/dist/shared/redis/rpc-connection-pool.spec.js +173 -0
  97. package/dist/shared/redis/rpc-connection-pool.spec.js.map +1 -0
  98. package/dist/shared/types.d.ts +0 -4
  99. package/dist/shared/utils/error-utils.d.ts +8 -0
  100. package/dist/shared/utils/error-utils.js +14 -0
  101. package/dist/shared/utils/error-utils.js.map +1 -0
  102. package/package.json +12 -12
  103. package/dist/command-bus/config/auto-config-optimizer.d.ts +0 -35
  104. package/dist/command-bus/config/auto-config-optimizer.js +0 -52
  105. package/dist/command-bus/config/auto-config-optimizer.js.map +0 -1
  106. package/dist/command-bus/config/auto-config-optimizer.spec.js +0 -42
  107. package/dist/command-bus/config/auto-config-optimizer.spec.js.map +0 -1
  108. package/dist/command-bus/job/index.d.ts +0 -6
  109. package/dist/command-bus/job/index.js +0 -15
  110. package/dist/command-bus/job/index.js.map +0 -1
  111. package/dist/command-bus/job/job-options-builder.d.ts +0 -21
  112. package/dist/command-bus/job/job-options-builder.js +0 -58
  113. package/dist/command-bus/job/job-options-builder.js.map +0 -1
  114. package/dist/command-bus/job/job-options-builder.spec.js +0 -156
  115. package/dist/command-bus/job/job-options-builder.spec.js.map +0 -1
  116. package/dist/command-bus/job/job-processor.d.ts +0 -39
  117. package/dist/command-bus/job/job-processor.js +0 -203
  118. package/dist/command-bus/job/job-processor.js.map +0 -1
  119. package/dist/command-bus/job/job-processor.spec.js +0 -436
  120. package/dist/command-bus/job/job-processor.spec.js.map +0 -1
  121. package/dist/command-bus/queue/index.d.ts +0 -5
  122. package/dist/command-bus/queue/index.js +0 -13
  123. package/dist/command-bus/queue/index.js.map +0 -1
  124. package/dist/command-bus/queue/queue-manager.d.ts +0 -56
  125. package/dist/command-bus/queue/queue-manager.js +0 -163
  126. package/dist/command-bus/queue/queue-manager.js.map +0 -1
  127. package/dist/command-bus/queue/queue-manager.spec.js +0 -371
  128. package/dist/command-bus/queue/queue-manager.spec.js.map +0 -1
  129. package/dist/command-bus/rpc/index.d.ts +0 -11
  130. package/dist/command-bus/rpc/index.js +0 -19
  131. package/dist/command-bus/rpc/index.js.map +0 -1
  132. package/dist/command-bus/rpc/payload-compression.service.d.ts +0 -50
  133. package/dist/command-bus/rpc/payload-compression.service.js +0 -215
  134. package/dist/command-bus/rpc/payload-compression.service.js.map +0 -1
  135. package/dist/command-bus/rpc/payload-compression.service.spec.js +0 -376
  136. package/dist/command-bus/rpc/payload-compression.service.spec.js.map +0 -1
  137. package/dist/command-bus/rpc/rpc-coordinator.d.ts +0 -96
  138. package/dist/command-bus/rpc/rpc-coordinator.js +0 -500
  139. package/dist/command-bus/rpc/rpc-coordinator.js.map +0 -1
  140. package/dist/command-bus/rpc/rpc-coordinator.spec.js +0 -621
  141. package/dist/command-bus/rpc/rpc-coordinator.spec.js.map +0 -1
  142. package/dist/command-bus/rpc/rpc-job-cancellation.service.d.ts +0 -82
  143. package/dist/command-bus/rpc/rpc-job-cancellation.service.js +0 -180
  144. package/dist/command-bus/rpc/rpc-job-cancellation.service.js.map +0 -1
  145. package/dist/command-bus/rpc/rpc-job-cancellation.service.spec.js +0 -286
  146. package/dist/command-bus/rpc/rpc-job-cancellation.service.spec.js.map +0 -1
  147. package/dist/command-bus/worker/index.d.ts +0 -10
  148. package/dist/command-bus/worker/index.js +0 -19
  149. package/dist/command-bus/worker/index.js.map +0 -1
  150. package/dist/command-bus/worker/worker-benchmark.d.ts +0 -71
  151. package/dist/command-bus/worker/worker-benchmark.js +0 -202
  152. package/dist/command-bus/worker/worker-benchmark.js.map +0 -1
  153. package/dist/command-bus/worker/worker-benchmark.spec.js +0 -310
  154. package/dist/command-bus/worker/worker-benchmark.spec.js.map +0 -1
  155. package/dist/command-bus/worker/worker-metrics-collector.d.ts +0 -98
  156. package/dist/command-bus/worker/worker-metrics-collector.js +0 -242
  157. package/dist/command-bus/worker/worker-metrics-collector.js.map +0 -1
  158. package/dist/command-bus/worker/worker-orchestrator.d.ts +0 -70
  159. package/dist/command-bus/worker/worker-orchestrator.js +0 -339
  160. package/dist/command-bus/worker/worker-orchestrator.js.map +0 -1
  161. package/dist/command-bus/worker/worker-orchestrator.spec.js +0 -712
  162. package/dist/command-bus/worker/worker-orchestrator.spec.js.map +0 -1
  163. package/dist/examples/auto-config.demo.d.ts +0 -9
  164. package/dist/examples/auto-config.demo.js +0 -106
  165. package/dist/examples/auto-config.demo.js.map +0 -1
  166. package/dist/examples/rpc-compression.demo.d.ts +0 -5
  167. package/dist/examples/rpc-compression.demo.js +0 -358
  168. package/dist/examples/rpc-compression.demo.js.map +0 -1
  169. package/dist/examples/rpc-resilience.demo.d.ts +0 -15
  170. package/dist/examples/rpc-resilience.demo.js +0 -233
  171. package/dist/examples/rpc-resilience.demo.js.map +0 -1
  172. package/dist/pp-command-bus-1.5.0.tgz +0 -0
  173. package/dist/shared/config/base-config.d.ts +0 -54
  174. package/dist/shared/config/base-config.js +0 -114
  175. package/dist/shared/config/base-config.js.map +0 -1
  176. package/dist/shared/config/base-config.spec.js +0 -204
  177. package/dist/shared/config/base-config.spec.js.map +0 -1
  178. package/dist/shared/config/index.d.ts +0 -1
  179. package/dist/shared/config/index.js +0 -9
  180. package/dist/shared/config/index.js.map +0 -1
  181. package/dist/shared/redis/redis-connection-factory.d.ts +0 -66
  182. package/dist/shared/redis/redis-connection-factory.js +0 -113
  183. package/dist/shared/redis/redis-connection-factory.js.map +0 -1
  184. /package/dist/command-bus/{config/auto-config-optimizer.spec.d.ts → serialization/msgpack-serializer.spec.d.ts} +0 -0
  185. /package/dist/command-bus/{job/job-options-builder.spec.d.ts → transport/consumer-loop.spec.d.ts} +0 -0
  186. /package/dist/command-bus/{job/job-processor.spec.d.ts → transport/message-processor.spec.d.ts} +0 -0
  187. /package/dist/command-bus/{queue/queue-manager.spec.d.ts → transport/pending-recovery.spec.d.ts} +0 -0
  188. /package/dist/command-bus/{rpc/payload-compression.service.spec.d.ts → transport/redis-codec.spec.d.ts} +0 -0
  189. /package/dist/command-bus/{rpc/rpc-coordinator.spec.d.ts → transport/redis-streams-transport.spec.d.ts} +0 -0
  190. /package/dist/command-bus/{rpc/rpc-job-cancellation.service.spec.d.ts → transport/rpc-handler.spec.d.ts} +0 -0
  191. /package/dist/command-bus/{worker/worker-benchmark.spec.d.ts → transport/stream-consumer.spec.d.ts} +0 -0
  192. /package/dist/command-bus/{worker/worker-orchestrator.spec.d.ts → transport/stream-producer.spec.d.ts} +0 -0
  193. /package/dist/shared/{config/base-config.spec.d.ts → redis/connection-pool.spec.d.ts} +0 -0
@@ -0,0 +1,134 @@
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 crypto_1 = require("crypto");
13
+ const stream_producer_1 = require("./stream-producer");
14
+ const stream_consumer_1 = require("./stream-consumer");
15
+ const rpc_handler_1 = require("./rpc-handler");
16
+ const pending_recovery_1 = require("./pending-recovery");
17
+ /**
18
+ * Fasada transportu Redis Streams dla CommandBus
19
+ *
20
+ * Kompozycja 4 komponentów z jasno rozdzielonymi odpowiedzialnościami:
21
+ * - StreamProducer: enqueue / enqueueBatch (XADD)
22
+ * - StreamConsumer: consume / consumerLoop / processMessage
23
+ * - RpcHandler: rpcCall / rpcRespond (LPUSH/BRPOP)
24
+ * - PendingRecovery: XPENDING / XCLAIM / dead letter
25
+ *
26
+ * Zachowuje publiczne API ITransport — zero zmian dla CommandBus
27
+ */
28
+ class RedisStreamsTransport {
29
+ constructor(options) {
30
+ this.pool = options.pool;
31
+ this.rpcPool = options.rpcPool;
32
+ this.logger = options.logger;
33
+ this.consumerId = `consumer-${process.pid}-${(0, crypto_1.randomUUID)().slice(0, 8)}`;
34
+ // Inicjalizacja komponentów
35
+ this.producer = new stream_producer_1.StreamProducer(options.pool);
36
+ this.rpc = new rpc_handler_1.RpcHandler(options.pool, options.rpcPool, options.serializer);
37
+ this.consumer = new stream_consumer_1.StreamConsumer({
38
+ pool: options.pool,
39
+ serializer: options.serializer,
40
+ logger: options.logger,
41
+ consumerId: this.consumerId,
42
+ batchSize: options.batchSize,
43
+ concurrency: options.concurrency,
44
+ maxRetained: options.maxRetained,
45
+ rpcRespond: this.rpc.rpcRespond.bind(this.rpc),
46
+ });
47
+ this.recovery = new pending_recovery_1.PendingRecovery({
48
+ pool: options.pool,
49
+ logger: options.logger,
50
+ consumerId: this.consumerId,
51
+ maxAttempts: options.maxAttempts,
52
+ claimTimeout: options.claimTimeout,
53
+ });
54
+ }
55
+ /**
56
+ * Dodaje komendę do strumienia (fire-and-forget)
57
+ * Deleguje do StreamProducer
58
+ */
59
+ enqueue(streamName, data) {
60
+ return __awaiter(this, void 0, void 0, function* () {
61
+ return this.producer.enqueue(streamName, data);
62
+ });
63
+ }
64
+ /**
65
+ * Dodaje wiele komend w jednym pipeline
66
+ * Deleguje do StreamProducer
67
+ */
68
+ enqueueBatch(entries) {
69
+ return __awaiter(this, void 0, void 0, function* () {
70
+ return this.producer.enqueueBatch(entries);
71
+ });
72
+ }
73
+ /**
74
+ * Rejestruje konsumenta dla strumienia z consumer group
75
+ * Deleguje do StreamConsumer + uruchamia PendingRecovery
76
+ */
77
+ consume(streamName, groupName, handler) {
78
+ return __awaiter(this, void 0, void 0, function* () {
79
+ yield this.consumer.consume(streamName, groupName, handler);
80
+ // Uruchom recovery loop dla pending wiadomości
81
+ this.recovery.start(streamName, groupName, handler, this.consumer);
82
+ });
83
+ }
84
+ /**
85
+ * RPC: wysyła request do strumienia i czeka na odpowiedź via BRPOP
86
+ * Deleguje do RpcHandler
87
+ */
88
+ rpcCall(commandName, data, timeout) {
89
+ return __awaiter(this, void 0, void 0, function* () {
90
+ return this.rpc.rpcCall(commandName, data, timeout);
91
+ });
92
+ }
93
+ /**
94
+ * RPC: odpowiada na request przez LPUSH + EXPIRE
95
+ * Deleguje do RpcHandler
96
+ */
97
+ rpcRespond(responseKey, data, ttl) {
98
+ return __awaiter(this, void 0, void 0, function* () {
99
+ return this.rpc.rpcRespond(responseKey, data, ttl);
100
+ });
101
+ }
102
+ /**
103
+ * Zamyka transport gracefully
104
+ *
105
+ * Kolejność:
106
+ * 1. Zatrzymaj consumer.running (przerywa consumer loops)
107
+ * 2. Zatrzymaj recovery intervals
108
+ * 3. Zamknij dedykowane połączenia konsumentów (przerywa XREADGROUP BLOCK)
109
+ * 4. Czekaj na zakończenie consumer loops (active tasks kończą processMessage)
110
+ * 5. Zamknij pule połączeń
111
+ */
112
+ close() {
113
+ return __awaiter(this, void 0, void 0, function* () {
114
+ if (!this.consumer.running)
115
+ return;
116
+ this.consumer.running = false;
117
+ this.logger.debug('Zamykanie RedisStreamsTransport', {
118
+ consumers: this.consumer.consumerCount,
119
+ timestamp: new Date().toISOString(),
120
+ });
121
+ // 1. Zatrzymaj recovery intervals
122
+ this.recovery.stop();
123
+ // 2. Zamknij dedykowane połączenia konsumentów — przerywa XREADGROUP BLOCK
124
+ this.consumer.closeConnections();
125
+ // 3. Czekaj na zakończenie consumer loops (active tasks kończą processMessage)
126
+ yield this.consumer.awaitLoops();
127
+ // 4. Zamknij pule połączeń — dopiero po zakończeniu wszystkich active tasks
128
+ yield this.pool.close();
129
+ yield this.rpcPool.close();
130
+ });
131
+ }
132
+ }
133
+ exports.default = RedisStreamsTransport;
134
+ //# sourceMappingURL=redis-streams-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis-streams-transport.js","sourceRoot":"","sources":["../../../src/command-bus/transport/redis-streams-transport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,420 @@
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 redis_streams_transport_1 = __importDefault(require("./redis-streams-transport"));
16
+ /**
17
+ * Tworzy mock Redis connection z disconnect() który przerywa blocking operations
18
+ * Symuluje prawdziwe zachowanie: disconnect() zamyka socket → XREADGROUP BLOCK rejectuje
19
+ */
20
+ const createMockConnection = () => {
21
+ /** Rejecty pending blocking operations — disconnect() je wywołuje */
22
+ const pendingRejects = [];
23
+ return {
24
+ xadd: jest.fn().mockResolvedValue('1700000000000-0'),
25
+ xreadgroup: jest.fn().mockImplementation(() => new Promise((_resolve, reject) => {
26
+ pendingRejects.push(reject);
27
+ })),
28
+ xack: jest.fn().mockResolvedValue(1),
29
+ xgroup: jest.fn().mockResolvedValue('OK'),
30
+ xpending: jest.fn().mockResolvedValue([]),
31
+ xclaim: jest.fn().mockResolvedValue([]),
32
+ xtrim: jest.fn().mockResolvedValue(0),
33
+ brpop: jest.fn().mockResolvedValue(null),
34
+ lpush: jest.fn().mockResolvedValue(1),
35
+ expire: jest.fn().mockResolvedValue(1),
36
+ del: jest.fn().mockResolvedValue(1),
37
+ quit: jest.fn().mockResolvedValue('OK'),
38
+ on: jest.fn(),
39
+ disconnect: jest.fn().mockImplementation(() => {
40
+ // Przerwij pending blocking operations — symuluje zamknięcie socketa
41
+ const disconnectError = new Error('Connection is closed.');
42
+ while (pendingRejects.length > 0) {
43
+ const reject = pendingRejects.shift();
44
+ if (reject)
45
+ reject(disconnectError);
46
+ }
47
+ }),
48
+ pipeline: jest.fn().mockReturnValue({
49
+ xadd: jest.fn().mockReturnThis(),
50
+ xack: jest.fn().mockReturnThis(),
51
+ xtrim: jest.fn().mockReturnThis(),
52
+ lpush: jest.fn().mockReturnThis(),
53
+ expire: jest.fn().mockReturnThis(),
54
+ exec: jest.fn().mockResolvedValue([
55
+ [null, '1700000000000-0'],
56
+ [null, '1700000000001-0'],
57
+ ]),
58
+ }),
59
+ };
60
+ };
61
+ const createMockPool = (conn) => ({
62
+ next: jest.fn().mockReturnValue(conn),
63
+ createDedicated: jest.fn().mockReturnValue(conn),
64
+ close: jest.fn().mockResolvedValue(undefined),
65
+ size: 4,
66
+ });
67
+ const createMockRpcPool = () => {
68
+ const rpcConn = createMockConnection();
69
+ return {
70
+ acquire: jest.fn().mockResolvedValue(rpcConn),
71
+ release: jest.fn(),
72
+ close: jest.fn().mockResolvedValue(undefined),
73
+ activeCount: 0,
74
+ waitingCount: 0,
75
+ };
76
+ };
77
+ const createMockSerializer = () => ({
78
+ serialize: jest.fn((data) => Buffer.from(JSON.stringify(data))),
79
+ deserialize: jest.fn((buf) => JSON.parse(buf.toString())),
80
+ });
81
+ const createMockLogger = () => ({
82
+ log: jest.fn(),
83
+ error: jest.fn(),
84
+ warn: jest.fn(),
85
+ debug: jest.fn(),
86
+ });
87
+ describe('RedisStreamsTransport', () => {
88
+ let transport;
89
+ let mockConn;
90
+ let mockPool;
91
+ let mockRpcPool;
92
+ let mockSerializer;
93
+ let logger;
94
+ beforeEach(() => {
95
+ jest.useFakeTimers({ legacyFakeTimers: false });
96
+ jest.clearAllMocks();
97
+ mockConn = createMockConnection();
98
+ mockPool = createMockPool(mockConn);
99
+ mockRpcPool = createMockRpcPool();
100
+ mockSerializer = createMockSerializer();
101
+ logger = createMockLogger();
102
+ transport = new redis_streams_transport_1.default({
103
+ pool: mockPool,
104
+ rpcPool: mockRpcPool,
105
+ serializer: mockSerializer,
106
+ logger,
107
+ maxRetained: 10000,
108
+ maxAttempts: 3,
109
+ claimTimeout: 30000,
110
+ batchSize: 10,
111
+ concurrency: 100,
112
+ });
113
+ });
114
+ afterEach(() => __awaiter(void 0, void 0, void 0, function* () {
115
+ yield transport.close();
116
+ jest.useRealTimers();
117
+ }));
118
+ describe('enqueue()', () => {
119
+ it('powinien wysłać dane do strumienia przez XADD', () => __awaiter(void 0, void 0, void 0, function* () {
120
+ const data = Buffer.from('test-data');
121
+ const messageId = yield transport.enqueue('cmd:TestCommand', data);
122
+ // Base64: ioredis dekoduje string responses jako UTF-8, co korumpuje surowe bajty
123
+ expect(mockConn.xadd).toHaveBeenCalledWith('cmd:TestCommand', '*', 'data', data.toString('base64'));
124
+ expect(messageId).toBe('1700000000000-0');
125
+ }));
126
+ it('powinien używać połączenia z puli (round-robin)', () => __awaiter(void 0, void 0, void 0, function* () {
127
+ yield transport.enqueue('cmd:Test', Buffer.from('data'));
128
+ expect(mockPool.next).toHaveBeenCalledTimes(1);
129
+ }));
130
+ });
131
+ describe('enqueueBatch()', () => {
132
+ it('powinien wysłać wiele komend w jednym pipeline', () => __awaiter(void 0, void 0, void 0, function* () {
133
+ const entries = [
134
+ { streamName: 'cmd:A', data: Buffer.from('data-a') },
135
+ { streamName: 'cmd:B', data: Buffer.from('data-b') },
136
+ ];
137
+ const ids = yield transport.enqueueBatch(entries);
138
+ expect(mockPool.next).toHaveBeenCalled();
139
+ expect(ids).toHaveLength(2);
140
+ }));
141
+ it('powinien zwrócić pustą tablicę dla pustego wejścia', () => __awaiter(void 0, void 0, void 0, function* () {
142
+ const ids = yield transport.enqueueBatch([]);
143
+ expect(ids).toEqual([]);
144
+ }));
145
+ });
146
+ describe('consume()', () => {
147
+ it('powinien utworzyć consumer group i rozpocząć nasłuchiwanie', () => __awaiter(void 0, void 0, void 0, function* () {
148
+ jest.useRealTimers(); // Potrzebujemy real timers dla setTimeout
149
+ const handler = jest.fn().mockResolvedValue(undefined);
150
+ // Mockujemy XREADGROUP:
151
+ // 1. Pierwsza wiadomość — dane do przetworzenia
152
+ // 2. Potem blocking promise (symuluje BLOCK 5000)
153
+ const consumerConn = createMockConnection();
154
+ // Dane w strumieniu są base64-encoded (jak w prawdziwym Redis)
155
+ const testPayload = Buffer.from('test-payload').toString('base64');
156
+ consumerConn.xreadgroup.mockResolvedValueOnce([
157
+ ['cmd:TestCommand', [['1700000000000-0', ['data', testPayload]]]],
158
+ ]);
159
+ mockPool.createDedicated.mockReturnValue(consumerConn);
160
+ yield transport.consume('cmd:TestCommand', 'workers', handler);
161
+ // Poczekaj na przetworzenie wiadomości
162
+ yield new Promise((r) => setTimeout(r, 50));
163
+ // Powinien utworzyć consumer group
164
+ expect(consumerConn.xgroup).toHaveBeenCalledWith('CREATE', 'cmd:TestCommand', 'workers', '0', 'MKSTREAM');
165
+ // Powinien wywołać handler z danymi
166
+ expect(handler).toHaveBeenCalledTimes(1);
167
+ expect(handler).toHaveBeenCalledWith(expect.any(Buffer));
168
+ // XACK idzie przez pool connection (nie dedykowane consumer conn — XREADGROUP BLOCK)
169
+ expect(mockConn.xack).toHaveBeenCalledWith('cmd:TestCommand', 'workers', '1700000000000-0');
170
+ }));
171
+ it('powinien obsłużyć błąd tworzenia grupy jeśli już istnieje', () => __awaiter(void 0, void 0, void 0, function* () {
172
+ const handler = jest.fn().mockResolvedValue(undefined);
173
+ const consumerConn = createMockConnection();
174
+ consumerConn.xgroup.mockRejectedValueOnce(new Error('BUSYGROUP Consumer Group name already exists'));
175
+ mockPool.createDedicated.mockReturnValue(consumerConn);
176
+ // Nie powinien rzucić błędu
177
+ yield transport.consume('cmd:Test', 'workers', handler);
178
+ }));
179
+ });
180
+ describe('rpcCall()', () => {
181
+ it('powinien wysłać komendę i czekać na odpowiedź przez BRPOP', () => __awaiter(void 0, void 0, void 0, function* () {
182
+ const responseData = Buffer.from(JSON.stringify({ result: 42 }));
183
+ const rpcConn = createMockConnection();
184
+ // BRPOP zwraca base64-encoded string (rpcRespond koduje dane jako base64)
185
+ rpcConn.brpop.mockResolvedValue(['rpc:res:test-id', responseData.toString('base64')]);
186
+ mockRpcPool.acquire.mockResolvedValue(rpcConn);
187
+ const result = yield transport.rpcCall('TestCommand', Buffer.from('request-data'), 5000);
188
+ // Powinien wysłać komendę do strumienia
189
+ expect(mockConn.xadd).toHaveBeenCalled();
190
+ // Powinien pobrać połączenie z RPC pool
191
+ expect(mockRpcPool.acquire).toHaveBeenCalled();
192
+ // Powinien czekać na odpowiedź przez BRPOP
193
+ expect(rpcConn.brpop).toHaveBeenCalled();
194
+ // Powinien zwolnić połączenie po zakończeniu
195
+ expect(mockRpcPool.release).toHaveBeenCalledWith(rpcConn);
196
+ expect(result).toBeInstanceOf(Buffer);
197
+ }));
198
+ it('powinien rzucić błąd przy timeout (BRPOP zwraca null)', () => __awaiter(void 0, void 0, void 0, function* () {
199
+ const rpcConn = createMockConnection();
200
+ rpcConn.brpop.mockResolvedValue(null);
201
+ mockRpcPool.acquire.mockResolvedValue(rpcConn);
202
+ yield expect(transport.rpcCall('TestCommand', Buffer.from('data'), 1000)).rejects.toThrow('RPC timeout');
203
+ // Powinien zwolnić połączenie nawet przy błędzie
204
+ expect(mockRpcPool.release).toHaveBeenCalledWith(rpcConn);
205
+ }));
206
+ });
207
+ describe('rpcRespond()', () => {
208
+ it('powinien wysłać odpowiedź przez pipeline LPUSH + EXPIRE', () => __awaiter(void 0, void 0, void 0, function* () {
209
+ const responseData = Buffer.from('response');
210
+ yield transport.rpcRespond('rpc:res:test-id', responseData, 60);
211
+ // Powinien użyć pipeline
212
+ expect(mockConn.pipeline).toHaveBeenCalled();
213
+ }));
214
+ });
215
+ describe('XTRIM throttling (H1+H2)', () => {
216
+ it('powinien wykonać XTRIM co batchSize wiadomości', () => __awaiter(void 0, void 0, void 0, function* () {
217
+ jest.useRealTimers();
218
+ const handler = jest.fn().mockResolvedValue(undefined);
219
+ const consumerConn = createMockConnection();
220
+ // Symuluj 10 wiadomości (batchSize = 10)
221
+ const testPayload = Buffer.from('payload').toString('base64');
222
+ const messages = Array.from({ length: 10 }, (_, i) => [
223
+ `170000000000${i}-0`,
224
+ ['data', testPayload],
225
+ ]);
226
+ consumerConn.xreadgroup.mockResolvedValueOnce([['cmd:Test', messages]]);
227
+ mockPool.createDedicated.mockReturnValue(consumerConn);
228
+ yield transport.consume('cmd:Test', 'workers', handler);
229
+ // Poczekaj na przetworzenie
230
+ yield new Promise((r) => setTimeout(r, 100));
231
+ // Pipeline powinien być użyty dokładnie raz (10. wiadomość = batchSize)
232
+ // Wiadomości 1-9: sam XACK, wiadomość 10: pipeline XACK+XTRIM
233
+ const pipelineCalls = mockConn.pipeline.mock.calls.length;
234
+ expect(pipelineCalls).toBeGreaterThanOrEqual(1);
235
+ // XTRIM NIE powinien być wywołany bezpośrednio (fire-and-forget usunięty)
236
+ expect(mockConn.xtrim).not.toHaveBeenCalled();
237
+ }));
238
+ });
239
+ describe('RPC marker field (H3)', () => {
240
+ it('powinien dodać marker rpc do XADD dla RPC', () => __awaiter(void 0, void 0, void 0, function* () {
241
+ const rpcConn = createMockConnection();
242
+ const responseData = Buffer.from(JSON.stringify({ result: 42 }));
243
+ rpcConn.brpop.mockResolvedValue(['rpc:res:test-id', responseData.toString('base64')]);
244
+ mockRpcPool.acquire.mockResolvedValue(rpcConn);
245
+ yield transport.rpcCall('TestCommand', Buffer.from('request-data'), 5000);
246
+ // XADD powinien mieć 6 argumentów: streamName, *, 'data', value, 'rpc', '1'
247
+ const xaddCall = mockConn.xadd.mock.calls[0];
248
+ expect(xaddCall).toContain('rpc');
249
+ expect(xaddCall).toContain('1');
250
+ }));
251
+ it('powinien użyć markera rpc do identyfikacji RPC envelope', () => __awaiter(void 0, void 0, void 0, function* () {
252
+ jest.useRealTimers();
253
+ const handler = jest.fn().mockResolvedValue('rpc-result');
254
+ const consumerConn = createMockConnection();
255
+ // Symuluj RPC wiadomość z markerem
256
+ const envelope = {
257
+ commandData: Buffer.from('cmd-data').toString('base64'),
258
+ rpc: { correlationId: 'test', responseKey: 'rpc:res:test' },
259
+ };
260
+ const envelopePayload = Buffer.from(JSON.stringify(envelope)).toString('base64');
261
+ consumerConn.xreadgroup.mockResolvedValueOnce([
262
+ ['cmd:Test', [['msg-rpc', ['data', envelopePayload, 'rpc', '1']]]],
263
+ ]);
264
+ mockPool.createDedicated.mockReturnValue(consumerConn);
265
+ yield transport.consume('cmd:Test', 'workers', handler);
266
+ yield new Promise((r) => setTimeout(r, 50));
267
+ // Handler powinien być wywołany
268
+ expect(handler).toHaveBeenCalledTimes(1);
269
+ }));
270
+ it('powinien obsługiwać zwykłe komendy bez markera', () => __awaiter(void 0, void 0, void 0, function* () {
271
+ jest.useRealTimers();
272
+ const handler = jest.fn().mockResolvedValue(undefined);
273
+ const consumerConn = createMockConnection();
274
+ // Zwykła komenda — bez markera 'rpc'
275
+ const testPayload = Buffer.from('normal-command').toString('base64');
276
+ consumerConn.xreadgroup.mockResolvedValueOnce([
277
+ ['cmd:Test', [['msg-normal', ['data', testPayload]]]],
278
+ ]);
279
+ mockPool.createDedicated.mockReturnValue(consumerConn);
280
+ yield transport.consume('cmd:Test', 'workers', handler);
281
+ yield new Promise((r) => setTimeout(r, 50));
282
+ // Handler powinien być wywołany z surowymi danymi (nie RPC)
283
+ expect(handler).toHaveBeenCalledTimes(1);
284
+ expect(handler).toHaveBeenCalledWith(expect.any(Buffer));
285
+ }));
286
+ });
287
+ describe('close()', () => {
288
+ it('powinien zamknąć transport gracefully', () => __awaiter(void 0, void 0, void 0, function* () {
289
+ yield transport.close();
290
+ expect(mockPool.close).toHaveBeenCalled();
291
+ expect(mockRpcPool.close).toHaveBeenCalled();
292
+ }));
293
+ it('powinien być idempotentny (drugie close nie rzuca)', () => __awaiter(void 0, void 0, void 0, function* () {
294
+ yield transport.close();
295
+ yield transport.close();
296
+ }));
297
+ it('powinien czekać na zakończenie aktywnych processMessage przed zamknięciem puli', () => __awaiter(void 0, void 0, void 0, function* () {
298
+ jest.useRealTimers();
299
+ // Przygotuj consumer z wolnym handlerem
300
+ let handlerResolve;
301
+ const handlerPromise = new Promise((resolve) => {
302
+ handlerResolve = resolve;
303
+ });
304
+ const handler = jest.fn().mockReturnValue(handlerPromise);
305
+ const consumerConn = createMockConnection();
306
+ const testPayload = Buffer.from('test-payload').toString('base64');
307
+ // Pierwsza wiadomość → przetworzenie, kolejne → domyślne interruptible blocking
308
+ consumerConn.xreadgroup.mockResolvedValueOnce([
309
+ ['cmd:Test', [['1700000000000-0', ['data', testPayload]]]],
310
+ ]);
311
+ mockPool.createDedicated.mockReturnValue(consumerConn);
312
+ yield transport.consume('cmd:Test', 'workers', handler);
313
+ // Poczekaj na start przetwarzania
314
+ yield new Promise((r) => setTimeout(r, 50));
315
+ expect(handler).toHaveBeenCalledTimes(1);
316
+ // Zamknij transport — close powinno czekać na handler
317
+ const closePromise = transport.close();
318
+ // Handler jeszcze pracuje — pool.close() jeszcze nie powinien być wywołany
319
+ yield new Promise((r) => setTimeout(r, 20));
320
+ // Zakończ handler
321
+ handlerResolve();
322
+ yield closePromise;
323
+ // Pool zamknięty dopiero po zakończeniu handlera
324
+ expect(mockPool.close).toHaveBeenCalled();
325
+ }));
326
+ });
327
+ describe('recoverPending()', () => {
328
+ /**
329
+ * Pomocnik — wyciąga wewnętrzne komponenty fasady do testowania recovery
330
+ * Po refaktorze SRP: recoverPending jest w PendingRecovery, processMessage w StreamConsumer
331
+ */
332
+ const getInternals = (t) => {
333
+ const any = t;
334
+ return {
335
+ recovery: any['recovery'],
336
+ consumer: any['consumer'],
337
+ };
338
+ };
339
+ it('powinien przetworzyć wiadomość po XCLAIM', () => __awaiter(void 0, void 0, void 0, function* () {
340
+ jest.useRealTimers();
341
+ const handler = jest.fn().mockResolvedValue('ok');
342
+ const consumerConn = createMockConnection();
343
+ mockPool.createDedicated.mockReturnValue(consumerConn);
344
+ // Symuluj XPENDING z 1 stalled wiadomością
345
+ const testPayload = Buffer.from('recovered-data').toString('base64');
346
+ mockConn.xpending.mockResolvedValue([['msg-1', 'consumer-old', 60000, 1]]);
347
+ // XCLAIM zwraca dane wiadomości
348
+ mockConn.xclaim.mockResolvedValue([['msg-1', ['data', testPayload]]]);
349
+ yield transport.consume('cmd:Test', 'workers', handler);
350
+ // Wywołujemy recoverPending bezpośrednio przez wewnętrzny komponent recovery
351
+ const { recovery, consumer } = getInternals(transport);
352
+ yield recovery['recoverPending']('cmd:Test', 'workers', handler, consumer);
353
+ // Poczekaj na przetworzenie
354
+ yield new Promise((r) => setTimeout(r, 50));
355
+ // Handler powinien być wywołany z recovered danymi
356
+ expect(handler).toHaveBeenCalledWith(expect.any(Buffer));
357
+ // XACK powinno być wywołane
358
+ expect(mockConn.xack).toHaveBeenCalledWith('cmd:Test', 'workers', 'msg-1');
359
+ }));
360
+ it('powinien przenieść do DLQ po maxAttempts (D3)', () => __awaiter(void 0, void 0, void 0, function* () {
361
+ jest.useRealTimers();
362
+ const handler = jest.fn().mockResolvedValue('ok');
363
+ const consumerConn = createMockConnection();
364
+ mockPool.createDedicated.mockReturnValue(consumerConn);
365
+ const testPayload = Buffer.from('dead-data').toString('base64');
366
+ // Wiadomość z deliveryCount >= maxAttempts (3)
367
+ mockConn.xpending.mockResolvedValue([['msg-dead', 'consumer-old', 60000, 3]]);
368
+ // D3: XCLAIM teraz jest wywoływany żeby pobrać dane do DLQ
369
+ mockConn.xclaim.mockResolvedValue([['msg-dead', ['data', testPayload]]]);
370
+ yield transport.consume('cmd:Test', 'workers', handler);
371
+ const { recovery, consumer } = getInternals(transport);
372
+ yield recovery['recoverPending']('cmd:Test', 'workers', handler, consumer);
373
+ // XCLAIM powinno być wywołane (pobiera dane do DLQ)
374
+ expect(mockConn.xclaim).toHaveBeenCalled();
375
+ // XADD do DLQ strumienia
376
+ expect(mockConn.xadd).toHaveBeenCalledWith('dlq:cmd:Test', '*', 'data', testPayload, 'original_stream', 'cmd:Test', 'delivery_count', '3');
377
+ // XACK po przeniesieniu do DLQ
378
+ expect(mockConn.xack).toHaveBeenCalledWith('cmd:Test', 'workers', 'msg-dead');
379
+ // Handler NIE powinien być wywołany
380
+ expect(handler).not.toHaveBeenCalled();
381
+ // Powinien zalogować
382
+ expect(logger.error).toHaveBeenCalledWith('Wiadomość przeniesiona do Dead Letter Queue', expect.objectContaining({
383
+ messageId: 'msg-dead',
384
+ dlqStream: 'dlq:cmd:Test',
385
+ deliveryCount: 3,
386
+ }));
387
+ }));
388
+ it('nie powinien duplikować gdy wiadomość jest już przetwarzana', () => __awaiter(void 0, void 0, void 0, function* () {
389
+ jest.useRealTimers();
390
+ // Handler który trwa długo
391
+ let handlerCallCount = 0;
392
+ const handler = jest.fn().mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () {
393
+ handlerCallCount++;
394
+ yield new Promise((r) => setTimeout(r, 100));
395
+ return 'ok';
396
+ }));
397
+ const consumerConn = createMockConnection();
398
+ const testPayload = Buffer.from('dedup-data').toString('base64');
399
+ // Consumer loop dostaje wiadomość — po niej domyślne interruptible blocking
400
+ consumerConn.xreadgroup.mockResolvedValueOnce([
401
+ ['cmd:Test', [['msg-dedup', ['data', testPayload]]]],
402
+ ]);
403
+ mockPool.createDedicated.mockReturnValue(consumerConn);
404
+ // XCLAIM też zwraca tę samą wiadomość
405
+ mockConn.xpending.mockResolvedValue([['msg-dedup', 'consumer-old', 60000, 1]]);
406
+ mockConn.xclaim.mockResolvedValue([['msg-dedup', ['data', testPayload]]]);
407
+ yield transport.consume('cmd:Test', 'workers', handler);
408
+ // Poczekaj aż consumer loop zacznie przetwarzać
409
+ yield new Promise((r) => setTimeout(r, 30));
410
+ // Recovery próbuje XCLAIM tej samej wiadomości — przez wewnętrzny komponent
411
+ const { recovery, consumer } = getInternals(transport);
412
+ yield recovery['recoverPending']('cmd:Test', 'workers', handler, consumer);
413
+ // Poczekaj na zakończenie
414
+ yield new Promise((r) => setTimeout(r, 200));
415
+ // Handler powinien być wywołany tylko RAZ (deduplicacja)
416
+ expect(handlerCallCount).toBe(1);
417
+ }));
418
+ });
419
+ });
420
+ //# sourceMappingURL=redis-streams-transport.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis-streams-transport.spec.js","sourceRoot":"","sources":["../../../src/command-bus/transport/redis-streams-transport.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import type { ISerializer } from '../serialization/serializer.interface';
2
+ import type { IRpcTransport, RpcMessageMetadata } from './transport.interface';
3
+ import type RedisConnectionPool from '../../shared/redis/connection-pool';
4
+ import type RpcConnectionPool from '../../shared/redis/rpc-connection-pool';
5
+ /**
6
+ * Dane envelope dla RPC — wiadomość w strumieniu zawiera zarówno
7
+ * dane komendy jak i metadane RPC do routingu odpowiedzi
8
+ */
9
+ export interface RpcEnvelope {
10
+ /** Surowe dane komendy zakodowane jako base64 string */
11
+ commandData: string;
12
+ /** Metadane RPC */
13
+ rpc: RpcMessageMetadata;
14
+ }
15
+ /**
16
+ * Handler RPC — odpowiada za request/response przez Redis Streams + LPUSH/BRPOP
17
+ * Jedna odpowiedzialność: RPC call i respond
18
+ */
19
+ export declare class RpcHandler implements IRpcTransport {
20
+ private readonly pool;
21
+ private readonly rpcPool;
22
+ private readonly serializer;
23
+ constructor(pool: RedisConnectionPool, rpcPool: RpcConnectionPool, serializer: ISerializer);
24
+ /**
25
+ * RPC: wysyła request do strumienia i czeka na odpowiedź via BRPOP
26
+ *
27
+ * Flow (4 komendy Redis):
28
+ * 1. XADD — komenda z metadanymi RPC do strumienia
29
+ * 2. BRPOP — czekaj na odpowiedź na dedykowanym połączeniu
30
+ * 3. Worker: LPUSH — odpowiedź na klucz
31
+ * 4. DEL — cleanup klucza (TTL safety net)
32
+ */
33
+ rpcCall(commandName: string, data: Buffer, timeout: number): Promise<Buffer>;
34
+ /**
35
+ * RPC: odpowiada na request przez LPUSH + EXPIRE w jednym pipeline
36
+ * Wywoływane przez worker po przetworzeniu komendy RPC
37
+ */
38
+ rpcRespond(responseKey: string, data: Buffer, ttl: number): Promise<void>;
39
+ }