@cargolift-cdi/util-rabbitmq 0.2.21 → 0.2.22
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.
|
@@ -4,16 +4,15 @@ interface RabbitMQTopologyRetry {
|
|
|
4
4
|
}
|
|
5
5
|
export interface RabbitMQTopology {
|
|
6
6
|
exchange: string;
|
|
7
|
-
type: string;
|
|
8
7
|
queues: RabbitMQTopologyQueue[];
|
|
9
8
|
alternateExchange?: {
|
|
10
9
|
exchange: string;
|
|
11
10
|
queue: string;
|
|
12
11
|
};
|
|
13
|
-
deadLetterExchange
|
|
12
|
+
deadLetterExchange?: {
|
|
14
13
|
exchange: string;
|
|
15
14
|
};
|
|
16
|
-
retry
|
|
15
|
+
retry?: {
|
|
17
16
|
exchanges: RabbitMQTopologyRetry;
|
|
18
17
|
policy_short_ms: number;
|
|
19
18
|
policy_long_ms: number;
|
|
@@ -22,11 +21,11 @@ export interface RabbitMQTopology {
|
|
|
22
21
|
export interface RabbitMQTopologyQueue {
|
|
23
22
|
queue: string;
|
|
24
23
|
routingKey: string;
|
|
25
|
-
deadLetterQueue
|
|
24
|
+
deadLetterQueue?: {
|
|
26
25
|
name: string;
|
|
27
26
|
routingKey: string;
|
|
28
27
|
};
|
|
29
|
-
retryQueues
|
|
28
|
+
retryQueues?: RabbitMQTopologyRetry;
|
|
30
29
|
}
|
|
31
30
|
/**
|
|
32
31
|
* RabbitMQTopologyService
|
|
@@ -38,7 +37,7 @@ export declare class RabbitMQTopologyService {
|
|
|
38
37
|
/**
|
|
39
38
|
* Cria exchanges, AE (fanout), DLX (topic), unrouteable queue e exchanges de retry (inbound).
|
|
40
39
|
*/
|
|
41
|
-
|
|
40
|
+
setupExchange(topology: RabbitMQTopology): Promise<void>;
|
|
42
41
|
/**
|
|
43
42
|
* Cria filas por sistema e faz binds necessários. Para inbound, cria filas de retry com TTLs.
|
|
44
43
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rabbitmq-topology.service.d.ts","sourceRoot":"","sources":["../src/rabbitmq-topology.service.ts"],"names":[],"mappings":"AAIA,UAAU,qBAAqB;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,
|
|
1
|
+
{"version":3,"file":"rabbitmq-topology.service.d.ts","sourceRoot":"","sources":["../src/rabbitmq-topology.service.ts"],"names":[],"mappings":"AAIA,UAAU,qBAAqB;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,qBAAqB,EAAE,CAAC;IAChC,iBAAiB,CAAC,EAAE;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,kBAAkB,CAAC,EAAE;QACnB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IAEF,KAAK,CAAC,EAAE;QACN,SAAS,EAAE,qBAAqB,CAAC;QACjC,eAAe,EAAE,MAAM,CAAC;QACxB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;CAGH;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,WAAW,CAAC,EAAE,qBAAqB,CAAC;CACrC;AAED;;;;GAIG;AACH,qBACa,uBAAuB;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4C;IAEnE;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IA+C9D;;OAEG;IACG,UAAU,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;CAuF9D"}
|
|
@@ -19,7 +19,7 @@ let RabbitMQTopologyService = RabbitMQTopologyService_1 = class RabbitMQTopology
|
|
|
19
19
|
/**
|
|
20
20
|
* Cria exchanges, AE (fanout), DLX (topic), unrouteable queue e exchanges de retry (inbound).
|
|
21
21
|
*/
|
|
22
|
-
async
|
|
22
|
+
async setupExchange(topology) {
|
|
23
23
|
const ch = await getRabbitConnectionManager().createChannel();
|
|
24
24
|
try {
|
|
25
25
|
// Alternate Exchange (inbound.ae)
|
|
@@ -47,7 +47,7 @@ let RabbitMQTopologyService = RabbitMQTopologyService_1 = class RabbitMQTopology
|
|
|
47
47
|
await ch.assertQueue(topology.alternateExchange.queue, { durable: true });
|
|
48
48
|
await ch.bindQueue(topology.alternateExchange.queue, topology.alternateExchange.exchange, "");
|
|
49
49
|
}
|
|
50
|
-
this.logger.log(`[
|
|
50
|
+
this.logger.log(`[RabbitMQ] Topology Queue = queue exchange: ${topology.exchange} ` +
|
|
51
51
|
(topology.alternateExchange ? ` | AE: ${topology.alternateExchange.exchange}` : "") +
|
|
52
52
|
(topology.deadLetterExchange ? ` | DLX: ${topology.deadLetterExchange.exchange}` : ""));
|
|
53
53
|
await this.setupQueue(topology);
|
|
@@ -67,32 +67,18 @@ let RabbitMQTopologyService = RabbitMQTopologyService_1 = class RabbitMQTopology
|
|
|
67
67
|
try {
|
|
68
68
|
for (const queue of topology.queues) {
|
|
69
69
|
// Dead Letter Queue (inbound.sistema.dlq)
|
|
70
|
-
await ch.assertQueue(queue.deadLetterQueue.name, { durable: true });
|
|
71
|
-
// Fila principal (inbound.sistema)
|
|
72
|
-
// x-dead-letter-exchange: (inbound.dlx)
|
|
73
|
-
// x-dead-letter-routing-key: (integration.sistema.dead)
|
|
74
|
-
await ch.assertQueue(queue.queue, {
|
|
75
|
-
durable: true,
|
|
76
|
-
arguments: {
|
|
77
|
-
"x-dead-letter-exchange": topology.deadLetterExchange?.exchange,
|
|
78
|
-
"x-dead-letter-routing-key": queue.deadLetterQueue?.routingKey,
|
|
79
|
-
},
|
|
80
|
-
});
|
|
81
|
-
await ch.bindQueue(queue.queue, topology.exchange, queue.routingKey);
|
|
82
|
-
await ch.bindQueue(queue.deadLetterQueue.name, topology.deadLetterExchange.exchange, queue.deadLetterQueue.routingKey);
|
|
83
70
|
try {
|
|
84
|
-
|
|
85
|
-
durable: true
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
await ch.assertQueue(queue.retryQueues.long, {
|
|
71
|
+
if (queue.deadLetterQueue) {
|
|
72
|
+
await ch.assertQueue(queue.deadLetterQueue.name, { durable: true });
|
|
73
|
+
}
|
|
74
|
+
// Fila principal (inbound.sistema)
|
|
75
|
+
// x-dead-letter-exchange: (inbound.dlx)
|
|
76
|
+
// x-dead-letter-routing-key: (integration.sistema.dead)
|
|
77
|
+
await ch.assertQueue(queue.queue, {
|
|
92
78
|
durable: true,
|
|
93
79
|
arguments: {
|
|
94
|
-
"x-
|
|
95
|
-
"x-dead-letter-
|
|
80
|
+
"x-dead-letter-exchange": topology.deadLetterExchange?.exchange || "",
|
|
81
|
+
"x-dead-letter-routing-key": queue.deadLetterQueue?.routingKey,
|
|
96
82
|
},
|
|
97
83
|
});
|
|
98
84
|
}
|
|
@@ -104,9 +90,43 @@ let RabbitMQTopologyService = RabbitMQTopologyService_1 = class RabbitMQTopology
|
|
|
104
90
|
}
|
|
105
91
|
throw e;
|
|
106
92
|
}
|
|
107
|
-
await ch.bindQueue(queue.
|
|
108
|
-
|
|
109
|
-
|
|
93
|
+
await ch.bindQueue(queue.queue, topology.exchange, queue.routingKey);
|
|
94
|
+
if (topology.deadLetterExchange && queue.deadLetterQueue) {
|
|
95
|
+
await ch.bindQueue(queue.deadLetterQueue.name, topology.deadLetterExchange.exchange || "", queue.deadLetterQueue.routingKey);
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
if (topology.retry && queue.retryQueues) {
|
|
99
|
+
await ch.assertQueue(queue.retryQueues.short, {
|
|
100
|
+
durable: true,
|
|
101
|
+
arguments: {
|
|
102
|
+
"x-message-ttl": topology.retry.policy_short_ms,
|
|
103
|
+
"x-dead-letter-exchange": topology.exchange,
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
await ch.assertQueue(queue.retryQueues.long, {
|
|
107
|
+
durable: true,
|
|
108
|
+
arguments: {
|
|
109
|
+
"x-message-ttl": topology.retry.policy_long_ms,
|
|
110
|
+
"x-dead-letter-exchange": topology.exchange,
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch (e) {
|
|
116
|
+
const msg = String(e?.message ?? e ?? "");
|
|
117
|
+
if (/PRECONDITION[_-]FAILED|inequivalent arg/i.test(msg)) {
|
|
118
|
+
// Sinaliza claramente drift de topologia
|
|
119
|
+
throw new Error(`RabbitMQ topology drift: ${msg}. Filas de retry existentes para '${queue.queue}' com TTL/args diferentes dos configurados. Alinhe variáveis ou remova filas manualmente.`);
|
|
120
|
+
}
|
|
121
|
+
throw e;
|
|
122
|
+
}
|
|
123
|
+
if (topology.retry && queue.retryQueues) {
|
|
124
|
+
await ch.bindQueue(queue.retryQueues.short, topology.retry.exchanges.short, queue.routingKey);
|
|
125
|
+
await ch.bindQueue(queue.retryQueues.long, topology.retry.exchanges.long, queue.routingKey);
|
|
126
|
+
}
|
|
127
|
+
this.logger.log(`[RabbitMQ] Topology Queue => queue ${queue.queue}` +
|
|
128
|
+
(queue.deadLetterQueue ? ` | DLQ: ${queue.deadLetterQueue.name}` : "") +
|
|
129
|
+
` | exchange: ${topology.exchange} | bind: ${queue.routingKey}`);
|
|
110
130
|
}
|
|
111
131
|
return "topology.queue";
|
|
112
132
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rabbitmq-topology.service.js","sourceRoot":"","sources":["../src/rabbitmq-topology.service.ts"],"names":[],"mappings":";;;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAEpD,OAAO,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"rabbitmq-topology.service.js","sourceRoot":"","sources":["../src/rabbitmq-topology.service.ts"],"names":[],"mappings":"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"}
|