1 | import amqp from "amqplib" |
2 |
|
3 | |
4 | * Publish message |
5 | * Publish one message to an AMQP 0-9-1 exchange (RabbitMQ) and wait for the broker's confirm. Leave exchange empty to send straight to the queue named by routing_key. A string payload is sent as-is, anything else as JSON. routed is false when no queue received it. |
6 | */ |
7 | export async function main( |
8 | auth: RT.Amqp, |
9 | routing_key: string, |
10 | payload: any, |
11 | exchange: string | undefined, |
12 | headers: { [key: string]: string } | undefined, |
13 | persistent: boolean = false |
14 | ) { |
15 | if (payload === undefined) throw new Error("payload is required") |
16 | const anonymous = !auth.username && !auth.password |
17 | const conn = await amqp.connect({ |
18 | protocol: auth.tls ? "amqps" : "amqp", |
19 | hostname: auth.host, |
20 | port: auth.port || (auth.tls ? 5671 : 5672), |
21 | |
22 | username: anonymous ? "guest" : (auth.username ?? ""), |
23 | password: anonymous ? "guest" : (auth.password ?? ""), |
24 | |
25 | vhost: encodeURIComponent(auth.vhost || "/"), |
26 | }) |
27 | try { |
28 | |
29 | |
30 | |
31 | const failed = new Promise<never>((_, reject) => conn.once("error", reject)) |
32 | failed.catch(() => {}) |
33 | const channel = await Promise.race([conn.createConfirmChannel(), failed]) |
34 | const closed = new Promise<never>((_, reject) => |
35 | channel.once("error", reject) |
36 | ) |
37 | closed.catch(() => {}) |
38 | |
39 | let routed = true |
40 | channel.on("return", () => (routed = false)) |
41 | const text = typeof payload === "string" |
42 | channel.publish( |
43 | exchange || "", |
44 | routing_key, |
45 | Buffer.from(text ? payload : JSON.stringify(payload)), |
46 | { |
47 | mandatory: true, |
48 | persistent, |
49 | contentType: text ? "text/plain" : "application/json", |
50 | headers: Object.fromEntries( |
51 | Object.entries(headers ?? {}).map(([k, v]) => [ |
52 | k, |
53 | typeof v === "string" ? v : JSON.stringify(v), |
54 | ]) |
55 | ), |
56 | } |
57 | ) |
58 | await Promise.race([channel.waitForConfirms(), failed, closed]) |
59 | return { exchange: exchange || "", routing_key, routed } |
60 | } finally { |
61 | |
62 | await conn.close().catch(() => {}) |
63 | } |
64 | } |
65 |
|