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,54 @@
1
+ import { Redis, type RedisOptions } from 'ioredis';
2
+ import type { ILogger } from '../types';
3
+ /**
4
+ * Opcje konfiguracji puli połączeń Redis
5
+ */
6
+ export interface ConnectionPoolOptions {
7
+ /** Opcje połączenia ioredis */
8
+ redisOptions: RedisOptions;
9
+ /** Rozmiar puli (domyślnie 2 * CPU count) */
10
+ size: number;
11
+ /** Logger */
12
+ logger: ILogger;
13
+ }
14
+ /**
15
+ * Pula połączeń Redis z round-robin dla operacji nieblokujących
16
+ *
17
+ * Przeznaczona dla komend takich jak XADD, XACK, DEL, pipeline
18
+ * które nie blokują połączenia. Połączenia tworzone eagerly przy starcie.
19
+ *
20
+ * DragonflyDB przetwarza komendy z wielu połączeń równolegle
21
+ * na różnych wątkach, więc więcej połączeń = lepszy throughput.
22
+ */
23
+ export default class RedisConnectionPool {
24
+ private readonly options;
25
+ private readonly connections;
26
+ private index;
27
+ private closed;
28
+ constructor(options: ConnectionPoolOptions);
29
+ /**
30
+ * Zwraca następne połączenie z puli (round-robin)
31
+ * Używaj wyłącznie do operacji nieblokujących (XADD, XACK, DEL, pipeline)
32
+ */
33
+ next(): Redis;
34
+ /**
35
+ * Tworzy nowe dedykowane połączenie (np. dla XREADGROUP BLOCK)
36
+ * Połączenie NIE jest częścią puli — caller odpowiada za zamknięcie
37
+ *
38
+ * @param name - Nazwa połączenia (do logów)
39
+ * @param overrideOptions - Opcje nadpisujące bazowe (np. maxRetriesPerRequest: null)
40
+ */
41
+ createDedicated(name: string, overrideOptions?: Partial<RedisOptions>): Redis;
42
+ /**
43
+ * Zwraca rozmiar puli
44
+ */
45
+ get size(): number;
46
+ /**
47
+ * Zamyka wszystkie połączenia w puli
48
+ */
49
+ close(): Promise<void>;
50
+ /**
51
+ * Konfiguruje handlery eventów dla połączenia
52
+ */
53
+ private setupEventHandlers;
54
+ }
@@ -0,0 +1,117 @@
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 ioredis_1 = require("ioredis");
13
+ const redis_error_formatter_1 = require("./redis-error-formatter");
14
+ /**
15
+ * Pula połączeń Redis z round-robin dla operacji nieblokujących
16
+ *
17
+ * Przeznaczona dla komend takich jak XADD, XACK, DEL, pipeline
18
+ * które nie blokują połączenia. Połączenia tworzone eagerly przy starcie.
19
+ *
20
+ * DragonflyDB przetwarza komendy z wielu połączeń równolegle
21
+ * na różnych wątkach, więc więcej połączeń = lepszy throughput.
22
+ */
23
+ class RedisConnectionPool {
24
+ constructor(options) {
25
+ this.options = options;
26
+ this.index = 0;
27
+ this.closed = false;
28
+ const { size, redisOptions, logger } = options;
29
+ if (size < 1) {
30
+ throw new Error('Rozmiar puli połączeń musi wynosić co najmniej 1');
31
+ }
32
+ this.connections = Array.from({ length: size }, (_, i) => {
33
+ const conn = new ioredis_1.Redis(redisOptions);
34
+ this.setupEventHandlers(conn, `Pool[${i}]`, logger);
35
+ return conn;
36
+ });
37
+ logger.debug('Pula połączeń Redis utworzona', {
38
+ size,
39
+ timestamp: new Date().toISOString(),
40
+ });
41
+ }
42
+ /**
43
+ * Zwraca następne połączenie z puli (round-robin)
44
+ * Używaj wyłącznie do operacji nieblokujących (XADD, XACK, DEL, pipeline)
45
+ */
46
+ next() {
47
+ if (this.closed) {
48
+ throw new Error('Pula połączeń jest zamknięta');
49
+ }
50
+ const conn = this.connections[this.index];
51
+ this.index = (this.index + 1) % this.connections.length;
52
+ return conn;
53
+ }
54
+ /**
55
+ * Tworzy nowe dedykowane połączenie (np. dla XREADGROUP BLOCK)
56
+ * Połączenie NIE jest częścią puli — caller odpowiada za zamknięcie
57
+ *
58
+ * @param name - Nazwa połączenia (do logów)
59
+ * @param overrideOptions - Opcje nadpisujące bazowe (np. maxRetriesPerRequest: null)
60
+ */
61
+ createDedicated(name, overrideOptions) {
62
+ if (this.closed) {
63
+ throw new Error('Pula połączeń jest zamknięta');
64
+ }
65
+ const conn = new ioredis_1.Redis(Object.assign(Object.assign({}, this.options.redisOptions), overrideOptions));
66
+ this.setupEventHandlers(conn, `Dedicated[${name}]`, this.options.logger);
67
+ return conn;
68
+ }
69
+ /**
70
+ * Zwraca rozmiar puli
71
+ */
72
+ get size() {
73
+ return this.connections.length;
74
+ }
75
+ /**
76
+ * Zamyka wszystkie połączenia w puli
77
+ */
78
+ close() {
79
+ return __awaiter(this, void 0, void 0, function* () {
80
+ if (this.closed)
81
+ return;
82
+ this.closed = true;
83
+ this.options.logger.debug('Zamykanie puli połączeń Redis', {
84
+ size: this.connections.length,
85
+ timestamp: new Date().toISOString(),
86
+ });
87
+ yield Promise.all(this.connections.map((c) => c.quit()));
88
+ });
89
+ }
90
+ /**
91
+ * Konfiguruje handlery eventów dla połączenia
92
+ */
93
+ setupEventHandlers(connection, name, logger) {
94
+ connection.on('error', (error) => {
95
+ logger.error(`Błąd połączenia Redis (${name})`, {
96
+ connectionName: name,
97
+ error: (0, redis_error_formatter_1.formatRedisError)(error),
98
+ errorCode: (0, redis_error_formatter_1.getErrorCode)(error),
99
+ timestamp: new Date().toISOString(),
100
+ });
101
+ });
102
+ connection.on('close', () => {
103
+ logger.warn(`Połączenie Redis zamknięte (${name})`, {
104
+ connectionName: name,
105
+ timestamp: new Date().toISOString(),
106
+ });
107
+ });
108
+ connection.on('reconnecting', () => {
109
+ logger.log(`Ponowne łączenie z Redis (${name})`, {
110
+ connectionName: name,
111
+ timestamp: new Date().toISOString(),
112
+ });
113
+ });
114
+ }
115
+ }
116
+ exports.default = RedisConnectionPool;
117
+ //# sourceMappingURL=connection-pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection-pool.js","sourceRoot":"","sources":["../../../src/shared/redis/connection-pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,114 @@
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 connection_pool_1 = __importDefault(require("./connection-pool"));
16
+ // Mock ioredis
17
+ jest.mock('ioredis', () => {
18
+ const mockRedis = jest.fn().mockImplementation(() => ({
19
+ on: jest.fn(),
20
+ quit: jest.fn().mockResolvedValue('OK'),
21
+ status: 'ready',
22
+ }));
23
+ return { Redis: mockRedis };
24
+ });
25
+ const createMockLogger = () => ({
26
+ log: jest.fn(),
27
+ error: jest.fn(),
28
+ warn: jest.fn(),
29
+ debug: jest.fn(),
30
+ });
31
+ describe('RedisConnectionPool', () => {
32
+ let logger;
33
+ beforeEach(() => {
34
+ logger = createMockLogger();
35
+ jest.clearAllMocks();
36
+ });
37
+ describe('konstruktor', () => {
38
+ it('powinien utworzyć pulę z określoną liczbą połączeń', () => {
39
+ const pool = new connection_pool_1.default({
40
+ size: 4,
41
+ redisOptions: { host: 'localhost', port: 6379 },
42
+ logger,
43
+ });
44
+ expect(pool.size).toBe(4);
45
+ });
46
+ it('powinien rzucić błąd gdy rozmiar puli < 1', () => {
47
+ expect(() => new connection_pool_1.default({
48
+ size: 0,
49
+ redisOptions: { host: 'localhost', port: 6379 },
50
+ logger,
51
+ })).toThrow('Rozmiar puli połączeń musi wynosić co najmniej 1');
52
+ });
53
+ });
54
+ describe('next()', () => {
55
+ it('powinien zwracać połączenia w trybie round-robin', () => {
56
+ const pool = new connection_pool_1.default({
57
+ size: 3,
58
+ redisOptions: { host: 'localhost', port: 6379 },
59
+ logger,
60
+ });
61
+ const first = pool.next();
62
+ const second = pool.next();
63
+ const third = pool.next();
64
+ const fourth = pool.next(); // Wraca do pierwszego
65
+ expect(first).not.toBe(second);
66
+ expect(second).not.toBe(third);
67
+ expect(fourth).toBe(first); // Round-robin wraca do początku
68
+ });
69
+ it('powinien rzucić błąd po zamknięciu puli', () => __awaiter(void 0, void 0, void 0, function* () {
70
+ const pool = new connection_pool_1.default({
71
+ size: 2,
72
+ redisOptions: { host: 'localhost', port: 6379 },
73
+ logger,
74
+ });
75
+ yield pool.close();
76
+ expect(() => pool.next()).toThrow('Pula połączeń jest zamknięta');
77
+ }));
78
+ });
79
+ describe('createDedicated()', () => {
80
+ it('powinien utworzyć nowe dedykowane połączenie', () => {
81
+ const pool = new connection_pool_1.default({
82
+ size: 2,
83
+ redisOptions: { host: 'localhost', port: 6379 },
84
+ logger,
85
+ });
86
+ const dedicated = pool.createDedicated('consumer-1');
87
+ expect(dedicated).toBeDefined();
88
+ // Dedykowane połączenie nie jest częścią puli
89
+ expect(dedicated).not.toBe(pool.next());
90
+ });
91
+ it('powinien rzucić błąd po zamknięciu puli', () => __awaiter(void 0, void 0, void 0, function* () {
92
+ const pool = new connection_pool_1.default({
93
+ size: 2,
94
+ redisOptions: { host: 'localhost', port: 6379 },
95
+ logger,
96
+ });
97
+ yield pool.close();
98
+ expect(() => pool.createDedicated('test')).toThrow('Pula połączeń jest zamknięta');
99
+ }));
100
+ });
101
+ describe('close()', () => {
102
+ it('powinien zamknąć wszystkie połączenia', () => __awaiter(void 0, void 0, void 0, function* () {
103
+ const pool = new connection_pool_1.default({
104
+ size: 3,
105
+ redisOptions: { host: 'localhost', port: 6379 },
106
+ logger,
107
+ });
108
+ yield pool.close();
109
+ // Drugie close nie powinno rzucić błędu (idempotentność)
110
+ yield pool.close();
111
+ }));
112
+ });
113
+ });
114
+ //# sourceMappingURL=connection-pool.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection-pool.spec.js","sourceRoot":"","sources":["../../../src/shared/redis/connection-pool.spec.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
1
  /**
2
- * Moduł Redis - eksporty publiczne
2
+ * Moduł Redis eksporty publiczne
3
3
  */
