@cargolift-cdi/util-rabbitmq 0.1.51 → 0.1.53
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.
|
@@ -10,12 +10,6 @@ export declare class RabbitMQPublisherService {
|
|
|
10
10
|
* - payload: corpo da mensagem
|
|
11
11
|
* - opts: opções opcionais: { exchange, exchangeType, routingKey, headers }
|
|
12
12
|
*/
|
|
13
|
-
emit(pattern: string, payload: any, opts?: {
|
|
14
|
-
exchange?: string;
|
|
15
|
-
exchangeType?: string;
|
|
16
|
-
routingKey?: string;
|
|
17
|
-
headers?: Record<string, any>;
|
|
18
|
-
}): Promise<void>;
|
|
19
13
|
/**
|
|
20
14
|
* Publica mensagem em exchange usando ConfirmChannel para garantir confirmação (publisher confirms).
|
|
21
15
|
* Boas práticas amqplib aplicadas:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rabbitmq-publisher.service.d.ts","sourceRoot":"","sources":["../src/rabbitmq-publisher.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAEhC,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAKjE,qBACa,wBAAwB;IAEO,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,oBAAoB;IAEvF;;;;;OAKG;
|
|
1
|
+
{"version":3,"file":"rabbitmq-publisher.service.d.ts","sourceRoot":"","sources":["../src/rabbitmq-publisher.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAEhC,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAKjE,qBACa,wBAAwB;IAEO,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,oBAAoB;IAEvF;;;;;OAKG;IAkIH;;;;;;;;;;;;;;OAcG;IACG,OAAO,CACX,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,GAAG,EACZ,IAAI,CAAC,EAAE;QACL,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,qBAAqB,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC;QACpD,cAAc,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;QACtC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,MAAM,CAAC;KACnC,GACA,OAAO,CAAC,IAAI,CAAC;CAiHjB"}
|
|
@@ -25,119 +25,134 @@ let RabbitMQPublisherService = class RabbitMQPublisherService {
|
|
|
25
25
|
* - payload: corpo da mensagem
|
|
26
26
|
* - opts: opções opcionais: { exchange, exchangeType, routingKey, headers }
|
|
27
27
|
*/
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
let channel = null;
|
|
28
|
+
/*
|
|
29
|
+
async emit(
|
|
30
|
+
pattern: string,
|
|
31
|
+
payload: any,
|
|
32
|
+
opts?: {
|
|
33
|
+
exchange?: string;
|
|
34
|
+
exchangeType?: string;
|
|
35
|
+
routingKey?: string;
|
|
36
|
+
headers?: Record<string, any>;
|
|
37
|
+
},
|
|
38
|
+
): Promise<void> {
|
|
39
|
+
const ctx = this.logger.getContext();
|
|
40
|
+
const headers: Record<string, any> = { ...(opts?.headers || {}) };
|
|
41
|
+
|
|
42
|
+
if (ctx?.correlation_id) headers['x-correlation-id'] = ctx.correlation_id;
|
|
43
|
+
if (ctx?.trace) headers['x-trace'] = ctx.trace;
|
|
44
|
+
if (ctx?.producer) headers['x-producer'] = ctx.producer;
|
|
45
|
+
|
|
46
|
+
headers['pattern'] = pattern;
|
|
47
|
+
const messageBody = { pattern, data: payload };
|
|
48
|
+
|
|
49
|
+
// URL do RabbitMQ (use a mesma que está no ClientsModule)
|
|
50
|
+
const url = process.env.RABBITMQ_URL;
|
|
51
|
+
if (!url) throw new Error('RABBITMQ_URL não definido');
|
|
52
|
+
|
|
53
|
+
const connection = await amqp.connect(url);
|
|
54
|
+
|
|
55
|
+
// Evita crash por "Unhandled 'error' event" e garante log com contexto atual
|
|
56
|
+
connection.on('error', (err) => {
|
|
58
57
|
try {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
this.logger?.error('AMQP connection error', err as any,
|
|
59
|
+
{
|
|
60
|
+
application: { name: "util-rabbitmq", function: "RabbitMQPublisherService", action: "emit" },
|
|
61
|
+
data: { rabbitmq: { url, queue: pattern } }
|
|
62
62
|
});
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
});
|
|
86
|
-
if (!published) {
|
|
87
|
-
// backpressure: aguardar 'drain' se necessário (simplificado)
|
|
88
|
-
await new Promise((res) => channel.once('drain', () => res()));
|
|
89
|
-
}
|
|
90
|
-
this.logger.info(`Mensagem publicada no exchange "${exchangeToUse}" com routingKey "${routingKey}"`, {
|
|
91
|
-
application: { name: "util-rabbitmq", function: "RabbitMQPublisherService", action: "emit" },
|
|
92
|
-
data: { rabbitmq: { queue: pattern, exchange: exchangeToUse, routingKey } },
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
// certifica que a fila existe antes de enviar diretamente
|
|
97
|
-
/*
|
|
98
|
-
await channel.assertQueue(pattern, queueOptions);
|
|
99
|
-
channel.sendToQueue(pattern, content, {
|
|
100
|
-
persistent: true,
|
|
101
|
-
headers,
|
|
102
|
-
});
|
|
103
|
-
*/
|
|
104
|
-
channel.sendToQueue(pattern, content, {
|
|
105
|
-
persistent: true,
|
|
106
|
-
headers,
|
|
107
|
-
});
|
|
108
|
-
this.logger.info(`Mensagem publicada na fila do RabbitMQ "${pattern}"`, {
|
|
109
|
-
application: { name: "util-rabbitmq", function: "RabbitMQPublisherService", action: "emit" },
|
|
110
|
-
data: { rabbitmq: { queue: pattern } },
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
await channel.close();
|
|
63
|
+
} catch { }
|
|
64
|
+
});
|
|
65
|
+
connection.on('close', () => {
|
|
66
|
+
// intentionally left blank
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
let channel: amqp.Channel | null = null;
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
channel = await connection.createChannel();
|
|
73
|
+
|
|
74
|
+
channel.on('error', (err) => {
|
|
75
|
+
// intentionally left blank
|
|
76
|
+
});
|
|
77
|
+
channel.on('close', () => {
|
|
78
|
+
// intentionally left blank
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Alinhar arguments da fila com o que já foi criado (ex.: x-dead-letter-exchange)
|
|
82
|
+
const queueArgs: Record<string, any> = {};
|
|
83
|
+
if (process.env.RABBITMQ_DLX) {
|
|
84
|
+
queueArgs['x-dead-letter-exchange'] = process.env.RABBITMQ_DLX;
|
|
114
85
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
86
|
+
|
|
87
|
+
// Declare a fila com os mesmos argumentos (se houver) para evitar PRECONDITION_FAILED
|
|
88
|
+
const queueOptions = Object.keys(queueArgs).length
|
|
89
|
+
? { durable: true, arguments: queueArgs }
|
|
90
|
+
: { durable: true };
|
|
91
|
+
|
|
92
|
+
const content = Buffer.from(JSON.stringify(messageBody));
|
|
93
|
+
|
|
94
|
+
// Prioridade: opts.exchange > variável de ambiente RABBITMQ_EXCHANGE > enviar direto para fila
|
|
95
|
+
const exchangeToUse = opts?.exchange ?? process.env.RABBITMQ_EXCHANGE;
|
|
96
|
+
const exchangeType = opts?.exchangeType ?? (process.env.RABBITMQ_EXCHANGE_TYPE as any) ?? 'direct';
|
|
97
|
+
const routingKey = opts?.routingKey ?? pattern;
|
|
98
|
+
|
|
99
|
+
if (exchangeToUse) {
|
|
100
|
+
await channel.assertExchange(exchangeToUse, exchangeType, { durable: true });
|
|
101
|
+
const published = channel.publish(exchangeToUse, routingKey, content, {
|
|
102
|
+
persistent: true,
|
|
103
|
+
headers,
|
|
104
|
+
});
|
|
105
|
+
if (!published) {
|
|
106
|
+
// backpressure: aguardar 'drain' se necessário (simplificado)
|
|
107
|
+
await new Promise<void>((res) => channel!.once('drain', () => res()));
|
|
108
|
+
}
|
|
109
|
+
this.logger.info(`Mensagem publicada no exchange "${exchangeToUse}" com routingKey "${routingKey}"`, {
|
|
110
|
+
application: { name: "util-rabbitmq", function: "RabbitMQPublisherService", action: "emit" },
|
|
111
|
+
data: { rabbitmq: { queue: pattern, exchange: exchangeToUse, routingKey } },
|
|
112
|
+
});
|
|
113
|
+
} else {
|
|
114
|
+
// certifica que a fila existe antes de enviar diretamente
|
|
115
|
+
|
|
116
|
+
// await channel.assertQueue(pattern, queueOptions);
|
|
117
|
+
// channel.sendToQueue(pattern, content, {
|
|
118
|
+
// persistent: true,
|
|
119
|
+
// headers,
|
|
120
|
+
// });
|
|
121
|
+
|
|
122
|
+
channel.sendToQueue(pattern, content, {
|
|
123
|
+
persistent: true,
|
|
124
|
+
headers,
|
|
125
|
+
});
|
|
126
|
+
this.logger.info(`Mensagem publicada na fila do RabbitMQ "${pattern}"`, {
|
|
127
|
+
application: { name: "util-rabbitmq", function: "RabbitMQPublisherService", action: "emit" },
|
|
128
|
+
data: { rabbitmq: { queue: pattern } },
|
|
129
|
+
});
|
|
122
130
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
131
|
+
|
|
132
|
+
await channel.close();
|
|
133
|
+
} catch (err) {
|
|
134
|
+
// Loga com contexto e relança para que o controller/filtro capture
|
|
135
|
+
this.logger.error(`Erro ao publicar mensagem no RabbitMQ "${pattern}"`, err as any, {
|
|
136
|
+
application: { name: "util-rabbitmq", function: "RabbitMQPublisherService", action: "emit" },
|
|
137
|
+
data: { rabbitmq: { queue: pattern } },
|
|
138
|
+
});
|
|
139
|
+
throw err;
|
|
140
|
+
} finally {
|
|
141
|
+
try {
|
|
142
|
+
if (channel) {
|
|
133
143
|
try {
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
144
|
+
await channel.close();
|
|
145
|
+
} catch { }
|
|
146
|
+
}
|
|
147
|
+
} catch { }
|
|
148
|
+
try {
|
|
149
|
+
await connection.close();
|
|
150
|
+
} catch {
|
|
151
|
+
// ignora erros ao fechar conexão
|
|
139
152
|
}
|
|
153
|
+
}
|
|
140
154
|
}
|
|
155
|
+
*/
|
|
141
156
|
/**
|
|
142
157
|
* Publica mensagem em exchange usando ConfirmChannel para garantir confirmação (publisher confirms).
|
|
143
158
|
* Boas práticas amqplib aplicadas:
|
|
@@ -247,7 +262,7 @@ let RabbitMQPublisherService = class RabbitMQPublisherService {
|
|
|
247
262
|
}
|
|
248
263
|
});
|
|
249
264
|
this.logger.info(`Mensagem publicada (publishConfirm) confirmada no exchange "${exchange}" routingKey "${routingKey}"`, {
|
|
250
|
-
application: {
|
|
265
|
+
application: { function: 'RabbitMQPublisherService', action: 'publish' },
|
|
251
266
|
data: { rabbitmq: { exchange, routingKey, pattern } },
|
|
252
267
|
});
|
|
253
268
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rabbitmq-publisher.service.js","sourceRoot":"","sources":["../src/rabbitmq-publisher.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEpD,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAEhC,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,CAAC;AAK7B,IAAM,wBAAwB,GAA9B,MAAM,wBAAwB;IACnC,gEAAgE;IAChE,YAA2D,MAA4B;QAA5B,WAAM,GAAN,MAAM,CAAsB;IAAI,CAAC;IAE5F;;;;;OAKG;
|
|
1
|
+
{"version":3,"file":"rabbitmq-publisher.service.js","sourceRoot":"","sources":["../src/rabbitmq-publisher.service.ts"],"names":[],"mappings":"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"}
|