@fedify/amqp 0.2.0 → 0.3.0-dev.17

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/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@fedify/amqp",
3
- "version": "0.2.0",
3
+ "version": "0.3.0-dev.17+484159bd",
4
4
  "description": "AMQP/RabbitMQ driver for Fedify",
5
5
  "keywords": [
6
6
  "fedify",
7
7
  "amqp",
8
8
  "rabbitmq"
9
9
  ],
10
+ "license": "MIT",
10
11
  "author": {
11
12
  "name": "Hong Minhee",
12
13
  "email": "hong@minhee.org",
@@ -17,45 +18,42 @@
17
18
  "type": "git",
18
19
  "url": "git+https://github.com/fedify-dev/amqp.git"
19
20
  },
20
- "license": "MIT",
21
21
  "bugs": {
22
22
  "url": "https://github.com/fedify-dev/amqp/issues"
23
23
  },
24
- "main": "./script/mod.js",
25
- "module": "./esm/mod.js",
26
- "types": "./types/mod.d.ts",
24
+ "funding": [
25
+ "https://github.com/sponsors/dahlia"
26
+ ],
27
+ "type": "module",
28
+ "main": "./dist/mod.js",
29
+ "module": "./dist/mod.js",
30
+ "types": "./dist/mod.d.ts",
27
31
  "exports": {
28
32
  ".": {
29
- "import": {
30
- "types": "./types/mod.d.ts",
31
- "default": "./esm/mod.js"
32
- },
33
- "require": {
34
- "types": "./types/mod.d.ts",
35
- "default": "./script/mod.js"
36
- }
33
+ "import": "./dist/mod.js",
34
+ "types": "./dist/mod.d.ts"
37
35
  },
38
- "./mq": {
39
- "import": {
40
- "types": "./types/src/mq.d.ts",
41
- "default": "./esm/src/mq.js"
42
- },
43
- "require": {
44
- "types": "./types/src/mq.d.ts",
45
- "default": "./script/src/mq.js"
46
- }
47
- }
36
+ "./package.json": "./package.json"
48
37
  },
49
- "funding": [
50
- "https://github.com/sponsors/dahlia"
51
- ],
52
- "dependencies": {
53
- "@fedify/fedify": "^1.5.0",
54
- "amqplib": "^0.10.4"
38
+ "peerDependencies": {
39
+ "@fedify/fedify": "^1.7.0-dev.887",
40
+ "amqplib": "^0.10.8"
55
41
  },
56
42
  "devDependencies": {
57
- "@types/node": "^20.9.0",
58
- "@types/amqplib": "0.10.6"
43
+ "@hongminhee/suite": "^0.6.3",
44
+ "@js-temporal/polyfill": "^0.5.1",
45
+ "@std/assert": "npm:@jsr/std__assert@^1.0.13",
46
+ "@std/async": "npm:@jsr/std__async@^1.0.13",
47
+ "@types/amqplib": "^0.10.7",
48
+ "tsdown": "^0.12.7",
49
+ "typescript": "^5.8.3"
59
50
  },
60
- "_generatedBy": "dnt@dev"
51
+ "scripts": {
52
+ "build": "tsdown",
53
+ "prepublish": "tsdown",
54
+ "test": "tsdown && node --experimental-transform-types --test",
55
+ "test:bun": "tsdown && bun test --timeout 15000",
56
+ "test:deno": "deno task test",
57
+ "test-all": "tsdown && node --experimental-transform-types --test && bun test --timeout 15000 && deno task test"
58
+ }
61
59
  }