4
- export { default as RedisConnectionFactory } from './redis-connection-factory';
5
- export type { RedisConnectionOptions } from './redis-connection-factory';
4
+ export { default as RedisConnectionPool } from './connection-pool';
5
+ export type { ConnectionPoolOptions } from './connection-pool';
6
+ export { default as RpcConnectionPool } from './rpc-connection-pool';
7
+ export type { RpcConnectionPoolOptions } from './rpc-connection-pool';
6
8
  export { formatRedisError, getErrorCode } from './redis-error-formatter';
@@ -1,14 +1,16 @@
1
1
  "use strict";
2
2
  /**
3
- * Moduł Redis - eksporty publiczne
3
+ * Moduł Redis eksporty publiczne
4
4
  */
5
5
  var __importDefault = (this && this.__importDefault) || function (mod) {
6
6
  return (mod && mod.__esModule) ? mod : { "default": mod };
7
7
  };
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.getErrorCode = exports.formatRedisError = exports.RedisConnectionFactory = void 0;
10
- var redis_connection_factory_1 = require("./redis-connection-factory");
11
- Object.defineProperty(exports, "RedisConnectionFactory", { enumerable: true, get: function () { return __importDefault(redis_connection_factory_1).default; } });
9
+ exports.getErrorCode = exports.formatRedisError = exports.RpcConnectionPool = exports.RedisConnectionPool = void 0;
10
+ var connection_pool_1 = require("./connection-pool");
11
+ Object.defineProperty(exports, "RedisConnectionPool", { enumerable: true, get: function () { return __importDefault(connection_pool_1).default; } });
12
+ var rpc_connection_pool_1 = require("./rpc-connection-pool");
13
+ Object.defineProperty(exports, "RpcConnectionPool", { enumerable: true, get: function () { return __importDefault(rpc_connection_pool_1).default; } });
12
14
  var redis_error_formatter_1 = require("./redis-error-formatter");
