atomic-queues 2.2.0 → 3.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 (236) hide show
  1. package/README.md +296 -417
  2. package/dist/cli/generators/classes.d.ts +1 -1
  3. package/dist/cli/generators/json-schema.d.ts +1 -1
  4. package/dist/cli/generators/typescript.d.ts +1 -1
  5. package/dist/cli/index.js +147 -5
  6. package/dist/cli/index.js.map +1 -1
  7. package/dist/cluster/cluster-discovery.service.d.ts +91 -0
  8. package/dist/cluster/cluster-discovery.service.d.ts.map +1 -0
  9. package/dist/cluster/cluster-discovery.service.js +423 -0
  10. package/dist/cluster/cluster-discovery.service.js.map +1 -0
  11. package/dist/cluster/grpc-peer-monitor.service.d.ts +31 -0
  12. package/dist/cluster/grpc-peer-monitor.service.d.ts.map +1 -0
  13. package/dist/cluster/grpc-peer-monitor.service.js +192 -0
  14. package/dist/cluster/grpc-peer-monitor.service.js.map +1 -0
  15. package/dist/cluster/index.d.ts +7 -0
  16. package/dist/cluster/index.d.ts.map +1 -0
  17. package/dist/cluster/index.js +23 -0
  18. package/dist/cluster/index.js.map +1 -0
  19. package/dist/cluster/leader-election.service.d.ts +38 -0
  20. package/dist/cluster/leader-election.service.d.ts.map +1 -0
  21. package/dist/cluster/leader-election.service.js +184 -0
  22. package/dist/cluster/leader-election.service.js.map +1 -0
  23. package/dist/cluster/master-coordinator.d.ts +50 -0
  24. package/dist/cluster/master-coordinator.d.ts.map +1 -0
  25. package/dist/cluster/master-coordinator.js +307 -0
  26. package/dist/cluster/master-coordinator.js.map +1 -0
  27. package/dist/cluster/redis-health-monitor.service.d.ts +23 -0
  28. package/dist/cluster/redis-health-monitor.service.d.ts.map +1 -0
  29. package/dist/cluster/redis-health-monitor.service.js +100 -0
  30. package/dist/cluster/redis-health-monitor.service.js.map +1 -0
  31. package/dist/cluster/server-ring.service.d.ts +48 -0
  32. package/dist/cluster/server-ring.service.d.ts.map +1 -0
  33. package/dist/cluster/server-ring.service.js +136 -0
  34. package/dist/cluster/server-ring.service.js.map +1 -0
  35. package/dist/decorators/constants.d.ts +0 -3
  36. package/dist/decorators/constants.d.ts.map +1 -1
  37. package/dist/decorators/constants.js +1 -5
  38. package/dist/decorators/constants.js.map +1 -1
  39. package/dist/decorators/entity.decorators.d.ts +16 -24
  40. package/dist/decorators/entity.decorators.d.ts.map +1 -1
  41. package/dist/decorators/entity.decorators.js +0 -39
  42. package/dist/decorators/entity.decorators.js.map +1 -1
  43. package/dist/decorators/index.d.ts +0 -1
  44. package/dist/decorators/index.d.ts.map +1 -1
  45. package/dist/decorators/index.js +0 -1
  46. package/dist/decorators/index.js.map +1 -1
  47. package/dist/decorators/interfaces.d.ts +10 -28
  48. package/dist/decorators/interfaces.d.ts.map +1 -1
  49. package/dist/decorators/job.decorators.d.ts +4 -52
  50. package/dist/decorators/job.decorators.d.ts.map +1 -1
  51. package/dist/decorators/job.decorators.js +6 -54
  52. package/dist/decorators/job.decorators.js.map +1 -1
  53. package/dist/decorators/metadata-readers.d.ts +5 -5
  54. package/dist/decorators/metadata-readers.d.ts.map +1 -1
  55. package/dist/decorators/metadata-readers.js +2 -8
  56. package/dist/decorators/metadata-readers.js.map +1 -1
  57. package/dist/decorators/schema.decorators.d.ts +1 -1
  58. package/dist/decorators/schema.decorators.d.ts.map +1 -1
  59. package/dist/decorators/schema.decorators.js.map +1 -1
  60. package/dist/decorators/utils.d.ts +1 -1
  61. package/dist/decorators/utils.d.ts.map +1 -1
  62. package/dist/decorators/utils.js +5 -1
  63. package/dist/decorators/utils.js.map +1 -1
  64. package/dist/domain/interfaces/config.interfaces.d.ts +92 -35
  65. package/dist/domain/interfaces/config.interfaces.d.ts.map +1 -1
  66. package/dist/domain/interfaces/index.d.ts +1 -0
  67. package/dist/domain/interfaces/index.d.ts.map +1 -1
  68. package/dist/domain/interfaces/index.js +1 -0
  69. package/dist/domain/interfaces/index.js.map +1 -1
  70. package/dist/{services/registry → domain/interfaces}/registry.types.d.ts.map +1 -1
  71. package/dist/domain/interfaces/registry.types.js.map +1 -0
  72. package/dist/grpc/grpc-client-pool.service.d.ts +71 -0
  73. package/dist/grpc/grpc-client-pool.service.d.ts.map +1 -0
  74. package/dist/grpc/grpc-client-pool.service.js +307 -0
  75. package/dist/grpc/grpc-client-pool.service.js.map +1 -0
  76. package/dist/grpc/grpc-server.service.d.ts +47 -0
  77. package/dist/grpc/grpc-server.service.d.ts.map +1 -0
  78. package/dist/grpc/grpc-server.service.js +494 -0
  79. package/dist/grpc/grpc-server.service.js.map +1 -0
  80. package/dist/grpc/index.d.ts +3 -0
  81. package/dist/grpc/index.d.ts.map +1 -0
  82. package/dist/{services/gate → grpc}/index.js +2 -1
  83. package/dist/grpc/index.js.map +1 -0
  84. package/dist/index.d.ts +4 -0
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.js +4 -0
  87. package/dist/index.js.map +1 -1
  88. package/dist/module/atomic-queues.module.d.ts +1 -0
  89. package/dist/module/atomic-queues.module.d.ts.map +1 -1
  90. package/dist/module/atomic-queues.module.js +60 -11
  91. package/dist/module/atomic-queues.module.js.map +1 -1
  92. package/dist/services/command-discovery/command-discovery.service.js +2 -2
  93. package/dist/services/command-discovery/command-discovery.service.js.map +1 -1
  94. package/dist/services/entity-type-registry/entity-type-registry.service.d.ts +13 -0
  95. package/dist/services/entity-type-registry/entity-type-registry.service.d.ts.map +1 -0
  96. package/dist/services/entity-type-registry/entity-type-registry.service.js +75 -0
  97. package/dist/services/entity-type-registry/entity-type-registry.service.js.map +1 -0
  98. package/dist/services/entity-type-registry/index.d.ts +2 -0
  99. package/dist/services/entity-type-registry/index.d.ts.map +1 -0
  100. package/dist/services/{actor-system → entity-type-registry}/index.js +1 -1
  101. package/dist/services/entity-type-registry/index.js.map +1 -0
  102. package/dist/services/handler-executor/handler-executor.service.d.ts +0 -2
  103. package/dist/services/handler-executor/handler-executor.service.d.ts.map +1 -1
  104. package/dist/services/handler-executor/handler-executor.service.js +0 -19
  105. package/dist/services/handler-executor/handler-executor.service.js.map +1 -1
  106. package/dist/services/index.d.ts +3 -9
  107. package/dist/services/index.d.ts.map +1 -1
  108. package/dist/services/index.js +3 -9
  109. package/dist/services/index.js.map +1 -1
  110. package/dist/services/message-router/index.d.ts +2 -0
  111. package/dist/services/message-router/index.d.ts.map +1 -0
  112. package/dist/services/{actor-registry → message-router}/index.js +1 -1
  113. package/dist/services/message-router/index.js.map +1 -0
  114. package/dist/services/message-router/message-router.service.d.ts +53 -0
  115. package/dist/services/message-router/message-router.service.d.ts.map +1 -0
  116. package/dist/services/message-router/message-router.service.js +519 -0
  117. package/dist/services/message-router/message-router.service.js.map +1 -0
  118. package/dist/services/queue-bus/cluster-contracts.d.ts +1 -1
  119. package/dist/services/queue-bus/cluster-contracts.d.ts.map +1 -1
  120. package/dist/services/queue-bus/cluster-contracts.js.map +1 -1
  121. package/dist/services/queue-bus/queue-bus.service.d.ts +3 -21
  122. package/dist/services/queue-bus/queue-bus.service.d.ts.map +1 -1
  123. package/dist/services/queue-bus/queue-bus.service.js +15 -119
  124. package/dist/services/queue-bus/queue-bus.service.js.map +1 -1
  125. package/dist/utils/id.utils.d.ts +3 -0
  126. package/dist/utils/id.utils.d.ts.map +1 -0
  127. package/dist/utils/id.utils.js +14 -0
  128. package/dist/utils/id.utils.js.map +1 -0
  129. package/dist/utils/index.d.ts +1 -0
  130. package/dist/utils/index.d.ts.map +1 -1
  131. package/dist/utils/index.js +1 -0
  132. package/dist/utils/index.js.map +1 -1
  133. package/dist/wal/index.d.ts +4 -0
  134. package/dist/wal/index.d.ts.map +1 -0
  135. package/dist/{services/executor-pool → wal}/index.js +3 -1
  136. package/dist/wal/index.js.map +1 -0
  137. package/dist/wal/wal.scripts.d.ts +51 -0
  138. package/dist/wal/wal.scripts.d.ts.map +1 -0
  139. package/dist/wal/wal.scripts.js +84 -0
  140. package/dist/wal/wal.scripts.js.map +1 -0
  141. package/dist/wal/wal.service.d.ts +46 -0
  142. package/dist/wal/wal.service.d.ts.map +1 -0
  143. package/dist/wal/wal.service.js +243 -0
  144. package/dist/wal/wal.service.js.map +1 -0
  145. package/dist/wal/wal.types.d.ts +23 -0
  146. package/dist/wal/wal.types.d.ts.map +1 -0
  147. package/dist/wal/wal.types.js +3 -0
  148. package/dist/wal/wal.types.js.map +1 -0
  149. package/dist/workers/consistent-hash.d.ts +97 -0
  150. package/dist/workers/consistent-hash.d.ts.map +1 -0
  151. package/dist/workers/consistent-hash.js +231 -0
  152. package/dist/workers/consistent-hash.js.map +1 -0
  153. package/dist/workers/entity-worker-manager.d.ts +35 -0
  154. package/dist/workers/entity-worker-manager.d.ts.map +1 -0
  155. package/dist/workers/entity-worker-manager.js +237 -0
  156. package/dist/workers/entity-worker-manager.js.map +1 -0
  157. package/dist/workers/entity-worker.d.ts +54 -0
  158. package/dist/workers/entity-worker.d.ts.map +1 -0
  159. package/dist/workers/entity-worker.js +142 -0
  160. package/dist/workers/entity-worker.js.map +1 -0
  161. package/dist/workers/index.d.ts +4 -0
  162. package/dist/workers/index.d.ts.map +1 -0
  163. package/dist/workers/index.js +20 -0
  164. package/dist/workers/index.js.map +1 -0
  165. package/package.json +17 -4
  166. package/dist/decorators/actor.decorators.d.ts +0 -4
  167. package/dist/decorators/actor.decorators.d.ts.map +0 -1
  168. package/dist/decorators/actor.decorators.js +0 -32
  169. package/dist/decorators/actor.decorators.js.map +0 -1
  170. package/dist/services/actor-registry/actor-registry.service.d.ts +0 -32
  171. package/dist/services/actor-registry/actor-registry.service.d.ts.map +0 -1
  172. package/dist/services/actor-registry/actor-registry.service.js +0 -220
  173. package/dist/services/actor-registry/actor-registry.service.js.map +0 -1
  174. package/dist/services/actor-registry/index.d.ts +0 -2
  175. package/dist/services/actor-registry/index.d.ts.map +0 -1
  176. package/dist/services/actor-registry/index.js.map +0 -1
  177. package/dist/services/actor-system/actor-system.service.d.ts +0 -19
  178. package/dist/services/actor-system/actor-system.service.d.ts.map +0 -1
  179. package/dist/services/actor-system/actor-system.service.js +0 -86
  180. package/dist/services/actor-system/actor-system.service.js.map +0 -1
  181. package/dist/services/actor-system/index.d.ts +0 -2
  182. package/dist/services/actor-system/index.d.ts.map +0 -1
  183. package/dist/services/actor-system/index.js.map +0 -1
  184. package/dist/services/executor-pool/executor-pool.service.d.ts +0 -38
  185. package/dist/services/executor-pool/executor-pool.service.d.ts.map +0 -1
  186. package/dist/services/executor-pool/executor-pool.service.js +0 -180
  187. package/dist/services/executor-pool/executor-pool.service.js.map +0 -1
  188. package/dist/services/executor-pool/index.d.ts +0 -2
  189. package/dist/services/executor-pool/index.d.ts.map +0 -1
  190. package/dist/services/executor-pool/index.js.map +0 -1
  191. package/dist/services/gate/gate.service.d.ts +0 -17
  192. package/dist/services/gate/gate.service.d.ts.map +0 -1
  193. package/dist/services/gate/gate.service.js +0 -81
  194. package/dist/services/gate/gate.service.js.map +0 -1
  195. package/dist/services/gate/index.d.ts +0 -2
  196. package/dist/services/gate/index.d.ts.map +0 -1
  197. package/dist/services/gate/index.js.map +0 -1
  198. package/dist/services/log/index.d.ts +0 -2
  199. package/dist/services/log/index.d.ts.map +0 -1
  200. package/dist/services/log/index.js +0 -18
  201. package/dist/services/log/index.js.map +0 -1
  202. package/dist/services/log/log.service.d.ts +0 -21
  203. package/dist/services/log/log.service.d.ts.map +0 -1
  204. package/dist/services/log/log.service.js +0 -92
  205. package/dist/services/log/log.service.js.map +0 -1
  206. package/dist/services/registry/index.d.ts +0 -4
  207. package/dist/services/registry/index.d.ts.map +0 -1
  208. package/dist/services/registry/index.js +0 -20
  209. package/dist/services/registry/index.js.map +0 -1
  210. package/dist/services/registry/registry.service.d.ts +0 -43
  211. package/dist/services/registry/registry.service.d.ts.map +0 -1
  212. package/dist/services/registry/registry.service.js +0 -402
  213. package/dist/services/registry/registry.service.js.map +0 -1
  214. package/dist/services/registry/registry.types.js.map +0 -1
  215. package/dist/services/registry/schema-converter.d.ts +0 -2
  216. package/dist/services/registry/schema-converter.d.ts.map +0 -1
  217. package/dist/services/registry/schema-converter.js +0 -27
  218. package/dist/services/registry/schema-converter.js.map +0 -1
  219. package/dist/services/result-collector/index.d.ts +0 -2
  220. package/dist/services/result-collector/index.d.ts.map +0 -1
  221. package/dist/services/result-collector/index.js +0 -18
  222. package/dist/services/result-collector/index.js.map +0 -1
  223. package/dist/services/result-collector/result-collector.service.d.ts +0 -17
  224. package/dist/services/result-collector/result-collector.service.d.ts.map +0 -1
  225. package/dist/services/result-collector/result-collector.service.js +0 -92
  226. package/dist/services/result-collector/result-collector.service.js.map +0 -1
  227. package/dist/services/scheduler/index.d.ts +0 -2
  228. package/dist/services/scheduler/index.d.ts.map +0 -1
  229. package/dist/services/scheduler/index.js +0 -18
  230. package/dist/services/scheduler/index.js.map +0 -1
  231. package/dist/services/scheduler/scheduler.service.d.ts +0 -17
  232. package/dist/services/scheduler/scheduler.service.d.ts.map +0 -1
  233. package/dist/services/scheduler/scheduler.service.js +0 -140
  234. package/dist/services/scheduler/scheduler.service.js.map +0 -1
  235. /package/dist/{services/registry → domain/interfaces}/registry.types.d.ts +0 -0
  236. /package/dist/{services/registry → domain/interfaces}/registry.types.js +0 -0