package/src/mod.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./mq.ts";
package/src/mq.test.ts ADDED
@@ -0,0 +1,186 @@
1
+ import { suite } from "@hongminhee/suite";
2
+ import * as temporal from "@js-temporal/polyfill";
3
+ import { assert, assertEquals, assertFalse, assertGreater } from "@std/assert";
4
+ import { delay } from "@std/async/delay";
5
+ // @deno-types="npm:@types/amqplib"
6
+ import { type ChannelModel, connect } from "amqplib";
7
+ import process from "node:process";
8
+ import { AmqpMessageQueue } from "./mq.ts";
9
+
10
+ let Temporal: typeof temporal.Temporal;
11
+ if ("Temporal" in globalThis) {
12
+ Temporal = globalThis.Temporal;
13
+ } else {
14
+ Temporal = temporal.Temporal;
15
+ }
16
+
17
+ const test = suite(import.meta);
18
+
19
+ function getConnection(): Promise<ChannelModel> {
20
+ const url = process.env.AMQP_URL;
21
+ return connect(url ?? "amqp://localhost");
22
+ }
23
+
24
+ test("AmqpMessageQueue", {
25
+ sanitizeOps: false,
26
+ sanitizeExit: false,
27
+ sanitizeResources: false,
28
+ }, async () => {
29
+ const conn = await getConnection();
30
+ const conn2 = await getConnection();
31
+ const randomSuffix = Math.random().toString(36).substring(2);
32
+ const queue = `fedify_queue_${randomSuffix}`;
33
+ const delayedQueuePrefix = `fedify_delayed_${randomSuffix}_`;
34
+ const mq = new AmqpMessageQueue(conn, { queue, delayedQueuePrefix });
35
+ const mq2 = new AmqpMessageQueue(conn2, { queue, delayedQueuePrefix });
36
+
37
+ const messages1: string[] = [];
38
+ const messages2: string[] = [];
39
+ const allMessages: string[] = [];
40
+ const controller = new AbortController();
41
+ const listening = mq.listen((message: string) => {
42
+ messages1.push(message);
43
+ allMessages.push(message);
44
+ }, { signal: controller.signal });
45
+ const listening2 = mq2.listen((message: string) => {
46
+ messages2.push(message);
47
+ allMessages.push(message);
48
+ }, { signal: controller.signal });
49
+
50
+ await mq.enqueue("Hello, world!");
51
+
52
+ await waitFor(() => allMessages.length > 0, 15_000);
53
+
54
+ assertEquals(allMessages.includes("Hello, world!"), true);
55
+
56
+ // enqueue() with delay
57
+ const started = Date.now();
58
+ await mq.enqueue(
59
+ "Delayed message",
60
+ { delay: Temporal.Duration.from({ seconds: 3 }) },
61
+ );
62
+
63
+ await waitFor(() => allMessages.includes("Delayed message"), 15_000);
64
+
65
+ // listen() with delay
66
+ assertEquals(allMessages.includes("Delayed message"), true);
67
+ assertGreater(Date.now() - started, 3_000);
68
+
69
+ await mq.enqueueMany(["Message 1", "Message 2", "Message 3"]);
70
+
71
+ await waitFor(() =>
72
+ allMessages.includes("Message 1") &&
73
+ allMessages.includes("Message 2") &&
74
+ allMessages.includes("Message 3"), 15_000);
75
+
76
+ // listen() after enqueueMany()
77
+ assertEquals(allMessages.includes("Message 1"), true);
78
+ assertEquals(allMessages.includes("Message 2"), true);
79
+ assertEquals(allMessages.includes("Message 3"), true);
80
+
81
+ // enqueueMany() with delay
82
+ const manyStarted = Date.now();
83
+ await mq.enqueueMany(
84
+ ["Delayed batch 1", "Delayed batch 2"],
85
+ { delay: Temporal.Duration.from({ seconds: 3 }) },
86
+ );
87
+
88
+ await waitFor(() =>
89
+ allMessages.includes("Delayed batch 1") &&
90
+ allMessages.includes("Delayed batch 2"), 15_000);
91
+
92
+ // listen() after enqueueMany() with delay
93
+ assertEquals(allMessages.includes("Delayed batch 1"), true);
94
+ assertEquals(allMessages.includes("Delayed batch 2"), true);
95
+ assertGreater(Date.now() - manyStarted, 3_000);
96
+
97
+ controller.abort();
98
+ await listening;
99
+ await listening2;
100
+
101
+ await conn.close();
102
+ await conn2.close();
103
+ });
104
+
105
+ test(
106
+ "AmqpMessageQueue [nativeRetrial: false]",
107
+ { sanitizeOps: false, sanitizeExit: false, sanitizeResources: false },
108
+ async () => {
109
+ const conn = await getConnection();
110
+ const randomSuffix = Math.random().toString(36).substring(2);
111
+ const queue = `fedify_queue_${randomSuffix}`;
112
+ const delayedQueuePrefix = `fedify_delayed_${randomSuffix}_`;
113
+ const mq = new AmqpMessageQueue(conn, { queue, delayedQueuePrefix });
114
+ assertFalse(mq.nativeRetrial);
115
+
116
+ const controller = new AbortController();
117
+ let i = 0;
118
+ const listening = mq.listen((message: string) => {
119
+ if (message !== "Hello, world!") return;
120
+ if (i++ < 1) {
121
+ throw new Error("Test error to check native retrial");
122
+ }
123
+ }, { signal: controller.signal });
124
+
125
+ await mq.enqueue("Hello, world!");
126
+
127
+ await waitFor(() => i >= 1, 15_000);
128
+ assertEquals(i, 1);
129
+ await delay(5_000);
130
+
131
+ controller.abort();
132
+ await listening;
133
+ await conn.close();
134
+
135
+ assertEquals(i, 1);
136
+ },
137
+ );
138
+
139
+ test(
140
+ "AmqpMessageQueue [nativeRetrial: true]",
141
+ { sanitizeOps: false, sanitizeExit: false, sanitizeResources: false },
142
+ async () => {
143
+ const conn = await getConnection();
144
+ const randomSuffix = Math.random().toString(36).substring(2);
145
+ const queue = `fedify_queue_${randomSuffix}`;
146
+ const delayedQueuePrefix = `fedify_delayed_${randomSuffix}_`;
147
+ const mq = new AmqpMessageQueue(conn, {
148
+ queue,
149
+ delayedQueuePrefix,
150
+ nativeRetrial: true,
151
+ });
152
+ assert(mq.nativeRetrial);
153
+
154
+ const controller = new AbortController();
155
+ let i = 0;
156
+ const listening = mq.listen((message: string) => {
157
+ if (message !== "Hello, world!") return;
158
+ if (i++ < 1) {
159
+ throw new Error("Test error to check native retrial");
160
+ }
161
+ }, { signal: controller.signal });
162
+
163
+ await mq.enqueue("Hello, world!");
164
+
165
+ await waitFor(() => i > 1, 15_000);
166
+
167
+ controller.abort();
168
+ await listening;
169
+ await conn.close();
170
+
171
+ assertGreater(i, 1);
172
+ },
173
+ );
174
+
175
+ async function waitFor(
176
+ predicate: () => boolean,
177
+ timeoutMs: number,
178
+ ): Promise<void> {
179
+ const started = Date.now();
180
+ while (!predicate()) {
181
+ await delay(500);
182
+ if (Date.now() - started > timeoutMs) {
183
+ throw new Error("Timeout");
184
+ }
185
+ }
186
+ }
package/src/mq.ts ADDED
@@ -0,0 +1,214 @@
1
+ import type {
2
+ MessageQueue,
3
+ MessageQueueEnqueueOptions,
4
+ MessageQueueListenOptions,
5
+ } from "@fedify/fedify";
6
+ // @deno-types="npm:@types/amqplib@^0.10.7"
7
+ import type { Channel, ChannelModel } from "amqplib";
8
+ import { Buffer } from "node:buffer";
9
+
10
+ /**
11
+ * Options for {@link AmqpMessageQueue}.
12
+ */
13
+ export interface AmqpMessageQueueOptions {
14
+ /**
15
+ * The name of the queue to use. Defaults to `"fedify_queue"`.
16
+ * @default `"fedify_queue"`
17
+ */
18
+ queue?: string;
19
+
20
+ /**
21
+ * The prefix to use for the delayed queue. Defaults to `"fedify_delayed_"`.
22
+ * Defaults to `"fedify_delayed_"`.
23
+ * @default `"fedify_delayed_"`
24
+ */
25
+ delayedQueuePrefix?: string;
26
+
27
+ /**
28
+ * Whether the queue will survive a broker restart. Defaults to `true`.
29
+ * @default `true`
30
+ */
31
+ durable?: boolean;
32
+
33
+ /**
34
+ * Whether to use native retrial mechanism. If set to `true`, the queue will
35
+ * not acknowledge messages that are not processed successfully, allowing
36
+ * them to be retried later. If set to `false`, messages will be acknowledged
37
+ * whether they are processed successfully or not.
38
+ *
39
+ * Both approaches have their own advantages and disadvantages. With native
40
+ * retrials, much less chance of losing messages, but timing of retrials is
41
+ * less predictable. With non-native retrials, retrials are handled by Fedify
42
+ * itself, which allows for more control over the timing and behavior of
43
+ * retrials, but may result in lost messages if the process crashes before
44
+ * acknowledging the message.
45
+ * @default `false`
46
+ */
47
+ nativeRetrial?: boolean;
48
+ }
49
+
50
+ /**
51
+ * A message queue that uses AMQP.
52
+ *
53
+ * @example
54
+ * ``` typescript
55
+ * import { createFederation } from "@fedify/fedify";
56
+ * import { AmqpMessageQueue } from "@fedify/amqp";
57
+ * import { connect } from "amqplib";
58
+ *
59
+ * const federation = createFederation({
60
+ * queue: new AmqpMessageQueue(await connect("amqp://localhost")),
61
+ * // ... other configurations
62
+ * });
63
+ * ```
64
+ */
65
+ export class AmqpMessageQueue implements MessageQueue {
66
+ #connection: ChannelModel;
67
+ #queue: string;
68
+ #delayedQueuePrefix: string;
69
+ #durable: boolean;
70
+ #senderChannel?: Channel;
71
+
72
+ readonly nativeRetrial: boolean;
73
+
74
+ /**
75
+ * Creates a new `AmqpMessageQueue`.
76
+ * @param connection A connection to the AMQP server.
77
+ * @param options Options for the message queue.
78
+ */
79
+ constructor(
80
+ connection: ChannelModel,
81
+ options: AmqpMessageQueueOptions = {},
82
+ ) {
83
+ this.#connection = connection;
84
+ this.#queue = options.queue ?? "fedify_queue";
85
+ this.#delayedQueuePrefix = options.delayedQueuePrefix ?? "fedify_delayed_";
86
+ this.#durable = options.durable ?? true;
87
+ this.nativeRetrial = options.nativeRetrial ?? false;
88
+ }
89
+
90
+ async #prepareQueue(channel: Channel): Promise<void> {
91
+ await channel.assertQueue(this.#queue, {
92
+ durable: this.#durable,
93
+ });
94
+ }
95
+
96
+ async #getSenderChannel(): Promise<Channel> {
97
+ if (this.#senderChannel != null) return this.#senderChannel;
98
+ const channel = await this.#connection.createChannel();
99
+ this.#senderChannel = channel;
100
+ this.#prepareQueue(channel);
101
+ return channel;
102
+ }
103
+
104
+ async enqueue(
105
+ // deno-lint-ignore no-explicit-any
106
+ message: any,
107
+ options?: MessageQueueEnqueueOptions,
108
+ ): Promise<void> {
109
+ const channel = await this.#getSenderChannel();
110
+ const delay = options?.delay?.total("millisecond");
111
+ let queue: string;
112
+ if (delay == null || delay <= 0) {
113
+ queue = this.#queue;
114
+ } else {
115
+ const delayStr = delay.toLocaleString("en", { useGrouping: false });
116
+ queue = this.#delayedQueuePrefix + delayStr;
117
+ await channel.assertQueue(queue, {
118
+ autoDelete: true,
119
+ durable: this.#durable,
120
+ deadLetterExchange: "",
121
+ deadLetterRoutingKey: this.#queue,
122
+ messageTtl: delay,
123
+ });
124
+ }
125
+ channel.sendToQueue(
126
+ queue,
127
+ Buffer.from(JSON.stringify(message), "utf-8"),
128
+ {
129
+ persistent: this.#durable,
130
+ contentType: "application/json",
131
+ },
132
+ );
133
+ }
134
+
135
+ async enqueueMany(
136
+ // deno-lint-ignore no-explicit-any
137
+ messages: any[],
138
+ options?: MessageQueueEnqueueOptions,
139
+ ): Promise<void> {
140
+ const channel = await this.#getSenderChannel();
141
+ const delay = options?.delay?.total("millisecond");
142
+ let queue: string;
143
+ if (delay == null || delay <= 0) {
144
+ queue = this.#queue;
145
+ } else {
146
+ const delayStr = delay.toLocaleString("en", { useGrouping: false });
147
+ queue = this.#delayedQueuePrefix + delayStr;
148
+ await channel.assertQueue(queue, {
149
+ autoDelete: true,
150
+ durable: this.#durable,
151
+ deadLetterExchange: "",
152
+ deadLetterRoutingKey: this.#queue,
153
+ messageTtl: delay,
154
+ });
155
+ }
156
+
157
+ for (const message of messages) {
158
+ channel.sendToQueue(
159
+ queue,
160
+ Buffer.from(JSON.stringify(message), "utf-8"),
161
+ {
162
+ persistent: this.#durable,
163
+ contentType: "application/json",
164
+ },
165
+ );
166
+ }
167
+ }
168
+
169
+ async listen(
170
+ // deno-lint-ignore no-explicit-any
171
+ handler: (message: any) => void | Promise<void>,
172
+ options: MessageQueueListenOptions = {},
173
+ ): Promise<void> {
174
+ const channel = await this.#connection.createChannel();
175
+ await this.#prepareQueue(channel);
176
+ await channel.prefetch(1);
177
+ const reply = await channel.consume(this.#queue, (msg) => {
178
+ if (msg == null) return;
179
+ const message = JSON.parse(msg.content.toString("utf-8"));
180
+ try {
181
+ const result = handler(message);
182
+ if (result instanceof Promise) {
183
+ if (this.nativeRetrial) {
184
+ result
185
+ .then(() => channel.ack(msg))
186
+ .catch(() => channel.nack(msg, undefined, true));
187
+ } else {
188
+ result.finally(() => channel.ack(msg));
189
+ }
190
+ } else if (this.nativeRetrial) {
191
+ channel.ack(msg);
192
+ }
193
+ } catch {
194
+ if (this.nativeRetrial) {
195
+ channel.nack(msg, undefined, true);
196
+ }
197
+ } finally {
198
+ if (!this.nativeRetrial) {
199
+ channel.ack(msg);
200
+ }
201
+ }
202
+ }, {
203
+ noAck: false,
204
+ });
205
+ return await new Promise((resolve) => {
206
+ if (options.signal?.aborted) resolve();
207
+ options.signal?.addEventListener("abort", () => {
208
+ channel.cancel(reply.consumerTag).then(() => {
209
+ channel.close().then(() => resolve());
210
+ });
211
+ });
212
+ });
213
+ }
214
+ }
@@ -0,0 +1,7 @@
1
+ import { defineConfig } from "tsdown";
2
+
3
+ export default defineConfig({
4
+ entry: "mod.ts",
5
+ dts: true,
6
+ platform: "node",
7
+ });
package/esm/mod.js DELETED
@@ -1 +0,0 @@
1
- export * from "./src/mod.js";
package/esm/package.json DELETED
@@ -1,3 +0,0 @@
1
- {
2
- "type": "module"
3
- }
package/esm/src/mod.js DELETED
@@ -1 +0,0 @@
1
- export * from "./mq.js";
package/esm/src/mq.js DELETED
@@ -1,139 +0,0 @@
1
- var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
- if (kind === "m") throw new TypeError("Private method is not writable");
3
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
- };
7
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
- };
12
- var _AmqpMessageQueue_instances, _AmqpMessageQueue_connection, _AmqpMessageQueue_queue, _AmqpMessageQueue_delayedQueuePrefix, _AmqpMessageQueue_durable, _AmqpMessageQueue_senderChannel, _AmqpMessageQueue_prepareQueue, _AmqpMessageQueue_getSenderChannel;
13
- import { Buffer } from "node:buffer";
14
- /**
15
- * A message queue that uses AMQP.
16
- *
17
- * @example
18
- * ``` typescript
19
- * import { createFederation } from "@fedify/fedify";
20
- * import { AmqpMessageQueue } from "@fedify/amqp";
21
- * import { connect } from "amqplib";
22
- *
23
- * const federation = createFederation({
24
- * queue: new AmqpMessageQueue(await connect("amqp://localhost")),
25
- * // ... other configurations
26
- * });
27
- * ```
28
- */
29
- export class AmqpMessageQueue {
30
- /**
31
- * Creates a new `AmqpMessageQueue`.
32
- * @param connection A connection to the AMQP server.
33
- * @param options Options for the message queue.
34
- */
35
- constructor(connection, options = {}) {
36
- _AmqpMessageQueue_instances.add(this);
37
- _AmqpMessageQueue_connection.set(this, void 0);
38
- _AmqpMessageQueue_queue.set(this, void 0);
39
- _AmqpMessageQueue_delayedQueuePrefix.set(this, void 0);
40
- _AmqpMessageQueue_durable.set(this, void 0);
41
- _AmqpMessageQueue_senderChannel.set(this, void 0);
42
- __classPrivateFieldSet(this, _AmqpMessageQueue_connection, connection, "f");
43
- __classPrivateFieldSet(this, _AmqpMessageQueue_queue, options.queue ?? "fedify_queue", "f");
44
- __classPrivateFieldSet(this, _AmqpMessageQueue_delayedQueuePrefix, options.delayedQueuePrefix ?? "fedify_delayed_", "f");
45
- __classPrivateFieldSet(this, _AmqpMessageQueue_durable, options.durable ?? true, "f");
46
- }
47
- async enqueue(
48
- // deno-lint-ignore no-explicit-any
49
- message, options) {
50
- const channel = await __classPrivateFieldGet(this, _AmqpMessageQueue_instances, "m", _AmqpMessageQueue_getSenderChannel).call(this);
51
- const delay = options?.delay?.total("millisecond");
52
- let queue;
53
- if (delay == null || delay <= 0) {
54
- queue = __classPrivateFieldGet(this, _AmqpMessageQueue_queue, "f");
55
- }
56
- else {
57
- const delayStr = delay.toLocaleString("en", { useGrouping: false });
58
- queue = __classPrivateFieldGet(this, _AmqpMessageQueue_delayedQueuePrefix, "f") + delayStr;
59
- await channel.assertQueue(queue, {
60
- autoDelete: true,
61
- durable: __classPrivateFieldGet(this, _AmqpMessageQueue_durable, "f"),
62
- deadLetterExchange: "",
63
- deadLetterRoutingKey: __classPrivateFieldGet(this, _AmqpMessageQueue_queue, "f"),
64
- messageTtl: delay,
65
- });
66
- }
67
- channel.sendToQueue(queue, Buffer.from(JSON.stringify(message), "utf-8"), {
68
- persistent: __classPrivateFieldGet(this, _AmqpMessageQueue_durable, "f"),
69
- contentType: "application/json",
70
- });
71
- }
72
- async enqueueMany(
73
- // deno-lint-ignore no-explicit-any
74
- messages, options) {
75
- const channel = await __classPrivateFieldGet(this, _AmqpMessageQueue_instances, "m", _AmqpMessageQueue_getSenderChannel).call(this);
76
- const delay = options?.delay?.total("millisecond");
77
- let queue;
78
- if (delay == null || delay <= 0) {
79
- queue = __classPrivateFieldGet(this, _AmqpMessageQueue_queue, "f");
80
- }
81
- else {
82
- const delayStr = delay.toLocaleString("en", { useGrouping: false });
83
- queue = __classPrivateFieldGet(this, _AmqpMessageQueue_delayedQueuePrefix, "f") + delayStr;
84
- await channel.assertQueue(queue, {
85
- autoDelete: true,
86
- durable: __classPrivateFieldGet(this, _AmqpMessageQueue_durable, "f"),
87
- deadLetterExchange: "",
88
- deadLetterRoutingKey: __classPrivateFieldGet(this, _AmqpMessageQueue_queue, "f"),
89
- messageTtl: delay,
90
- });
91
- }
92
- for (const message of messages) {
93
- channel.sendToQueue(queue, Buffer.from(JSON.stringify(message), "utf-8"), {
94
- persistent: __classPrivateFieldGet(this, _AmqpMessageQueue_durable, "f"),
95
- contentType: "application/json",
96
- });
97
- }
98
- }
99
- async listen(
100
- // deno-lint-ignore no-explicit-any
101
- handler, options = {}) {
102
- const channel = await __classPrivateFieldGet(this, _AmqpMessageQueue_connection, "f").createChannel();
103
- await __classPrivateFieldGet(this, _AmqpMessageQueue_instances, "m", _AmqpMessageQueue_prepareQueue).call(this, channel);
104
- await channel.prefetch(1);
105
- const reply = await channel.consume(__classPrivateFieldGet(this, _AmqpMessageQueue_queue, "f"), (msg) => {
106
- if (msg == null)
107
- return;
108
- const message = JSON.parse(msg.content.toString("utf-8"));
109
- const result = handler(message);
110
- if (result instanceof Promise) {
111
- result.finally(() => channel.ack(msg));
112
- }
113
- else {
114
- channel.ack(msg);
115
- }
116
- }, {
117
- noAck: false,
118
- });
119
- return await new Promise((resolve) => {
120
- options.signal?.addEventListener("abort", () => {
121
- channel.cancel(reply.consumerTag).then(() => {
122
- channel.close().then(() => resolve());
123
- });
124
- });
125
- });
126
- }
127
- }
128
- _AmqpMessageQueue_connection = new WeakMap(), _AmqpMessageQueue_queue = new WeakMap(), _AmqpMessageQueue_delayedQueuePrefix = new WeakMap(), _AmqpMessageQueue_durable = new WeakMap(), _AmqpMessageQueue_senderChannel = new WeakMap(), _AmqpMessageQueue_instances = new WeakSet(), _AmqpMessageQueue_prepareQueue = async function _AmqpMessageQueue_prepareQueue(channel) {
129
- await channel.assertQueue(__classPrivateFieldGet(this, _AmqpMessageQueue_queue, "f"), {
130
- durable: __classPrivateFieldGet(this, _AmqpMessageQueue_durable, "f"),
131
- });
132
- }, _AmqpMessageQueue_getSenderChannel = async function _AmqpMessageQueue_getSenderChannel() {
133
- if (__classPrivateFieldGet(this, _AmqpMessageQueue_senderChannel, "f") != null)
134
- return __classPrivateFieldGet(this, _AmqpMessageQueue_senderChannel, "f");
135
- const channel = await __classPrivateFieldGet(this, _AmqpMessageQueue_connection, "f").createChannel();
136
- __classPrivateFieldSet(this, _AmqpMessageQueue_senderChannel, channel, "f");
137
- __classPrivateFieldGet(this, _AmqpMessageQueue_instances, "m", _AmqpMessageQueue_prepareQueue).call(this, channel);
138
- return channel;
139
- };
package/script/mod.js DELETED
@@ -1,17 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./src/mod.js"), exports);
@@ -1,3 +0,0 @@
1
- {
2
- "type": "commonjs"
3
- }