13
15
  Object.defineProperty(exports, "formatRedisError", { enumerable: true, get: function () { return redis_error_formatter_1.formatRedisError; } });
14
16
  Object.defineProperty(exports, "getErrorCode", { enumerable: true, get: function () { return redis_error_formatter_1.getErrorCode; } });
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/shared/redis/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;AAEH,uEAA+E;AAAtE,mJAAA,OAAO,OAA0B;AAE1C,iEAAyE;AAAhE,yHAAA,gBAAgB,OAAA;AAAE,qHAAA,YAAY,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/shared/redis/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;AAEH,qDAAmE;AAA1D,uIAAA,OAAO,OAAuB;AAEvC,6DAAqE;AAA5D,yIAAA,OAAO,OAAqB;AAErC,iEAAyE;AAAhE,yHAAA,gBAAgB,OAAA;AAAE,qHAAA,YAAY,OAAA"}
@@ -0,0 +1,61 @@
1
+ import { Redis, type RedisOptions } from 'ioredis';
2
+ import type { ILogger } from '../types';
3
+ /**
4
+ * Opcje konfiguracji puli RPC połączeń
5
+ */
6
+ export interface RpcConnectionPoolOptions {
7
+ /** Opcje połączenia ioredis */
8
+ redisOptions: RedisOptions;
9
+ /** Maksymalna liczba równoległych połączeń (domyślnie 50) */
10
+ maxSize: number;
11
+ /** Logger */
12
+ logger: ILogger;
13
+ }
14
+ /**
15
+ * Bounded, lazy pula połączeń dla operacji blokujących (BRPOP)
16
+ *
17
+ * Każde aktywne wywołanie RPC potrzebuje dedykowanego połączenia,
18
+ * ponieważ BRPOP blokuje cały socket do momentu odpowiedzi lub timeout.
19
+ *
20
+ * Połączenia tworzone leniwie przy acquire() i reużywane po release().
21
+ * Jeśli limit osiągnięty — caller czeka na wolne połączenie.
22
+ *
23
+ * DragonflyDB obsługuje tysiące połączeń efektywnie (multi-threaded),
24
+ * więc 50 concurrent BRPOP = ~100KB pamięci + 50 TCP socketów.
25
+ */
26
+ export default class RpcConnectionPool {
27
+ private readonly options;
28
+ private readonly available;
29
+ private active;
30
+ private readonly waiting;
31
+ /** Wypożyczone połączenia — śledzone do zamknięcia w close() */
32
+ private readonly borrowed;
33
+ private closed;
34
+ constructor(options: RpcConnectionPoolOptions);
35
+ /**
36
+ * Pobiera połączenie z puli (lazy init, czeka jeśli limit osiągnięty)
37
+ * Caller MUSI wywołać release() po zakończeniu BRPOP
38
+ */
39
+ acquire(): Promise<Redis>;
40
+ /**
41
+ * Zwraca połączenie do puli
42
+ * Jeśli ktoś czeka — oddaje mu połączenie bez odkładania do available
43
+ */
44
+ release(conn: Redis): void;
45
+ /**
46
+ * Zwraca liczbę aktywnych (wypożyczonych) połączeń
47
+ */
48
+ get activeCount(): number;
49
+ /**
50
+ * Zwraca liczbę czekających na połączenie
51
+ */
52
+ get waitingCount(): number;
53
+ /**
54
+ * Zamyka wszystkie połączenia w puli
55
+ */
56
+ close(): Promise<void>;
57
+ /**
58
+ * Konfiguruje handlery eventów dla połączenia
59
+ */
60
+ private setupEventHandlers;
61
+ }
@@ -0,0 +1,154 @@
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 ioredis_1 = require("ioredis");
13
+ const redis_error_formatter_1 = require("./redis-error-formatter");
14
+ /**
15
+ * Bounded, lazy pula połączeń dla operacji blokujących (BRPOP)
16
+ *
17
+ * Każde aktywne wywołanie RPC potrzebuje dedykowanego połączenia,
18
+ * ponieważ BRPOP blokuje cały socket do momentu odpowiedzi lub timeout.
19
+ *
20
+ * Połączenia tworzone leniwie przy acquire() i reużywane po release().
21
+ * Jeśli limit osiągnięty — caller czeka na wolne połączenie.
22
+ *
23
+ * DragonflyDB obsługuje tysiące połączeń efektywnie (multi-threaded),
24
+ * więc 50 concurrent BRPOP = ~100KB pamięci + 50 TCP socketów.
25
+ */
26
+ class RpcConnectionPool {
27
+ constructor(options) {
28
+ this.options = options;
29
+ this.available = [];
30
+ this.active = 0;
31
+ this.waiting = [];
32
+ /** Wypożyczone połączenia — śledzone do zamknięcia w close() */
33
+ this.borrowed = new Set();
34
+ this.closed = false;
35
+ if (options.maxSize < 1) {
36
+ throw new Error('Maksymalny rozmiar puli RPC musi wynosić co najmniej 1');
37
+ }
38
+ options.logger.debug('Pula połączeń RPC utworzona', {
39
+ maxSize: options.maxSize,
40
+ timestamp: new Date().toISOString(),
41
+ });
42
+ }
43
+ /**
44
+ * Pobiera połączenie z puli (lazy init, czeka jeśli limit osiągnięty)
45
+ * Caller MUSI wywołać release() po zakończeniu BRPOP
46
+ */
47
+ acquire() {
48
+ return __awaiter(this, void 0, void 0, function* () {
49
+ if (this.closed) {
50
+ throw new Error('Pula połączeń RPC jest zamknięta');
51
+ }
52
+ // Spróbuj użyć wolnego połączenia
53
+ const free = this.available.pop();
54
+ if (free) {
55
+ this.active++;
56
+ this.borrowed.add(free);
57
+ return free;
58
+ }
59
+ // Stwórz nowe jeśli limit nie osiągnięty
60
+ if (this.active < this.options.maxSize) {
61
+ this.active++;
62
+ const conn = new ioredis_1.Redis(Object.assign(Object.assign({}, this.options.redisOptions), { maxRetriesPerRequest: null }));
63
+ this.setupEventHandlers(conn, `RpcPool[${this.active}]`);
64
+ this.borrowed.add(conn);
65
+ return conn;
66
+ }
67
+ // Limit osiągnięty — czekaj na release
68
+ return new Promise((resolve, reject) => {
69
+ this.waiting.push({ resolve, reject });
70
+ });
71
+ });
72
+ }
73
+ /**
74
+ * Zwraca połączenie do puli
75
+ * Jeśli ktoś czeka — oddaje mu połączenie bez odkładania do available
76
+ */
77
+ release(conn) {
78
+ this.active--;
79
+ this.borrowed.delete(conn);
80
+ // Jeśli pula zamknięta — zamknij zwrócone połączenie zamiast odkładać do available
81
+ if (this.closed) {
82
+ conn.disconnect();
83
+ return;
84
+ }
85
+ const next = this.waiting.shift();
86
+ if (next) {
87
+ this.active++;
88
+ this.borrowed.add(conn);
89
+ next.resolve(conn);
90
+ return;
91
+ }
92
+ this.available.push(conn);
93
+ }
94
+ /**
95
+ * Zwraca liczbę aktywnych (wypożyczonych) połączeń
96
+ */
97
+ get activeCount() {
98
+ return this.active;
99
+ }
100
+ /**
101
+ * Zwraca liczbę czekających na połączenie
102
+ */
103
+ get waitingCount() {
104
+ return this.waiting.length;
105
+ }
106
+ /**
107
+ * Zamyka wszystkie połączenia w puli
108
+ */
109
+ close() {
110
+ return __awaiter(this, void 0, void 0, function* () {
111
+ if (this.closed)
112
+ return;
113
+ this.closed = true;
114
+ // Odrzuć czekających — reject ich promises żeby nie wisieli w pamięci
115
+ const closeError = new Error('Pula połączeń RPC została zamknięta');
116
+ while (this.waiting.length > 0) {
117
+ const waiter = this.waiting.shift();
118
+ if (waiter) {
119
+ waiter.reject(closeError);
120
+ }
121
+ }
122
+ this.options.logger.debug('Zamykanie puli połączeń RPC', {
123
+ available: this.available.length,
124
+ active: this.active,
125
+ borrowed: this.borrowed.size,
126
+ timestamp: new Date().toISOString(),
127
+ });
128
+ // Zamknij wolne połączenia gracefully
129
+ yield Promise.all(this.available.map((c) => c.quit()));
130
+ this.available.length = 0;
131
+ // Zamknij wypożyczone połączenia (mogą mieć blocking BRPOP) — disconnect przerywa natychmiast
132
+ for (const conn of this.borrowed) {
133
+ conn.disconnect();
134
+ }
135
+ this.borrowed.clear();
136
+ });
137
+ }
138
+ /**
139
+ * Konfiguruje handlery eventów dla połączenia
140
+ */
141
+ setupEventHandlers(connection, name) {
142
+ const logger = this.options.logger;
143
+ connection.on('error', (error) => {
144
+ logger.error(`Błąd połączenia Redis (${name})`, {
145
+ connectionName: name,
146
+ error: (0, redis_error_formatter_1.formatRedisError)(error),
147
+ errorCode: (0, redis_error_formatter_1.getErrorCode)(error),
148
+ timestamp: new Date().toISOString(),
149
+ });
150
+ });
151
+ }
152
+ }
153
+ exports.default = RpcConnectionPool;
154
+ //# sourceMappingURL=rpc-connection-pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc-connection-pool.js","sourceRoot":"","sources":["../../../src/shared/redis/rpc-connection-pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};