@zdavison/matador 2.0.8 → 2.0.10
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.
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/package.json +6 -2
- package/examples/config.ts +0 -126
- package/examples/event.ts +0 -26
- package/examples/order-event.json +0 -19
- package/src/checkpoint/context.test.ts +0 -510
- package/src/checkpoint/context.ts +0 -213
- package/src/checkpoint/index.ts +0 -30
- package/src/checkpoint/stores/memory.ts +0 -47
- package/src/checkpoint/stores/noop.ts +0 -22
- package/src/checkpoint/stores/stores.test.ts +0 -177
- package/src/checkpoint/types.ts +0 -147
- package/src/codec/codec.ts +0 -42
- package/src/codec/header-aware-codec.ts +0 -41
- package/src/codec/index.ts +0 -11
- package/src/codec/json-codec.ts +0 -69
- package/src/codec/rabbitmq-codec.test.ts +0 -516
- package/src/codec/rabbitmq-codec.ts +0 -336
- package/src/core/fanout.test.ts +0 -1350
- package/src/core/fanout.ts +0 -184
- package/src/core/index.ts +0 -12
- package/src/core/matador.test.ts +0 -575
- package/src/core/matador.ts +0 -357
- package/src/core/shutdown.test.ts +0 -853
- package/src/core/shutdown.ts +0 -165
- package/src/errors/checkpoint-errors.ts +0 -62
- package/src/errors/has-description.ts +0 -25
- package/src/errors/index.ts +0 -58
- package/src/errors/matador-errors.ts +0 -477
- package/src/errors/retry-errors.test.ts +0 -175
- package/src/errors/retry-errors.ts +0 -188
- package/src/hooks/index.ts +0 -14
- package/src/hooks/safe-hooks.ts +0 -200
- package/src/hooks/types.ts +0 -226
- package/src/index.ts +0 -241
- package/src/pipeline/index.ts +0 -2
- package/src/pipeline/pipeline.test.ts +0 -1377
- package/src/pipeline/pipeline.ts +0 -393
- package/src/retry/index.ts +0 -4
- package/src/retry/policy.ts +0 -46
- package/src/retry/standard-policy.test.ts +0 -290
- package/src/retry/standard-policy.ts +0 -156
- package/src/schema/index.ts +0 -16
- package/src/schema/registry.test.ts +0 -339
- package/src/schema/registry.ts +0 -229
- package/src/schema/types.test.ts +0 -280
- package/src/schema/types.ts +0 -217
- package/src/topology/builder.test.ts +0 -451
- package/src/topology/builder.ts +0 -238
- package/src/topology/index.ts +0 -19
- package/src/topology/types.ts +0 -183
- package/src/transport/capabilities.ts +0 -88
- package/src/transport/connection-manager.ts +0 -218
- package/src/transport/index.ts +0 -42
- package/src/transport/local/local-transport.test.ts +0 -262
- package/src/transport/local/local-transport.ts +0 -330
- package/src/transport/multi/multi-transport.test.ts +0 -320
- package/src/transport/multi/multi-transport.ts +0 -294
- package/src/transport/rabbitmq/rabbitmq-transport.test.ts +0 -120
- package/src/transport/rabbitmq/rabbitmq-transport.ts +0 -782
- package/src/transport/transport.ts +0 -200
- package/src/types/common.ts +0 -53
- package/src/types/dispatcher.ts +0 -18
- package/src/types/envelope.ts +0 -244
- package/src/types/event.test.ts +0 -157
- package/src/types/event.ts +0 -112
- package/src/types/index.ts +0 -62
- package/src/types/subscriber.ts +0 -333
- package/test/e2e/multi-transport.e2e.test.ts +0 -237
- package/test/e2e/rabbitmq-transport.e2e.test.ts +0 -618
- package/test/e2e/transport-compliance.e2e.test.ts +0 -506
- package/test/integration/matador.integration.test.ts +0 -634
- package/tsconfig.json +0 -29
- package/tsconfig.tsbuildinfo +0 -1
- package/tsup.config.ts +0 -13
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
afterAll,
|
|
3
|
-
afterEach,
|
|
4
|
-
beforeAll,
|
|
5
|
-
beforeEach,
|
|
6
|
-
describe,
|
|
7
|
-
expect,
|
|
8
|
-
it,
|
|
9
|
-
} from 'bun:test';
|
|
10
|
-
import {
|
|
11
|
-
RabbitMQContainer,
|
|
12
|
-
type StartedRabbitMQContainer,
|
|
13
|
-
} from '@testcontainers/rabbitmq';
|
|
14
|
-
import type { TransportFallbackContext } from '../../src/hooks/index.js';
|
|
15
|
-
import type { Subscription } from '../../src/transport/index.js';
|
|
16
|
-
import { LocalTransport } from '../../src/transport/local/local-transport.js';
|
|
17
|
-
import { MultiTransport } from '../../src/transport/multi/multi-transport.js';
|
|
18
|
-
import { RabbitMQTransport } from '../../src/transport/rabbitmq/rabbitmq-transport.js';
|
|
19
|
-
import {
|
|
20
|
-
createTestEnvelope,
|
|
21
|
-
createTestTopology,
|
|
22
|
-
} from './transport-compliance.e2e.test.js';
|
|
23
|
-
|
|
24
|
-
// Skip tests if docker is not available
|
|
25
|
-
const SKIP_E2E = process.env.SKIP_E2E_TESTS === 'true';
|
|
26
|
-
|
|
27
|
-
describe.skipIf(SKIP_E2E)('MultiTransport E2E', () => {
|
|
28
|
-
let container: StartedRabbitMQContainer;
|
|
29
|
-
let connectionUrl: string;
|
|
30
|
-
|
|
31
|
-
beforeAll(async () => {
|
|
32
|
-
container = await new RabbitMQContainer('rabbitmq:3.13-management')
|
|
33
|
-
.withExposedPorts(5672, 15672)
|
|
34
|
-
.start();
|
|
35
|
-
|
|
36
|
-
connectionUrl = container.getAmqpUrl();
|
|
37
|
-
console.log(`RabbitMQ container started at ${connectionUrl}`);
|
|
38
|
-
}, 120_000);
|
|
39
|
-
|
|
40
|
-
afterAll(async () => {
|
|
41
|
-
if (container) {
|
|
42
|
-
await container.stop();
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
describe('fallback to local transport when RabbitMQ fails', () => {
|
|
47
|
-
let rabbitTransport: RabbitMQTransport;
|
|
48
|
-
let localTransport: LocalTransport;
|
|
49
|
-
let multiTransport: MultiTransport;
|
|
50
|
-
let subscriptions: Subscription[];
|
|
51
|
-
let fallbackEvents: TransportFallbackContext[];
|
|
52
|
-
|
|
53
|
-
beforeEach(async () => {
|
|
54
|
-
subscriptions = [];
|
|
55
|
-
fallbackEvents = [];
|
|
56
|
-
|
|
57
|
-
rabbitTransport = new RabbitMQTransport({
|
|
58
|
-
url: connectionUrl,
|
|
59
|
-
connectionName: 'matador-multi-transport-test',
|
|
60
|
-
quorumQueues: false,
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
localTransport = new LocalTransport();
|
|
64
|
-
|
|
65
|
-
multiTransport = new MultiTransport(
|
|
66
|
-
{ transports: [rabbitTransport, localTransport] },
|
|
67
|
-
{ onEnqueueFallback: (ctx) => fallbackEvents.push(ctx) },
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
await multiTransport.connect();
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
afterEach(async () => {
|
|
74
|
-
for (const sub of subscriptions) {
|
|
75
|
-
if (sub.isActive) {
|
|
76
|
-
await sub.unsubscribe();
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
if (multiTransport.isConnected()) {
|
|
80
|
-
await multiTransport.disconnect();
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it('should send to RabbitMQ when healthy', async () => {
|
|
85
|
-
const topology = createTestTopology(`healthy-${Date.now()}`);
|
|
86
|
-
await multiTransport.applyTopology(topology);
|
|
87
|
-
const queueName = `${topology.namespace}.events`;
|
|
88
|
-
|
|
89
|
-
const receivedMessages: string[] = [];
|
|
90
|
-
|
|
91
|
-
const subscription = await multiTransport.subscribe(
|
|
92
|
-
queueName,
|
|
93
|
-
async (env, receipt) => {
|
|
94
|
-
receivedMessages.push(env.id);
|
|
95
|
-
await multiTransport.complete(receipt);
|
|
96
|
-
},
|
|
97
|
-
);
|
|
98
|
-
subscriptions.push(subscription);
|
|
99
|
-
|
|
100
|
-
const envelope = createTestEnvelope();
|
|
101
|
-
await multiTransport.send(queueName, envelope);
|
|
102
|
-
|
|
103
|
-
await waitFor(() => receivedMessages.length >= 1, 5000);
|
|
104
|
-
|
|
105
|
-
expect(receivedMessages).toContain(envelope.id);
|
|
106
|
-
expect(fallbackEvents).toHaveLength(0); // No fallback occurred
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it('should fallback to memory transport when RabbitMQ send fails', async () => {
|
|
110
|
-
const topology = createTestTopology(`fallback-${Date.now()}`);
|
|
111
|
-
await multiTransport.applyTopology(topology);
|
|
112
|
-
const queueName = `${topology.namespace}.events`;
|
|
113
|
-
|
|
114
|
-
const receivedMessages: string[] = [];
|
|
115
|
-
|
|
116
|
-
// Subscribe BEFORE disconnecting RabbitMQ
|
|
117
|
-
const subscription = await multiTransport.subscribe(
|
|
118
|
-
queueName,
|
|
119
|
-
async (env, receipt) => {
|
|
120
|
-
receivedMessages.push(env.id);
|
|
121
|
-
await multiTransport.complete(receipt);
|
|
122
|
-
},
|
|
123
|
-
);
|
|
124
|
-
subscriptions.push(subscription);
|
|
125
|
-
|
|
126
|
-
// Disconnect RabbitMQ to simulate failure
|
|
127
|
-
await rabbitTransport.disconnect();
|
|
128
|
-
|
|
129
|
-
// Send should fallback to memory transport
|
|
130
|
-
const envelope = createTestEnvelope();
|
|
131
|
-
await multiTransport.send(queueName, envelope);
|
|
132
|
-
|
|
133
|
-
// Message should be processed by subscriber on memory transport
|
|
134
|
-
await waitFor(() => receivedMessages.length >= 1, 5000);
|
|
135
|
-
|
|
136
|
-
expect(receivedMessages).toContain(envelope.id);
|
|
137
|
-
|
|
138
|
-
// Verify fallback was triggered
|
|
139
|
-
expect(fallbackEvents).toHaveLength(1);
|
|
140
|
-
expect(fallbackEvents[0]!.failedTransport).toBe('rabbitmq');
|
|
141
|
-
expect(fallbackEvents[0]!.nextTransport).toBe('local');
|
|
142
|
-
expect(fallbackEvents[0]!.queue).toBe(queueName);
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
it('should process multiple messages via fallback', async () => {
|
|
146
|
-
const topology = createTestTopology(`multi-${Date.now()}`);
|
|
147
|
-
await multiTransport.applyTopology(topology);
|
|
148
|
-
const queueName = `${topology.namespace}.events`;
|
|
149
|
-
|
|
150
|
-
const receivedMessages: string[] = [];
|
|
151
|
-
|
|
152
|
-
const subscription = await multiTransport.subscribe(
|
|
153
|
-
queueName,
|
|
154
|
-
async (env, receipt) => {
|
|
155
|
-
receivedMessages.push(env.id);
|
|
156
|
-
await multiTransport.complete(receipt);
|
|
157
|
-
},
|
|
158
|
-
);
|
|
159
|
-
subscriptions.push(subscription);
|
|
160
|
-
|
|
161
|
-
// Disconnect RabbitMQ
|
|
162
|
-
await rabbitTransport.disconnect();
|
|
163
|
-
|
|
164
|
-
// Send multiple messages
|
|
165
|
-
const envelopes = [
|
|
166
|
-
createTestEnvelope({ id: 'msg-1' }),
|
|
167
|
-
createTestEnvelope({ id: 'msg-2' }),
|
|
168
|
-
createTestEnvelope({ id: 'msg-3' }),
|
|
169
|
-
];
|
|
170
|
-
|
|
171
|
-
for (const env of envelopes) {
|
|
172
|
-
await multiTransport.send(queueName, env);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
await waitFor(() => receivedMessages.length >= 3, 5000);
|
|
176
|
-
|
|
177
|
-
expect(receivedMessages).toContain('msg-1');
|
|
178
|
-
expect(receivedMessages).toContain('msg-2');
|
|
179
|
-
expect(receivedMessages).toContain('msg-3');
|
|
180
|
-
expect(fallbackEvents).toHaveLength(3);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
it('should handle mixed success/fallback sends', async () => {
|
|
184
|
-
const topology = createTestTopology(`mixed-${Date.now()}`);
|
|
185
|
-
await multiTransport.applyTopology(topology);
|
|
186
|
-
const queueName = `${topology.namespace}.events`;
|
|
187
|
-
|
|
188
|
-
const receivedMessages: string[] = [];
|
|
189
|
-
|
|
190
|
-
const subscription = await multiTransport.subscribe(
|
|
191
|
-
queueName,
|
|
192
|
-
async (env, receipt) => {
|
|
193
|
-
receivedMessages.push(env.id);
|
|
194
|
-
await multiTransport.complete(receipt);
|
|
195
|
-
},
|
|
196
|
-
);
|
|
197
|
-
subscriptions.push(subscription);
|
|
198
|
-
|
|
199
|
-
// Send first message to RabbitMQ (should succeed)
|
|
200
|
-
const env1 = createTestEnvelope({ id: 'rabbit-msg' });
|
|
201
|
-
await multiTransport.send(queueName, env1);
|
|
202
|
-
|
|
203
|
-
await waitFor(() => receivedMessages.includes('rabbit-msg'), 5000);
|
|
204
|
-
|
|
205
|
-
// Disconnect RabbitMQ
|
|
206
|
-
await rabbitTransport.disconnect();
|
|
207
|
-
|
|
208
|
-
// Send second message (should fallback to memory)
|
|
209
|
-
const env2 = createTestEnvelope({ id: 'memory-msg' });
|
|
210
|
-
await multiTransport.send(queueName, env2);
|
|
211
|
-
|
|
212
|
-
await waitFor(() => receivedMessages.includes('memory-msg'), 5000);
|
|
213
|
-
|
|
214
|
-
expect(receivedMessages).toContain('rabbit-msg');
|
|
215
|
-
expect(receivedMessages).toContain('memory-msg');
|
|
216
|
-
expect(fallbackEvents).toHaveLength(1);
|
|
217
|
-
expect(fallbackEvents[0]!.envelope.id).toBe('memory-msg');
|
|
218
|
-
});
|
|
219
|
-
});
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Waits for a condition to be true, with timeout.
|
|
224
|
-
*/
|
|
225
|
-
async function waitFor(
|
|
226
|
-
condition: () => boolean,
|
|
227
|
-
timeoutMs: number,
|
|
228
|
-
intervalMs = 50,
|
|
229
|
-
): Promise<void> {
|
|
230
|
-
const startTime = Date.now();
|
|
231
|
-
while (!condition()) {
|
|
232
|
-
if (Date.now() - startTime > timeoutMs) {
|
|
233
|
-
throw new Error(`Timeout waiting for condition after ${timeoutMs}ms`);
|
|
234
|
-
}
|
|
235
|
-
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
236
|
-
}
|
|
237
|
-
}
|