@zdavison/matador 2.0.1
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/cli.ts +453 -0
- package/dist/checkpoint/context.d.ts +59 -0
- package/dist/checkpoint/context.d.ts.map +1 -0
- package/dist/checkpoint/context.js +140 -0
- package/dist/checkpoint/context.test.d.ts +2 -0
- package/dist/checkpoint/context.test.d.ts.map +1 -0
- package/dist/checkpoint/context.test.js +424 -0
- package/dist/checkpoint/index.d.ts +7 -0
- package/dist/checkpoint/index.d.ts.map +1 -0
- package/dist/checkpoint/index.js +6 -0
- package/dist/checkpoint/stores/memory.d.ts +29 -0
- package/dist/checkpoint/stores/memory.d.ts.map +1 -0
- package/dist/checkpoint/stores/memory.js +39 -0
- package/dist/checkpoint/stores/noop.d.ts +14 -0
- package/dist/checkpoint/stores/noop.d.ts.map +1 -0
- package/dist/checkpoint/stores/noop.js +18 -0
- package/dist/checkpoint/stores/stores.test.d.ts +2 -0
- package/dist/checkpoint/stores/stores.test.d.ts.map +1 -0
- package/dist/checkpoint/stores/stores.test.js +146 -0
- package/dist/checkpoint/types.d.ts +119 -0
- package/dist/checkpoint/types.d.ts.map +1 -0
- package/dist/checkpoint/types.js +1 -0
- package/dist/codec/codec.d.ts +29 -0
- package/dist/codec/codec.d.ts.map +1 -0
- package/dist/codec/codec.js +15 -0
- package/dist/codec/header-aware-codec.d.ts +36 -0
- package/dist/codec/header-aware-codec.d.ts.map +1 -0
- package/dist/codec/header-aware-codec.js +1 -0
- package/dist/codec/index.d.ts +6 -0
- package/dist/codec/index.d.ts.map +1 -0
- package/dist/codec/index.js +3 -0
- package/dist/codec/json-codec.d.ts +13 -0
- package/dist/codec/json-codec.d.ts.map +1 -0
- package/dist/codec/json-codec.js +64 -0
- package/dist/codec/rabbitmq-codec.d.ts +28 -0
- package/dist/codec/rabbitmq-codec.d.ts.map +1 -0
- package/dist/codec/rabbitmq-codec.js +242 -0
- package/dist/codec/rabbitmq-codec.test.d.ts +2 -0
- package/dist/codec/rabbitmq-codec.test.d.ts.map +1 -0
- package/dist/codec/rabbitmq-codec.test.js +433 -0
- package/dist/core/fanout.d.ts +59 -0
- package/dist/core/fanout.d.ts.map +1 -0
- package/dist/core/fanout.js +121 -0
- package/dist/core/fanout.test.d.ts +2 -0
- package/dist/core/fanout.test.d.ts.map +1 -0
- package/dist/core/fanout.test.js +1055 -0
- package/dist/core/index.d.ts +7 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +3 -0
- package/dist/core/matador.d.ts +133 -0
- package/dist/core/matador.d.ts.map +1 -0
- package/dist/core/matador.js +222 -0
- package/dist/core/matador.test.d.ts +2 -0
- package/dist/core/matador.test.d.ts.map +1 -0
- package/dist/core/matador.test.js +446 -0
- package/dist/core/shutdown.d.ts +78 -0
- package/dist/core/shutdown.d.ts.map +1 -0
- package/dist/core/shutdown.js +111 -0
- package/dist/core/shutdown.test.d.ts +2 -0
- package/dist/core/shutdown.test.d.ts.map +1 -0
- package/dist/core/shutdown.test.js +524 -0
- package/dist/errors/checkpoint-errors.d.ts +30 -0
- package/dist/errors/checkpoint-errors.d.ts.map +1 -0
- package/dist/errors/checkpoint-errors.js +49 -0
- package/dist/errors/has-description.d.ts +18 -0
- package/dist/errors/has-description.d.ts.map +1 -0
- package/dist/errors/has-description.js +9 -0
- package/dist/errors/index.d.ts +6 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +22 -0
- package/dist/errors/matador-errors.d.ts +183 -0
- package/dist/errors/matador-errors.d.ts.map +1 -0
- package/dist/errors/matador-errors.js +376 -0
- package/dist/errors/retry-errors.d.ts +67 -0
- package/dist/errors/retry-errors.d.ts.map +1 -0
- package/dist/errors/retry-errors.js +108 -0
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +2 -0
- package/dist/hooks/safe-hooks.d.ts +34 -0
- package/dist/hooks/safe-hooks.d.ts.map +1 -0
- package/dist/hooks/safe-hooks.js +135 -0
- package/dist/hooks/types.d.ts +189 -0
- package/dist/hooks/types.d.ts.map +1 -0
- package/dist/hooks/types.js +9 -0
- package/dist/index.cjs +3156 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +23 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/pipeline/index.d.ts +3 -0
- package/dist/pipeline/index.d.ts.map +1 -0
- package/dist/pipeline/index.js +1 -0
- package/dist/pipeline/pipeline.d.ts +60 -0
- package/dist/pipeline/pipeline.d.ts.map +1 -0
- package/dist/pipeline/pipeline.js +261 -0
- package/dist/pipeline/pipeline.test.d.ts +2 -0
- package/dist/pipeline/pipeline.test.d.ts.map +1 -0
- package/dist/pipeline/pipeline.test.js +1065 -0
- package/dist/retry/index.d.ts +4 -0
- package/dist/retry/index.d.ts.map +1 -0
- package/dist/retry/index.js +1 -0
- package/dist/retry/policy.d.ts +43 -0
- package/dist/retry/policy.d.ts.map +1 -0
- package/dist/retry/policy.js +1 -0
- package/dist/retry/standard-policy.d.ts +44 -0
- package/dist/retry/standard-policy.d.ts.map +1 -0
- package/dist/retry/standard-policy.js +102 -0
- package/dist/retry/standard-policy.test.d.ts +2 -0
- package/dist/retry/standard-policy.test.d.ts.map +1 -0
- package/dist/retry/standard-policy.test.js +190 -0
- package/dist/schema/index.d.ts +4 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +2 -0
- package/dist/schema/registry.d.ts +63 -0
- package/dist/schema/registry.d.ts.map +1 -0
- package/dist/schema/registry.js +171 -0
- package/dist/schema/registry.test.d.ts +2 -0
- package/dist/schema/registry.test.d.ts.map +1 -0
- package/dist/schema/registry.test.js +278 -0
- package/dist/schema/types.d.ts +158 -0
- package/dist/schema/types.d.ts.map +1 -0
- package/dist/schema/types.js +74 -0
- package/dist/schema/types.test.d.ts +2 -0
- package/dist/schema/types.test.d.ts.map +1 -0
- package/dist/schema/types.test.js +243 -0
- package/dist/topology/builder.d.ts +66 -0
- package/dist/topology/builder.d.ts.map +1 -0
- package/dist/topology/builder.js +156 -0
- package/dist/topology/builder.test.d.ts +2 -0
- package/dist/topology/builder.test.d.ts.map +1 -0
- package/dist/topology/builder.test.js +222 -0
- package/dist/topology/index.d.ts +5 -0
- package/dist/topology/index.d.ts.map +1 -0
- package/dist/topology/index.js +2 -0
- package/dist/topology/types.d.ts +76 -0
- package/dist/topology/types.d.ts.map +1 -0
- package/dist/topology/types.js +18 -0
- package/dist/transport/capabilities.d.ts +66 -0
- package/dist/transport/capabilities.d.ts.map +1 -0
- package/dist/transport/capabilities.js +18 -0
- package/dist/transport/connection-manager.d.ts +95 -0
- package/dist/transport/connection-manager.d.ts.map +1 -0
- package/dist/transport/connection-manager.js +144 -0
- package/dist/transport/index.d.ts +11 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +5 -0
- package/dist/transport/local/local-transport.d.ts +62 -0
- package/dist/transport/local/local-transport.d.ts.map +1 -0
- package/dist/transport/local/local-transport.js +241 -0
- package/dist/transport/local/local-transport.test.d.ts +2 -0
- package/dist/transport/local/local-transport.test.d.ts.map +1 -0
- package/dist/transport/local/local-transport.test.js +192 -0
- package/dist/transport/multi/multi-transport.d.ts +94 -0
- package/dist/transport/multi/multi-transport.d.ts.map +1 -0
- package/dist/transport/multi/multi-transport.js +184 -0
- package/dist/transport/multi/multi-transport.test.d.ts +2 -0
- package/dist/transport/multi/multi-transport.test.d.ts.map +1 -0
- package/dist/transport/multi/multi-transport.test.js +236 -0
- package/dist/transport/rabbitmq/rabbitmq-transport.d.ts +73 -0
- package/dist/transport/rabbitmq/rabbitmq-transport.d.ts.map +1 -0
- package/dist/transport/rabbitmq/rabbitmq-transport.js +518 -0
- package/dist/transport/transport.d.ts +152 -0
- package/dist/transport/transport.d.ts.map +1 -0
- package/dist/transport/transport.js +1 -0
- package/dist/types/common.d.ts +41 -0
- package/dist/types/common.d.ts.map +1 -0
- package/dist/types/common.js +12 -0
- package/dist/types/envelope.d.ts +82 -0
- package/dist/types/envelope.d.ts.map +1 -0
- package/dist/types/envelope.js +36 -0
- package/dist/types/event.d.ts +96 -0
- package/dist/types/event.d.ts.map +1 -0
- package/dist/types/event.js +26 -0
- package/dist/types/event.test.d.ts +2 -0
- package/dist/types/event.test.d.ts.map +1 -0
- package/dist/types/event.test.js +130 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/types/subscriber.d.ts +207 -0
- package/dist/types/subscriber.d.ts.map +1 -0
- package/dist/types/subscriber.js +99 -0
- package/examples/config.ts +126 -0
- package/examples/event.ts +26 -0
- package/examples/order-event.json +19 -0
- package/package.json +66 -0
- package/src/checkpoint/context.test.ts +510 -0
- package/src/checkpoint/context.ts +213 -0
- package/src/checkpoint/index.ts +30 -0
- package/src/checkpoint/stores/memory.ts +47 -0
- package/src/checkpoint/stores/noop.ts +22 -0
- package/src/checkpoint/stores/stores.test.ts +177 -0
- package/src/checkpoint/types.ts +147 -0
- package/src/codec/codec.ts +42 -0
- package/src/codec/header-aware-codec.ts +41 -0
- package/src/codec/index.ts +11 -0
- package/src/codec/json-codec.ts +69 -0
- package/src/codec/rabbitmq-codec.test.ts +516 -0
- package/src/codec/rabbitmq-codec.ts +336 -0
- package/src/core/fanout.test.ts +1351 -0
- package/src/core/fanout.ts +184 -0
- package/src/core/index.ts +12 -0
- package/src/core/matador.test.ts +575 -0
- package/src/core/matador.ts +344 -0
- package/src/core/shutdown.test.ts +853 -0
- package/src/core/shutdown.ts +165 -0
- package/src/errors/checkpoint-errors.ts +62 -0
- package/src/errors/has-description.ts +25 -0
- package/src/errors/index.ts +57 -0
- package/src/errors/matador-errors.ts +477 -0
- package/src/errors/retry-errors.ts +134 -0
- package/src/hooks/index.ts +15 -0
- package/src/hooks/safe-hooks.ts +223 -0
- package/src/hooks/types.ts +248 -0
- package/src/index.ts +231 -0
- package/src/pipeline/index.ts +2 -0
- package/src/pipeline/pipeline.test.ts +1317 -0
- package/src/pipeline/pipeline.ts +371 -0
- package/src/retry/index.ts +4 -0
- package/src/retry/policy.ts +46 -0
- package/src/retry/standard-policy.test.ts +282 -0
- package/src/retry/standard-policy.ts +156 -0
- package/src/schema/index.ts +16 -0
- package/src/schema/registry.test.ts +339 -0
- package/src/schema/registry.ts +226 -0
- package/src/schema/types.test.ts +281 -0
- package/src/schema/types.ts +217 -0
- package/src/topology/builder.test.ts +275 -0
- package/src/topology/builder.ts +199 -0
- package/src/topology/index.ts +15 -0
- package/src/topology/types.ts +109 -0
- package/src/transport/capabilities.ts +88 -0
- package/src/transport/connection-manager.ts +218 -0
- package/src/transport/index.ts +42 -0
- package/src/transport/local/local-transport.test.ts +262 -0
- package/src/transport/local/local-transport.ts +327 -0
- package/src/transport/multi/multi-transport.test.ts +320 -0
- package/src/transport/multi/multi-transport.ts +294 -0
- package/src/transport/rabbitmq/rabbitmq-transport.ts +753 -0
- package/src/transport/transport.ts +200 -0
- package/src/types/common.ts +53 -0
- package/src/types/envelope.ts +152 -0
- package/src/types/event.test.ts +157 -0
- package/src/types/event.ts +118 -0
- package/src/types/index.ts +52 -0
- package/src/types/subscriber.ts +310 -0
- package/test/e2e/multi-transport.e2e.test.ts +236 -0
- package/test/e2e/rabbitmq-transport.e2e.test.ts +327 -0
- package/test/e2e/transport-compliance.e2e.test.ts +505 -0
- package/test/integration/matador.integration.test.ts +634 -0
- package/tsconfig.json +29 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/tsup.config.ts +13 -0
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from 'bun:test';
|
|
2
|
+
import { TopologyBuilder } from '../topology/builder.js';
|
|
3
|
+
import { LocalTransport } from '../transport/local/local-transport.js';
|
|
4
|
+
import { MatadorEvent, createSubscriber } from '../types/index.js';
|
|
5
|
+
import { Matador } from './matador.js';
|
|
6
|
+
class UserCreatedEvent extends MatadorEvent {
|
|
7
|
+
data;
|
|
8
|
+
static key = 'user.created';
|
|
9
|
+
static description = 'Fired when a new user is created';
|
|
10
|
+
constructor(data) {
|
|
11
|
+
super();
|
|
12
|
+
this.data = data;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
class OrderPlacedEvent extends MatadorEvent {
|
|
16
|
+
data;
|
|
17
|
+
static key = 'order.placed';
|
|
18
|
+
static description = 'Fired when an order is placed';
|
|
19
|
+
constructor(data) {
|
|
20
|
+
super();
|
|
21
|
+
this.data = data;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
describe('Matador', () => {
|
|
25
|
+
let transport;
|
|
26
|
+
let matador;
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
transport = new LocalTransport();
|
|
29
|
+
});
|
|
30
|
+
afterEach(async () => {
|
|
31
|
+
if (matador) {
|
|
32
|
+
await matador.shutdown();
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
describe('configuration', () => {
|
|
36
|
+
it('should create with schema in config using constructor', () => {
|
|
37
|
+
const topology = TopologyBuilder.create()
|
|
38
|
+
.withNamespace('test')
|
|
39
|
+
.addQueue('events')
|
|
40
|
+
.build();
|
|
41
|
+
const subscriber = createSubscriber({
|
|
42
|
+
name: 'handle-user',
|
|
43
|
+
description: 'Handles user events',
|
|
44
|
+
callback: async () => { },
|
|
45
|
+
});
|
|
46
|
+
const schema = {
|
|
47
|
+
[UserCreatedEvent.key]: [UserCreatedEvent, [subscriber]],
|
|
48
|
+
};
|
|
49
|
+
matador = new Matador({ transport, topology, schema });
|
|
50
|
+
expect(matador).toBeInstanceOf(Matador);
|
|
51
|
+
expect(matador.isConnected()).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
it('should support hooks as second argument for dependency injection', () => {
|
|
54
|
+
const topology = TopologyBuilder.create()
|
|
55
|
+
.withNamespace('test')
|
|
56
|
+
.addQueue('events')
|
|
57
|
+
.build();
|
|
58
|
+
const subscriber = createSubscriber({
|
|
59
|
+
name: 'handle-user',
|
|
60
|
+
description: 'Handles user events',
|
|
61
|
+
callback: async () => { },
|
|
62
|
+
});
|
|
63
|
+
const schema = {
|
|
64
|
+
[UserCreatedEvent.key]: [UserCreatedEvent, [subscriber]],
|
|
65
|
+
};
|
|
66
|
+
const logs = [];
|
|
67
|
+
const mockLogger = {
|
|
68
|
+
debug: (msg) => logs.push(`debug: ${msg}`),
|
|
69
|
+
info: (msg) => logs.push(`info: ${msg}`),
|
|
70
|
+
warn: (msg) => logs.push(`warn: ${msg}`),
|
|
71
|
+
error: (msg) => logs.push(`error: ${msg}`),
|
|
72
|
+
};
|
|
73
|
+
matador = new Matador({ transport, topology, schema }, { logger: mockLogger });
|
|
74
|
+
expect(matador).toBeInstanceOf(Matador);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
describe('registration', () => {
|
|
78
|
+
it('should register events via schema in constructor', () => {
|
|
79
|
+
const topology = TopologyBuilder.create()
|
|
80
|
+
.withNamespace('test')
|
|
81
|
+
.addQueue('events')
|
|
82
|
+
.build();
|
|
83
|
+
const subscriber = createSubscriber({
|
|
84
|
+
name: 'send-welcome-email',
|
|
85
|
+
description: 'Sends welcome email',
|
|
86
|
+
callback: async () => { },
|
|
87
|
+
});
|
|
88
|
+
const schema = {
|
|
89
|
+
[UserCreatedEvent.key]: [UserCreatedEvent, [subscriber]],
|
|
90
|
+
};
|
|
91
|
+
matador = new Matador({ transport, topology, schema });
|
|
92
|
+
expect(matador).toBeInstanceOf(Matador);
|
|
93
|
+
});
|
|
94
|
+
it('should support multiple events in schema', () => {
|
|
95
|
+
const topology = TopologyBuilder.create()
|
|
96
|
+
.withNamespace('test')
|
|
97
|
+
.addQueue('events')
|
|
98
|
+
.build();
|
|
99
|
+
const userSub = createSubscriber({
|
|
100
|
+
name: 'handle-user',
|
|
101
|
+
description: 'Handles user events',
|
|
102
|
+
callback: async () => { },
|
|
103
|
+
});
|
|
104
|
+
const orderSub = createSubscriber({
|
|
105
|
+
name: 'handle-order',
|
|
106
|
+
description: 'Handles order events',
|
|
107
|
+
callback: async () => { },
|
|
108
|
+
});
|
|
109
|
+
const schema = {
|
|
110
|
+
[UserCreatedEvent.key]: [UserCreatedEvent, [userSub]],
|
|
111
|
+
[OrderPlacedEvent.key]: [OrderPlacedEvent, [orderSub]],
|
|
112
|
+
};
|
|
113
|
+
matador = new Matador({ transport, topology, schema });
|
|
114
|
+
expect(matador).toBeInstanceOf(Matador);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
describe('start', () => {
|
|
118
|
+
it('should connect transport and be ready', async () => {
|
|
119
|
+
const topology = TopologyBuilder.create()
|
|
120
|
+
.withNamespace('test')
|
|
121
|
+
.addQueue('events')
|
|
122
|
+
.build();
|
|
123
|
+
const subscriber = createSubscriber({
|
|
124
|
+
name: 'handle-user',
|
|
125
|
+
description: 'Handles user events',
|
|
126
|
+
callback: async () => { },
|
|
127
|
+
});
|
|
128
|
+
const schema = {
|
|
129
|
+
[UserCreatedEvent.key]: [UserCreatedEvent, [subscriber]],
|
|
130
|
+
};
|
|
131
|
+
matador = new Matador({ transport, topology, schema });
|
|
132
|
+
await matador.start();
|
|
133
|
+
expect(matador.isConnected()).toBe(true);
|
|
134
|
+
});
|
|
135
|
+
it('should throw if started twice', async () => {
|
|
136
|
+
const topology = TopologyBuilder.create()
|
|
137
|
+
.withNamespace('test')
|
|
138
|
+
.addQueue('events')
|
|
139
|
+
.build();
|
|
140
|
+
const subscriber = createSubscriber({
|
|
141
|
+
name: 'handle-user',
|
|
142
|
+
description: 'Handles user events',
|
|
143
|
+
callback: async () => { },
|
|
144
|
+
});
|
|
145
|
+
const schema = {
|
|
146
|
+
[UserCreatedEvent.key]: [UserCreatedEvent, [subscriber]],
|
|
147
|
+
};
|
|
148
|
+
matador = new Matador({ transport, topology, schema });
|
|
149
|
+
await matador.start();
|
|
150
|
+
// start() is idempotent - calling it again should not throw
|
|
151
|
+
await expect(matador.start()).resolves.toBeUndefined();
|
|
152
|
+
});
|
|
153
|
+
it('should throw on invalid schema', async () => {
|
|
154
|
+
const topology = TopologyBuilder.create()
|
|
155
|
+
.withNamespace('test')
|
|
156
|
+
.addQueue('events')
|
|
157
|
+
.build();
|
|
158
|
+
// Register duplicate subscriber names
|
|
159
|
+
const sub1 = createSubscriber({
|
|
160
|
+
name: 'same-name',
|
|
161
|
+
description: 'Test subscriber',
|
|
162
|
+
callback: async () => { },
|
|
163
|
+
});
|
|
164
|
+
const sub2 = createSubscriber({
|
|
165
|
+
name: 'same-name',
|
|
166
|
+
description: 'Test subscriber',
|
|
167
|
+
callback: async () => { },
|
|
168
|
+
});
|
|
169
|
+
const schema = {
|
|
170
|
+
[UserCreatedEvent.key]: [UserCreatedEvent, [sub1, sub2]],
|
|
171
|
+
};
|
|
172
|
+
matador = new Matador({ transport, topology, schema });
|
|
173
|
+
expect(matador.start()).rejects.toThrow('Schema validation failed');
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
describe('send', () => {
|
|
177
|
+
it('should throw if not started', async () => {
|
|
178
|
+
const topology = TopologyBuilder.create()
|
|
179
|
+
.withNamespace('test')
|
|
180
|
+
.addQueue('events')
|
|
181
|
+
.build();
|
|
182
|
+
const subscriber = createSubscriber({
|
|
183
|
+
name: 'handle-user',
|
|
184
|
+
description: 'Handles user events',
|
|
185
|
+
callback: async () => { },
|
|
186
|
+
});
|
|
187
|
+
const schema = {
|
|
188
|
+
[UserCreatedEvent.key]: [UserCreatedEvent, [subscriber]],
|
|
189
|
+
};
|
|
190
|
+
matador = new Matador({ transport, topology, schema });
|
|
191
|
+
const event = new UserCreatedEvent({
|
|
192
|
+
userId: '123',
|
|
193
|
+
email: 'test@example.com',
|
|
194
|
+
});
|
|
195
|
+
await expect(matador.send(event)).rejects.toThrow('Matador has not been started');
|
|
196
|
+
});
|
|
197
|
+
it('should send events to transport', async () => {
|
|
198
|
+
const topology = TopologyBuilder.create()
|
|
199
|
+
.withNamespace('test')
|
|
200
|
+
.addQueue('events')
|
|
201
|
+
.build();
|
|
202
|
+
const subscriber = createSubscriber({
|
|
203
|
+
name: 'handle-user',
|
|
204
|
+
description: 'Handles user events',
|
|
205
|
+
callback: async () => { },
|
|
206
|
+
});
|
|
207
|
+
const schema = {
|
|
208
|
+
[UserCreatedEvent.key]: [UserCreatedEvent, [subscriber]],
|
|
209
|
+
};
|
|
210
|
+
matador = new Matador({ transport, topology, schema });
|
|
211
|
+
await matador.start();
|
|
212
|
+
const event = new UserCreatedEvent({
|
|
213
|
+
userId: '123',
|
|
214
|
+
email: 'test@example.com',
|
|
215
|
+
});
|
|
216
|
+
const result = await matador.send(event);
|
|
217
|
+
expect(result.subscribersSent).toBe(1);
|
|
218
|
+
expect(result.errors).toHaveLength(0);
|
|
219
|
+
});
|
|
220
|
+
it('should send events using class + data shorthand', async () => {
|
|
221
|
+
const topology = TopologyBuilder.create()
|
|
222
|
+
.withNamespace('test')
|
|
223
|
+
.addQueue('events')
|
|
224
|
+
.build();
|
|
225
|
+
const subscriber = createSubscriber({
|
|
226
|
+
name: 'handle-user',
|
|
227
|
+
description: 'Handles user events',
|
|
228
|
+
callback: async () => { },
|
|
229
|
+
});
|
|
230
|
+
const schema = {
|
|
231
|
+
[UserCreatedEvent.key]: [UserCreatedEvent, [subscriber]],
|
|
232
|
+
};
|
|
233
|
+
matador = new Matador({ transport, topology, schema });
|
|
234
|
+
await matador.start();
|
|
235
|
+
// Use the shorthand: send(EventClass, data)
|
|
236
|
+
const result = await matador.send(UserCreatedEvent, {
|
|
237
|
+
userId: '123',
|
|
238
|
+
email: 'test@example.com',
|
|
239
|
+
});
|
|
240
|
+
expect(result.subscribersSent).toBe(1);
|
|
241
|
+
expect(result.errors).toHaveLength(0);
|
|
242
|
+
});
|
|
243
|
+
it('should create one envelope per subscriber', async () => {
|
|
244
|
+
const topology = TopologyBuilder.create()
|
|
245
|
+
.withNamespace('test')
|
|
246
|
+
.addQueue('events')
|
|
247
|
+
.build();
|
|
248
|
+
const sub1 = createSubscriber({
|
|
249
|
+
name: 'sub-1',
|
|
250
|
+
description: 'Subscriber 1',
|
|
251
|
+
callback: async () => { },
|
|
252
|
+
});
|
|
253
|
+
const sub2 = createSubscriber({
|
|
254
|
+
name: 'sub-2',
|
|
255
|
+
description: 'Subscriber 2',
|
|
256
|
+
callback: async () => { },
|
|
257
|
+
});
|
|
258
|
+
const sub3 = createSubscriber({
|
|
259
|
+
name: 'sub-3',
|
|
260
|
+
description: 'Subscriber 3',
|
|
261
|
+
callback: async () => { },
|
|
262
|
+
});
|
|
263
|
+
const schema = {
|
|
264
|
+
[UserCreatedEvent.key]: [UserCreatedEvent, [sub1, sub2, sub3]],
|
|
265
|
+
};
|
|
266
|
+
matador = new Matador({ transport, topology, schema });
|
|
267
|
+
await matador.start();
|
|
268
|
+
const event = new UserCreatedEvent({
|
|
269
|
+
userId: '123',
|
|
270
|
+
email: 'test@example.com',
|
|
271
|
+
});
|
|
272
|
+
const result = await matador.send(event);
|
|
273
|
+
expect(result.subscribersSent).toBe(3);
|
|
274
|
+
});
|
|
275
|
+
it('should include correlation ID in send', async () => {
|
|
276
|
+
const topology = TopologyBuilder.create()
|
|
277
|
+
.withNamespace('test')
|
|
278
|
+
.addQueue('events')
|
|
279
|
+
.build();
|
|
280
|
+
const subscriber = createSubscriber({
|
|
281
|
+
name: 'handle-user',
|
|
282
|
+
description: 'Handles user events',
|
|
283
|
+
callback: async () => { },
|
|
284
|
+
});
|
|
285
|
+
const schema = {
|
|
286
|
+
[UserCreatedEvent.key]: [UserCreatedEvent, [subscriber]],
|
|
287
|
+
};
|
|
288
|
+
matador = new Matador({ transport, topology, schema });
|
|
289
|
+
await matador.start();
|
|
290
|
+
const event = new UserCreatedEvent({
|
|
291
|
+
userId: '123',
|
|
292
|
+
email: 'test@example.com',
|
|
293
|
+
});
|
|
294
|
+
const result = await matador.send(event, {
|
|
295
|
+
correlationId: 'request-456',
|
|
296
|
+
});
|
|
297
|
+
expect(result.subscribersSent).toBe(1);
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
describe('shutdown', () => {
|
|
301
|
+
it('should gracefully shutdown', async () => {
|
|
302
|
+
const topology = TopologyBuilder.create()
|
|
303
|
+
.withNamespace('test')
|
|
304
|
+
.addQueue('events')
|
|
305
|
+
.build();
|
|
306
|
+
const subscriber = createSubscriber({
|
|
307
|
+
name: 'handle-user',
|
|
308
|
+
description: 'Handles user events',
|
|
309
|
+
callback: async () => { },
|
|
310
|
+
});
|
|
311
|
+
const schema = {
|
|
312
|
+
[UserCreatedEvent.key]: [UserCreatedEvent, [subscriber]],
|
|
313
|
+
};
|
|
314
|
+
matador = new Matador({ transport, topology, schema });
|
|
315
|
+
await matador.start();
|
|
316
|
+
await matador.shutdown();
|
|
317
|
+
expect(matador.isConnected()).toBe(false);
|
|
318
|
+
});
|
|
319
|
+
it('should be idempotent', async () => {
|
|
320
|
+
const topology = TopologyBuilder.create()
|
|
321
|
+
.withNamespace('test')
|
|
322
|
+
.addQueue('events')
|
|
323
|
+
.build();
|
|
324
|
+
const subscriber = createSubscriber({
|
|
325
|
+
name: 'handle-user',
|
|
326
|
+
description: 'Handles user events',
|
|
327
|
+
callback: async () => { },
|
|
328
|
+
});
|
|
329
|
+
const schema = {
|
|
330
|
+
[UserCreatedEvent.key]: [UserCreatedEvent, [subscriber]],
|
|
331
|
+
};
|
|
332
|
+
matador = new Matador({ transport, topology, schema });
|
|
333
|
+
await matador.start();
|
|
334
|
+
await matador.shutdown();
|
|
335
|
+
await matador.shutdown(); // Should not throw
|
|
336
|
+
expect(matador.isConnected()).toBe(false);
|
|
337
|
+
});
|
|
338
|
+
it('should reject send after shutdown initiated', async () => {
|
|
339
|
+
const topology = TopologyBuilder.create()
|
|
340
|
+
.withNamespace('test')
|
|
341
|
+
.addQueue('events')
|
|
342
|
+
.build();
|
|
343
|
+
const subscriber = createSubscriber({
|
|
344
|
+
name: 'handle-user',
|
|
345
|
+
description: 'Handles user events',
|
|
346
|
+
callback: async () => { },
|
|
347
|
+
});
|
|
348
|
+
const schema = {
|
|
349
|
+
[UserCreatedEvent.key]: [UserCreatedEvent, [subscriber]],
|
|
350
|
+
};
|
|
351
|
+
matador = new Matador({ transport, topology, schema });
|
|
352
|
+
await matador.start();
|
|
353
|
+
// Initiate shutdown but don't await
|
|
354
|
+
const shutdownPromise = matador.shutdown();
|
|
355
|
+
const event = new UserCreatedEvent({
|
|
356
|
+
userId: '123',
|
|
357
|
+
email: 'test@example.com',
|
|
358
|
+
});
|
|
359
|
+
// Send should fail during/after shutdown
|
|
360
|
+
await shutdownPromise;
|
|
361
|
+
expect(matador.send(event)).rejects.toThrow();
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
describe('idle state', () => {
|
|
365
|
+
it('should report idle when no processing', async () => {
|
|
366
|
+
const topology = TopologyBuilder.create()
|
|
367
|
+
.withNamespace('test')
|
|
368
|
+
.addQueue('events')
|
|
369
|
+
.build();
|
|
370
|
+
const subscriber = createSubscriber({
|
|
371
|
+
name: 'handle-user',
|
|
372
|
+
description: 'Handles user events',
|
|
373
|
+
callback: async () => { },
|
|
374
|
+
});
|
|
375
|
+
const schema = {
|
|
376
|
+
[UserCreatedEvent.key]: [UserCreatedEvent, [subscriber]],
|
|
377
|
+
};
|
|
378
|
+
matador = new Matador({ transport, topology, schema });
|
|
379
|
+
await matador.start();
|
|
380
|
+
expect(matador.isIdle()).toBe(true);
|
|
381
|
+
});
|
|
382
|
+
it('should return handlers state', async () => {
|
|
383
|
+
const topology = TopologyBuilder.create()
|
|
384
|
+
.withNamespace('test')
|
|
385
|
+
.addQueue('events')
|
|
386
|
+
.build();
|
|
387
|
+
const subscriber = createSubscriber({
|
|
388
|
+
name: 'handle-user',
|
|
389
|
+
description: 'Handles user events',
|
|
390
|
+
callback: async () => { },
|
|
391
|
+
});
|
|
392
|
+
const schema = {
|
|
393
|
+
[UserCreatedEvent.key]: [UserCreatedEvent, [subscriber]],
|
|
394
|
+
};
|
|
395
|
+
matador = new Matador({ transport, topology, schema });
|
|
396
|
+
await matador.start();
|
|
397
|
+
const state = matador.getHandlersState();
|
|
398
|
+
expect(state.isIdle).toBe(true);
|
|
399
|
+
expect(state.eventsBeingProcessed).toBe(0);
|
|
400
|
+
expect(state.eventsBeingEnqueued).toBe(0);
|
|
401
|
+
});
|
|
402
|
+
it('should wait for idle', async () => {
|
|
403
|
+
const topology = TopologyBuilder.create()
|
|
404
|
+
.withNamespace('test')
|
|
405
|
+
.addQueue('events')
|
|
406
|
+
.build();
|
|
407
|
+
const subscriber = createSubscriber({
|
|
408
|
+
name: 'handle-user',
|
|
409
|
+
description: 'Handles user events',
|
|
410
|
+
callback: async () => { },
|
|
411
|
+
});
|
|
412
|
+
const schema = {
|
|
413
|
+
[UserCreatedEvent.key]: [UserCreatedEvent, [subscriber]],
|
|
414
|
+
};
|
|
415
|
+
matador = new Matador({ transport, topology, schema });
|
|
416
|
+
await matador.start();
|
|
417
|
+
const isIdle = await matador.waitForIdle(1000);
|
|
418
|
+
expect(isIdle).toBe(true);
|
|
419
|
+
});
|
|
420
|
+
});
|
|
421
|
+
describe('consuming from queues', () => {
|
|
422
|
+
it('should subscribe to specified queues', async () => {
|
|
423
|
+
const topology = TopologyBuilder.create()
|
|
424
|
+
.withNamespace('test')
|
|
425
|
+
.addQueue('events')
|
|
426
|
+
.addQueue('notifications')
|
|
427
|
+
.build();
|
|
428
|
+
const subscriber = createSubscriber({
|
|
429
|
+
name: 'handle-user',
|
|
430
|
+
description: 'Handles user events',
|
|
431
|
+
callback: async () => { },
|
|
432
|
+
});
|
|
433
|
+
const schema = {
|
|
434
|
+
[UserCreatedEvent.key]: [UserCreatedEvent, [subscriber]],
|
|
435
|
+
};
|
|
436
|
+
matador = new Matador({
|
|
437
|
+
transport,
|
|
438
|
+
topology,
|
|
439
|
+
schema,
|
|
440
|
+
consumeFrom: ['events'],
|
|
441
|
+
});
|
|
442
|
+
await matador.start();
|
|
443
|
+
expect(matador.isConnected()).toBe(true);
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
});
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { type Logger } from '../hooks/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Shutdown state.
|
|
4
|
+
*/
|
|
5
|
+
export type ShutdownState = 'running' | 'stopping-receive' | 'waiting-handlers' | 'stopping-enqueue' | 'disconnecting' | 'stopped';
|
|
6
|
+
/**
|
|
7
|
+
* Configuration for shutdown manager.
|
|
8
|
+
*/
|
|
9
|
+
export interface ShutdownConfig {
|
|
10
|
+
/** Timeout for graceful shutdown in milliseconds */
|
|
11
|
+
readonly gracefulShutdownTimeout: number;
|
|
12
|
+
/** Polling interval when waiting for handlers to idle */
|
|
13
|
+
readonly idlePollingInterval: number;
|
|
14
|
+
/** Logger for shutdown events (defaults to console) */
|
|
15
|
+
readonly logger: Logger;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Default shutdown configuration.
|
|
19
|
+
*/
|
|
20
|
+
export declare const defaultShutdownConfig: ShutdownConfig;
|
|
21
|
+
/**
|
|
22
|
+
* Handler state tracking.
|
|
23
|
+
*/
|
|
24
|
+
export interface HandlersState {
|
|
25
|
+
readonly eventsBeingProcessed: number;
|
|
26
|
+
readonly eventsBeingEnqueued: number;
|
|
27
|
+
readonly isIdle: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Manages graceful shutdown of Matador.
|
|
31
|
+
*
|
|
32
|
+
* Shutdown sequence:
|
|
33
|
+
* 1. Stop receiving new messages
|
|
34
|
+
* 2. Wait for in-flight processing to complete
|
|
35
|
+
* 3. Stop accepting new enqueue requests
|
|
36
|
+
* 4. Disconnect transport
|
|
37
|
+
*/
|
|
38
|
+
export declare class ShutdownManager {
|
|
39
|
+
private readonly getEnqueueCount;
|
|
40
|
+
private readonly stopReceiving;
|
|
41
|
+
private readonly disconnectTransport;
|
|
42
|
+
private _state;
|
|
43
|
+
private readonly config;
|
|
44
|
+
private eventsBeingProcessed;
|
|
45
|
+
private acceptingEnqueue;
|
|
46
|
+
constructor(getEnqueueCount: () => number, stopReceiving: () => Promise<void>, disconnectTransport: () => Promise<void>, config?: Partial<ShutdownConfig>);
|
|
47
|
+
/**
|
|
48
|
+
* Current shutdown state.
|
|
49
|
+
*/
|
|
50
|
+
get state(): ShutdownState;
|
|
51
|
+
/**
|
|
52
|
+
* Whether enqueue is currently allowed.
|
|
53
|
+
*/
|
|
54
|
+
get isEnqueueAllowed(): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Gets current handler state.
|
|
57
|
+
*/
|
|
58
|
+
getHandlersState(): HandlersState;
|
|
59
|
+
/**
|
|
60
|
+
* Increment processing counter.
|
|
61
|
+
*/
|
|
62
|
+
incrementProcessing(): void;
|
|
63
|
+
/**
|
|
64
|
+
* Decrement processing counter.
|
|
65
|
+
*/
|
|
66
|
+
decrementProcessing(): void;
|
|
67
|
+
/**
|
|
68
|
+
* Performs graceful shutdown.
|
|
69
|
+
*/
|
|
70
|
+
shutdown(): Promise<void>;
|
|
71
|
+
/**
|
|
72
|
+
* Forcefully stops without waiting.
|
|
73
|
+
*/
|
|
74
|
+
forceStop(): Promise<void>;
|
|
75
|
+
private waitForIdle;
|
|
76
|
+
private sleep;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=shutdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shutdown.d.ts","sourceRoot":"","sources":["../../src/core/shutdown.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAiB,MAAM,mBAAmB,CAAC;AAE/D;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,SAAS,GACT,kBAAkB,GAClB,kBAAkB,GAClB,kBAAkB,GAClB,eAAe,GACf,SAAS,CAAC;AAEd;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,oDAAoD;IACpD,QAAQ,CAAC,uBAAuB,EAAE,MAAM,CAAC;IAEzC,yDAAyD;IACzD,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IAErC,uDAAuD;IACvD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,eAAO,MAAM,qBAAqB,EAAE,cAInC,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,qBAAa,eAAe;IAOxB,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IARtC,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,gBAAgB,CAAQ;gBAGb,eAAe,EAAE,MAAM,MAAM,EAC7B,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAClC,mBAAmB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EACzD,MAAM,GAAE,OAAO,CAAC,cAAc,CAAM;IAKtC;;OAEG;IACH,IAAI,KAAK,IAAI,aAAa,CAEzB;IAED;;OAEG;IACH,IAAI,gBAAgB,IAAI,OAAO,CAE9B;IAED;;OAEG;IACH,gBAAgB,IAAI,aAAa;IASjC;;OAEG;IACH,mBAAmB,IAAI,IAAI;IAI3B;;OAEG;IACH,mBAAmB,IAAI,IAAI;IAI3B;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB/B;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;YAOlB,WAAW;IAezB,OAAO,CAAC,KAAK;CAGd"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { consoleLogger } from '../hooks/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Default shutdown configuration.
|
|
4
|
+
*/
|
|
5
|
+
export const defaultShutdownConfig = {
|
|
6
|
+
gracefulShutdownTimeout: 30000,
|
|
7
|
+
idlePollingInterval: 1000,
|
|
8
|
+
logger: consoleLogger,
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Manages graceful shutdown of Matador.
|
|
12
|
+
*
|
|
13
|
+
* Shutdown sequence:
|
|
14
|
+
* 1. Stop receiving new messages
|
|
15
|
+
* 2. Wait for in-flight processing to complete
|
|
16
|
+
* 3. Stop accepting new enqueue requests
|
|
17
|
+
* 4. Disconnect transport
|
|
18
|
+
*/
|
|
19
|
+
export class ShutdownManager {
|
|
20
|
+
getEnqueueCount;
|
|
21
|
+
stopReceiving;
|
|
22
|
+
disconnectTransport;
|
|
23
|
+
_state = 'running';
|
|
24
|
+
config;
|
|
25
|
+
eventsBeingProcessed = 0;
|
|
26
|
+
acceptingEnqueue = true;
|
|
27
|
+
constructor(getEnqueueCount, stopReceiving, disconnectTransport, config = {}) {
|
|
28
|
+
this.getEnqueueCount = getEnqueueCount;
|
|
29
|
+
this.stopReceiving = stopReceiving;
|
|
30
|
+
this.disconnectTransport = disconnectTransport;
|
|
31
|
+
this.config = { ...defaultShutdownConfig, ...config };
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Current shutdown state.
|
|
35
|
+
*/
|
|
36
|
+
get state() {
|
|
37
|
+
return this._state;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Whether enqueue is currently allowed.
|
|
41
|
+
*/
|
|
42
|
+
get isEnqueueAllowed() {
|
|
43
|
+
return this.acceptingEnqueue;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Gets current handler state.
|
|
47
|
+
*/
|
|
48
|
+
getHandlersState() {
|
|
49
|
+
const eventsBeingEnqueued = this.getEnqueueCount();
|
|
50
|
+
return {
|
|
51
|
+
eventsBeingProcessed: this.eventsBeingProcessed,
|
|
52
|
+
eventsBeingEnqueued,
|
|
53
|
+
isIdle: this.eventsBeingProcessed === 0 && eventsBeingEnqueued === 0,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Increment processing counter.
|
|
58
|
+
*/
|
|
59
|
+
incrementProcessing() {
|
|
60
|
+
this.eventsBeingProcessed++;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Decrement processing counter.
|
|
64
|
+
*/
|
|
65
|
+
decrementProcessing() {
|
|
66
|
+
this.eventsBeingProcessed--;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Performs graceful shutdown.
|
|
70
|
+
*/
|
|
71
|
+
async shutdown() {
|
|
72
|
+
if (this._state !== 'running') {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// 1. Stop receiving new messages
|
|
76
|
+
this._state = 'stopping-receive';
|
|
77
|
+
await this.stopReceiving();
|
|
78
|
+
// 2. Wait for handlers to idle
|
|
79
|
+
this._state = 'waiting-handlers';
|
|
80
|
+
await this.waitForIdle();
|
|
81
|
+
// 3. Stop accepting new enqueue requests
|
|
82
|
+
this._state = 'stopping-enqueue';
|
|
83
|
+
this.acceptingEnqueue = false;
|
|
84
|
+
// 4. Disconnect transport
|
|
85
|
+
this._state = 'disconnecting';
|
|
86
|
+
await this.disconnectTransport();
|
|
87
|
+
this._state = 'stopped';
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Forcefully stops without waiting.
|
|
91
|
+
*/
|
|
92
|
+
async forceStop() {
|
|
93
|
+
this.acceptingEnqueue = false;
|
|
94
|
+
await this.stopReceiving();
|
|
95
|
+
await this.disconnectTransport();
|
|
96
|
+
this._state = 'stopped';
|
|
97
|
+
}
|
|
98
|
+
async waitForIdle() {
|
|
99
|
+
const deadline = Date.now() + this.config.gracefulShutdownTimeout;
|
|
100
|
+
while (!this.getHandlersState().isIdle) {
|
|
101
|
+
if (Date.now() > deadline) {
|
|
102
|
+
this.config.logger.warn(`[Matador] ⚠️ Shutdown timeout reached with ${this.eventsBeingProcessed} events still processing`);
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
await this.sleep(this.config.idlePollingInterval);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
sleep(ms) {
|
|
109
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shutdown.test.d.ts","sourceRoot":"","sources":["../../src/core/shutdown.test.ts"],"names":[],"mappings":""}
|