@@ -0,0 +1,243 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WalService = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const utils_1 = require("../utils");
6
+ const wal_scripts_1 = require("./wal.scripts");
7
+ /**
8
+ * Write-Ahead Log service.
9
+ *
10
+ * Constructed via factory in the module (not via DI injection decorators)
11
+ * because it needs a serverId that's generated at startup.
12
+ */
13
+ class WalService {
14
+ constructor(redis, config, serverId) {
15
+ this.redis = redis;
16
+ this.config = config;
17
+ this.logger = new common_1.Logger(WalService.name);
18
+ this.cleanupTimer = null;
19
+ this.deadLetterCallbacks = [];
20
+ this.keyPrefix = (0, utils_1.resolveKeyPrefix)(config);
21
+ this.serverId = serverId;
22
+ this.entryTTL = config.wal?.entryTTL ?? 86400;
23
+ this.cleanupInterval = config.wal?.cleanupInterval ?? 5000;
24
+ }
25
+ // =========================================================================
26
+ // KEY HELPERS
27
+ // =========================================================================
28
+ walEntryKey(entityKey, messageId) {
29
+ return `${this.keyPrefix}:wal:${this.serverId}:${entityKey}:${messageId}`;
30
+ }
31
+ walIndexKey() {
32
+ return `${this.keyPrefix}:wal:${this.serverId}:index`;
33
+ }
34
+ deadLetterKey(entityType) {
35
+ return `${this.keyPrefix}:dead:${entityType}`;
36
+ }
37
+ // =========================================================================
38
+ // WRITE — enqueue a message to the WAL
39
+ // =========================================================================
40
+ async write(entityKey, message) {
41
+ const entryKey = this.walEntryKey(entityKey, message.id);
42
+ const indexKey = this.walIndexKey();
43
+ const indexMember = `${entityKey}:${message.id}`;
44
+ const entry = {
45
+ state: 'enqueued',
46
+ message: JSON.stringify(message),
47
+ entity_key: entityKey,
48
+ enqueued_at: message.enqueuedAt.toString(),
49
+ correlation_id: message.correlationId ?? '',
50
+ server_id: this.serverId,
51
+ };
52
+ const pipeline = this.redis.pipeline();
53
+ pipeline.hset(entryKey, entry);
54
+ pipeline.expire(entryKey, this.entryTTL);
55
+ pipeline.zadd(indexKey, message.enqueuedAt, indexMember);
56
+ await pipeline.exec();
57
+ }
58
+ // =========================================================================
59
+ // STATE TRANSITIONS — atomic via Lua scripts
60
+ // =========================================================================
61
+ async markDispatched(entityKey, messageId, workerId) {
62
+ const entryKey = this.walEntryKey(entityKey, messageId);
63
+ const result = (await this.redis.eval(wal_scripts_1.DISPATCH_SCRIPT, 1, entryKey, Date.now().toString(), workerId.toString()));
64
+ return result === 1;
65
+ }
66
+ async markCompleted(entityKey, messageId) {
67
+ const entryKey = this.walEntryKey(entityKey, messageId);
68
+ const indexKey = this.walIndexKey();
69
+ const indexMember = `${entityKey}:${messageId}`;
70
+ const result = (await this.redis.eval(wal_scripts_1.COMPLETE_SCRIPT, 2, entryKey, indexKey, Date.now().toString(), indexMember));
71
+ return result === 1;
72
+ }
73
+ async markFailed(entityKey, messageId, error, stack) {
74
+ const entryKey = this.walEntryKey(entityKey, messageId);
75
+ const result = (await this.redis.eval(wal_scripts_1.FAIL_SCRIPT, 1, entryKey, Date.now().toString(), error, stack ?? ''));
76
+ return result === 1;
77
+ }
78
+ async markInterrupted(entityKey, messageId, reason) {
79
+ const entryKey = this.walEntryKey(entityKey, messageId);
80
+ const result = (await this.redis.eval(wal_scripts_1.INTERRUPT_SCRIPT, 1, entryKey, Date.now().toString(), reason));
81
+ return result === 1;
82
+ }
83
+ // =========================================================================
84
+ // READ — get a WAL entry
85
+ // =========================================================================
86
+ async getEntry(entityKey, messageId) {
87
+ const entryKey = this.walEntryKey(entityKey, messageId);
88
+ const raw = await this.redis.hgetall(entryKey);
89
+ if (!raw || !raw.state)
90
+ return null;
91
+ return {
92
+ messageId,
93
+ state: raw.state,
94
+ message: JSON.parse(raw.message),
95
+ entityKey: raw.entity_key,
96
+ serverId: raw.server_id,
97
+ enqueuedAt: parseInt(raw.enqueued_at, 10),
98
+ dispatchedAt: raw.dispatched_at ? parseInt(raw.dispatched_at, 10) : undefined,
99
+ completedAt: raw.completed_at ? parseInt(raw.completed_at, 10) : undefined,
100
+ error: raw.error || undefined,
101
+ errorStack: raw.error_stack || undefined,
102
+ correlationId: raw.correlation_id || undefined,
103
+ workerId: raw.worker_id ? parseInt(raw.worker_id, 10) : undefined,
104
+ };
105
+ }
106
+ // =========================================================================
107
+ // RECOVERY — run on startup to resolve orphaned entries
108
+ // =========================================================================
109
+ async recover() {
110
+ const indexKey = this.walIndexKey();
111
+ const members = await this.redis.zrange(indexKey, 0, -1);
112
+ let reEnqueued = 0;
113
+ let interrupted = 0;
114
+ let cleaned = 0;
115
+ for (const member of members) {
116
+ const parts = member.split(':');
117
+ const messageId = parts[parts.length - 1];
118
+ const entityKey = parts.slice(0, -1).join(':');
119
+ const entry = await this.getEntry(entityKey, messageId);
120
+ if (!entry) {
121
+ await this.redis.zrem(indexKey, member);
122
+ cleaned++;
123
+ continue;
124
+ }
125
+ switch (entry.state) {
126
+ case 'enqueued':
127
+ reEnqueued++;
128
+ break;
129
+ case 'dispatched': {
130
+ await this.deadLetter(entry.message.entityType, entry.message, 'interrupted: process crashed during execution');
131
+ interrupted++;
132
+ const entryKey = this.walEntryKey(entityKey, messageId);
133
+ await this.redis.del(entryKey);
134
+ await this.redis.zrem(indexKey, member);
135
+ break;
136
+ }
137
+ case 'completed':
138
+ case 'failed':
139
+ case 'interrupted': {
140
+ const entryKey = this.walEntryKey(entityKey, messageId);
141
+ await this.redis.del(entryKey);
142
+ await this.redis.zrem(indexKey, member);
143
+ cleaned++;
144
+ break;
145
+ }
146
+ }
147
+ }
148
+ this.logger.log(`WAL recovery: ${reEnqueued} re-enqueued, ${interrupted} interrupted, ${cleaned} cleaned`);
149
+ return { reEnqueued, interrupted, cleaned };
150
+ }
151
+ /**
152
+ * Returns the messages that should be re-enqueued after recovery.
153
+ * Called by the recovery procedure to get pending messages.
154
+ */
155
+ async getPendingMessages() {
156
+ const indexKey = this.walIndexKey();
157
+ const members = await this.redis.zrange(indexKey, 0, -1);
158
+ const pending = [];
159
+ for (const member of members) {
160
+ const parts = member.split(':');
161
+ const messageId = parts[parts.length - 1];
162
+ const entityKey = parts.slice(0, -1).join(':');
163
+ const entry = await this.getEntry(entityKey, messageId);
164
+ if (entry && entry.state === 'enqueued') {
165
+ pending.push(entry.message);
166
+ }
167
+ }
168
+ return pending;
169
+ }
170
+ // =========================================================================
171
+ // DEAD LETTER
172
+ // =========================================================================
173
+ onDeadLetter(callback) {
174
+ this.deadLetterCallbacks.push(callback);
175
+ }
176
+ async deadLetter(entityType, message, reason) {
177
+ const deadKey = this.deadLetterKey(entityType);
178
+ await this.redis.lpush(deadKey, JSON.stringify({
179
+ ...message,
180
+ deadLetteredAt: Date.now(),
181
+ deadLetterReason: reason,
182
+ }));
183
+ this.logger.warn(`Dead-lettered ${message.name} for ${entityType}:${message.entityId}: ${reason}`);
184
+ for (const cb of this.deadLetterCallbacks) {
185
+ try {
186
+ cb(entityType, message, reason);
187
+ }
188
+ catch {
189
+ /* subscriber errors don't propagate */
190
+ }
191
+ }
192
+ }
193
+ async getDeadLetters(entityType, limit = 100) {
194
+ const deadKey = this.deadLetterKey(entityType);
195
+ const raw = await this.redis.lrange(deadKey, 0, limit - 1);
196
+ return raw.map((r) => JSON.parse(r));
197
+ }
198
+ // =========================================================================
199
+ // CLEANUP
200
+ // =========================================================================
201
+ startCleanup() {
202
+ if (this.cleanupTimer)
203
+ return;
204
+ this.cleanupTimer = setInterval(() => {
205
+ this.cleanup().catch((err) => {
206
+ this.logger.error(`WAL cleanup error: ${err.message}`);
207
+ });
208
+ }, this.cleanupInterval);
209
+ }
210
+ stopCleanup() {
211
+ if (this.cleanupTimer) {
212
+ clearInterval(this.cleanupTimer);
213
+ this.cleanupTimer = null;
214
+ }
215
+ }
216
+ async cleanup() {
217
+ const indexKey = this.walIndexKey();
218
+ const staleThreshold = Date.now() - this.entryTTL * 1000;
219
+ const members = await this.redis.zrangebyscore(indexKey, 0, staleThreshold);
220
+ if (members.length === 0)
221
+ return;
222
+ let cleaned = 0;
223
+ for (const member of members) {
224
+ const parts = member.split(':');
225
+ const messageId = parts[parts.length - 1];
226
+ const entityKey = parts.slice(0, -1).join(':');
227
+ const entryKey = this.walEntryKey(entityKey, messageId);
228
+ const state = await this.redis.hget(entryKey, 'state');
229
+ if (!state || state === 'completed' || state === 'failed' || state === 'interrupted') {
230
+ const pipeline = this.redis.pipeline();
231
+ pipeline.del(entryKey);
232
+ pipeline.zrem(indexKey, member);
233
+ await pipeline.exec();
234
+ cleaned++;
235
+ }
236
+ }
237
+ if (cleaned > 0) {
238
+ this.logger.debug(`WAL cleanup: removed ${cleaned} entries`);
239
+ }
240
+ }
241
+ }
242
+ exports.WalService = WalService;
243
+ //# sourceMappingURL=wal.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wal.service.js","sourceRoot":"","sources":["../../src/wal/wal.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { ISerializedMessage, IWalConfig } from '../domain';
2
+ export type WalState = 'enqueued' | 'dispatched' | 'completed' | 'failed' | 'interrupted';
3
+ export interface IWalEntry {
4
+ messageId: string;
5
+ state: WalState;
6
+ message: ISerializedMessage;
7
+ entityKey: string;
8
+ serverId: string;
9
+ enqueuedAt: number;
10
+ dispatchedAt?: number;
11
+ completedAt?: number;
12
+ error?: string;
13
+ errorStack?: string;
14
+ correlationId?: string;
15
+ workerId?: number;
16
+ }
17
+ export { IWalConfig };
18
+ export interface IWalRecoveryResult {
19
+ reEnqueued: number;
20
+ interrupted: number;
21
+ cleaned: number;
22
+ }
23
+ //# sourceMappingURL=wal.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wal.types.d.ts","sourceRoot":"","sources":["../../src/wal/wal.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE3D,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,YAAY,GAAG,WAAW,GAAG,QAAQ,GAAG,aAAa,CAAC;AAE1F,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,QAAQ,CAAC;IAChB,OAAO,EAAE,kBAAkB,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,OAAO,EAAE,UAAU,EAAE,CAAC;AAEtB,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=wal.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wal.types.js","sourceRoot":"","sources":["../../src/wal/wal.types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * MurmurHash3 (32-bit) — deterministic, fast, excellent distribution.
3
+ * Pure JS implementation, no dependencies.
4
+ */
5
+ export declare function murmurhash3(key: string, seed?: number): number;
6
+ /**
7
+ * A node on the consistent hash ring.
8
+ */
9
+ export interface HashRingNode<T = unknown> {
10
+ /** Unique identifier for this node (e.g. workerId, serverId) */
11
+ id: string;
12
+ /** Arbitrary metadata attached to the node */
13
+ data: T;
14
+ }
15
+ /**
16
+ * Consistent hash ring with virtual nodes.
17
+ *
18
+ * Provides O(log n) lookups and minimizes entity reassignment
19
+ * when nodes are added or removed (~1/N entities move).
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const ring = new ConsistentHashRing<number>(150);
24
+ * ring.addNode({ id: 'worker-0', data: 0 });
25
+ * ring.addNode({ id: 'worker-1', data: 1 });
26
+ *
27
+ * const owner = ring.getNode('account:a-123');
28
+ * // owner.data === 0 or 1 (deterministic for same key)
29
+ * ```
30
+ */
31
+ export declare class ConsistentHashRing<T = unknown> {
32
+ private ring;
33
+ private readonly nodes;
34
+ private readonly virtualNodesPerNode;
35
+ constructor(virtualNodesPerNode?: number);
36
+ /**
37
+ * Add a node to the ring with its virtual nodes.
38
+ * If a node with this ID already exists, it is replaced.
39
+ */
40
+ addNode(node: HashRingNode<T>): void;
41
+ /**
42
+ * Remove a node and all its virtual nodes from the ring.
43
+ */
44
+ removeNode(nodeId: string): void;
45
+ /**
46
+ * Get the node that owns the given key.
47
+ * Returns null if the ring is empty.
48
+ *
49
+ * Uses binary search to find the first virtual node
50
+ * whose hash is >= the key's hash (clockwise walk).
51
+ */
52
+ getNode(key: string): HashRingNode<T> | null;
53
+ /**
54
+ * Get the node that owns the given key, but only consider nodes
55
+ * that pass the filter. Walks clockwise until a matching node is found.
56
+ *
57
+ * Useful for entity-type affinity: skip nodes that don't handle
58
+ * the entity type.
59
+ *
60
+ * Returns null if no matching node exists.
61
+ */
62
+ getNodeFiltered(key: string, filter: (node: HashRingNode<T>) => boolean): HashRingNode<T> | null;
63
+ /**
64
+ * Check if a specific node owns the given key.
65
+ */
66
+ isOwner(nodeId: string, key: string): boolean;
67
+ /**
68
+ * Get all node IDs currently in the ring.
69
+ */
70
+ getNodeIds(): string[];
71
+ /**
72
+ * Get the number of physical nodes in the ring.
73
+ */
74
+ get size(): number;
75
+ /**
76
+ * Check if a node exists in the ring.
77
+ */
78
+ hasNode(nodeId: string): boolean;
79
+ /**
80
+ * Get a node by its ID.
81
+ */
82
+ getNodeById(nodeId: string): HashRingNode<T> | null;
83
+ /**
84
+ * Compute which keys from the given set would be reassigned
85
+ * if a node were added or removed.
86
+ *
87
+ * Returns a map of key → new owner node ID.
88
+ */
89
+ computeReassignment(keys: Iterable<string>, operation: {
90
+ type: 'add';
91
+ node: HashRingNode<T>;
92
+ } | {
93
+ type: 'remove';
94
+ nodeId: string;
95
+ }): Map<string, string>;
96
+ }
97
+ //# sourceMappingURL=consistent-hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consistent-hash.d.ts","sourceRoot":"","sources":["../../src/workers/consistent-hash.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,SAAI,GAAG,MAAM,CAiDzD;AAED;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACvC,gEAAgE;IAChE,EAAE,EAAE,MAAM,CAAC;IACX,8CAA8C;IAC9C,IAAI,EAAE,CAAC,CAAC;CACT;AAQD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,kBAAkB,CAAC,CAAC,GAAG,OAAO;IACzC,OAAO,CAAC,IAAI,CAAwB;IACpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAsC;IAC5D,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;gBAEjC,mBAAmB,SAAM;IAIrC;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAmBpC;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAKhC;;;;;;OAMG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAyB5C;;;;;;;;OAQG;IACH,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAoChG;;OAEG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO;IAK7C;;OAEG;IACH,UAAU,IAAI,MAAM,EAAE;IAItB;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAIhC;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAInD;;;;;OAKG;IACH,mBAAmB,CACjB,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,EACtB,SAAS,EAAE;QAAE,IAAI,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GACrF,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;CA0BvB"}
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConsistentHashRing = void 0;
4
+ exports.murmurhash3 = murmurhash3;
5
+ /**
6
+ * MurmurHash3 (32-bit) — deterministic, fast, excellent distribution.
7
+ * Pure JS implementation, no dependencies.
8
+ */
9
+ function murmurhash3(key, seed = 0) {
10
+ let h1 = seed >>> 0;
11
+ const len = key.length;
12
+ const nblocks = len >> 2;
13
+ const c1 = 0xcc9e2d51;
14
+ const c2 = 0x1b873593;
15
+ // Body
16
+ for (let i = 0; i < nblocks; i++) {
17
+ let k1 = (key.charCodeAt(i * 4) & 0xff) |
18
+ ((key.charCodeAt(i * 4 + 1) & 0xff) << 8) |
19
+ ((key.charCodeAt(i * 4 + 2) & 0xff) << 16) |
20
+ ((key.charCodeAt(i * 4 + 3) & 0xff) << 24);
21
+ k1 = Math.imul(k1, c1);
22
+ k1 = (k1 << 15) | (k1 >>> 17);
23
+ k1 = Math.imul(k1, c2);
24
+ h1 ^= k1;
25
+ h1 = (h1 << 13) | (h1 >>> 19);
26
+ h1 = Math.imul(h1, 5) + 0xe6546b64;
27
+ }
28
+ // Tail
29
+ const tail = nblocks * 4;
30
+ let k1 = 0;
31
+ const remainder = len & 3;
32
+ if (remainder >= 3)
33
+ k1 ^= (key.charCodeAt(tail + 2) & 0xff) << 16;
34
+ if (remainder >= 2)
35
+ k1 ^= (key.charCodeAt(tail + 1) & 0xff) << 8;
36
+ if (remainder >= 1) {
37
+ k1 ^= key.charCodeAt(tail) & 0xff;
38
+ k1 = Math.imul(k1, c1);
39
+ k1 = (k1 << 15) | (k1 >>> 17);
40
+ k1 = Math.imul(k1, c2);
41
+ h1 ^= k1;
42
+ }
43
+ // Finalization
44
+ h1 ^= len;
45
+ h1 ^= h1 >>> 16;
46
+ h1 = Math.imul(h1, 0x85ebca6b);
47
+ h1 ^= h1 >>> 13;
48
+ h1 = Math.imul(h1, 0xc2b2ae35);
49
+ h1 ^= h1 >>> 16;
50
+ return h1 >>> 0;
51
+ }
52
+ /**
53
+ * Consistent hash ring with virtual nodes.
54
+ *
55
+ * Provides O(log n) lookups and minimizes entity reassignment
56
+ * when nodes are added or removed (~1/N entities move).
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * const ring = new ConsistentHashRing<number>(150);
61
+ * ring.addNode({ id: 'worker-0', data: 0 });
62
+ * ring.addNode({ id: 'worker-1', data: 1 });
63
+ *
64
+ * const owner = ring.getNode('account:a-123');
65
+ * // owner.data === 0 or 1 (deterministic for same key)
66
+ * ```
67
+ */
68
+ class ConsistentHashRing {
69
+ constructor(virtualNodesPerNode = 150) {
70
+ this.ring = [];
71
+ this.nodes = new Map();
72
+ this.virtualNodesPerNode = virtualNodesPerNode;
73
+ }
74
+ /**
75
+ * Add a node to the ring with its virtual nodes.
76
+ * If a node with this ID already exists, it is replaced.
77
+ */
78
+ addNode(node) {
79
+ if (this.nodes.has(node.id)) {
80
+ this.removeNode(node.id);
81
+ }
82
+ this.nodes.set(node.id, node);
83
+ for (let i = 0; i < this.virtualNodesPerNode; i++) {
84
+ const key = `${node.id}:vnode:${i}`;
85
+ this.ring.push({
86
+ hash: murmurhash3(key),
87
+ nodeId: node.id,
88
+ data: node.data,
89
+ });
90
+ }
91
+ this.ring.sort((a, b) => a.hash - b.hash);
92
+ }
93
+ /**
94
+ * Remove a node and all its virtual nodes from the ring.
95
+ */
96
+ removeNode(nodeId) {
97
+ this.nodes.delete(nodeId);
98
+ this.ring = this.ring.filter((vn) => vn.nodeId !== nodeId);
99
+ }
100
+ /**
101
+ * Get the node that owns the given key.
102
+ * Returns null if the ring is empty.
103
+ *
104
+ * Uses binary search to find the first virtual node
105
+ * whose hash is >= the key's hash (clockwise walk).
106
+ */
107
+ getNode(key) {
108
+ if (this.ring.length === 0)
109
+ return null;
110
+ const hash = murmurhash3(key);
111
+ // Binary search for first virtual node with hash >= key hash
112
+ let lo = 0;
113
+ let hi = this.ring.length;
114
+ while (lo < hi) {
115
+ const mid = (lo + hi) >>> 1;
116
+ if (this.ring[mid].hash < hash) {
117
+ lo = mid + 1;
118
+ }
119
+ else {
120
+ hi = mid;
121
+ }
122
+ }
123
+ // Wrap around to the first node if we're past the end
124
+ const idx = lo < this.ring.length ? lo : 0;
125
+ const vnode = this.ring[idx];
126
+ return this.nodes.get(vnode.nodeId) ?? null;
127
+ }
128
+ /**
129
+ * Get the node that owns the given key, but only consider nodes
130
+ * that pass the filter. Walks clockwise until a matching node is found.
131
+ *
132
+ * Useful for entity-type affinity: skip nodes that don't handle
133
+ * the entity type.
134
+ *
135
+ * Returns null if no matching node exists.
136
+ */
137
+ getNodeFiltered(key, filter) {
138
+ if (this.ring.length === 0)
139
+ return null;
140
+ const hash = murmurhash3(key);
141
+ // Find starting position
142
+ let lo = 0;
143
+ let hi = this.ring.length;
144
+ while (lo < hi) {
145
+ const mid = (lo + hi) >>> 1;
146
+ if (this.ring[mid].hash < hash) {
147
+ lo = mid + 1;
148
+ }
149
+ else {
150
+ hi = mid;
151
+ }
152
+ }
153
+ // Walk clockwise, checking filter
154
+ const visited = new Set();
155
+ for (let i = 0; i < this.ring.length; i++) {
156
+ const idx = (lo + i) % this.ring.length;
157
+ const vnode = this.ring[idx];
158
+ if (visited.has(vnode.nodeId))
159
+ continue;
160
+ visited.add(vnode.nodeId);
161
+ const node = this.nodes.get(vnode.nodeId);
162
+ if (node && filter(node))
163
+ return node;
164
+ // If we've checked all distinct nodes, stop
165
+ if (visited.size >= this.nodes.size)
166
+ break;
167
+ }
168
+ return null;
169
+ }
170
+ /**
171
+ * Check if a specific node owns the given key.
172
+ */
173
+ isOwner(nodeId, key) {
174
+ const owner = this.getNode(key);
175
+ return owner?.id === nodeId;
176
+ }
177
+ /**
178
+ * Get all node IDs currently in the ring.
179
+ */
180
+ getNodeIds() {
181
+ return Array.from(this.nodes.keys());
182
+ }
183
+ /**
184
+ * Get the number of physical nodes in the ring.
185
+ */
186
+ get size() {
187
+ return this.nodes.size;
188
+ }
189
+ /**
190
+ * Check if a node exists in the ring.
191
+ */
192
+ hasNode(nodeId) {
193
+ return this.nodes.has(nodeId);
194
+ }
195
+ /**
196
+ * Get a node by its ID.
197
+ */
198
+ getNodeById(nodeId) {
199
+ return this.nodes.get(nodeId) ?? null;
200
+ }
201
+ /**
202
+ * Compute which keys from the given set would be reassigned
203
+ * if a node were added or removed.
204
+ *
205
+ * Returns a map of key → new owner node ID.
206
+ */
207
+ computeReassignment(keys, operation) {
208
+ // Create a hypothetical ring with the change applied
209
+ const hypothetical = new ConsistentHashRing(this.virtualNodesPerNode);
210
+ for (const [id, node] of this.nodes) {
211
+ if (operation.type === 'remove' && id === operation.nodeId)
212
+ continue;
213
+ hypothetical.addNode(node);
214
+ }
215
+ if (operation.type === 'add') {
216
+ hypothetical.addNode(operation.node);
217
+ }
218
+ // Find keys that changed ownership
219
+ const reassignment = new Map();
220
+ for (const key of keys) {
221
+ const currentOwner = this.getNode(key);
222
+ const newOwner = hypothetical.getNode(key);
223
+ if (currentOwner?.id !== newOwner?.id && newOwner) {
224
+ reassignment.set(key, newOwner.id);
225
+ }
226
+ }
227
+ return reassignment;
228
+ }
229
+ }
230
+ exports.ConsistentHashRing = ConsistentHashRing;
231
+ //# sourceMappingURL=consistent-hash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consistent-hash.js","sourceRoot":"","sources":["../../src/workers/consistent-hash.ts"],"names":[],"mappings":"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"}