@fedify/amqp 0.2.0-dev.12 → 0.3.0-dev.16
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/.github/FUNDING.yaml +1 -0
- package/.github/workflows/main.yaml +93 -0
- package/.vscode/extensions.json +6 -0
- package/.vscode/settings.json +33 -0
- package/.zed/settings.json +30 -0
- package/README.md +8 -1
- package/deno.json +51 -0
- package/deno.lock +684 -0
- package/mod.ts +1 -0
- package/package.json +31 -33
- package/src/mod.ts +1 -0
- package/src/mq.test.ts +113 -0
- package/src/mq.ts +178 -0
- package/tsdown.config.ts +7 -0
- package/esm/mod.js +0 -1
- package/esm/package.json +0 -3
- package/esm/src/mod.js +0 -1
- package/esm/src/mq.js +0 -139
- package/script/mod.js +0 -17
- package/script/package.json +0 -3
- package/script/src/mod.js +0 -17
- package/script/src/mq.js +0 -143
- package/types/mod.d.ts +0 -2
- package/types/mod.d.ts.map +0 -1
- package/types/src/mod.d.ts +0 -2
- package/types/src/mod.d.ts.map +0 -1
- package/types/src/mq.d.ts +0 -51
- package/types/src/mq.d.ts.map +0 -1
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fedify/amqp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0-dev.16+bc8a5574",
|
|
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",
|
|
27
|
-
"exports": {
|
|
28
|
-
".": {
|
|
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
|
-
}
|
|
37
|
-
},
|
|
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
|
-
}
|
|
48
|
-
},
|
|
49
24
|
"funding": [
|
|
50
25
|
"https://github.com/sponsors/dahlia"
|
|
51
26
|
],
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
27
|
+
"type": "module",
|
|
28
|
+
"main": "./dist/mod.js",
|
|
29
|
+
"module": "./dist/mod.js",
|
|
30
|
+
"types": "./dist/mod.d.ts",
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"import": "./dist/mod.js",
|
|
34
|
+
"types": "./dist/mod.d.ts"
|
|
35
|
+
},
|
|
36
|
+
"./package.json": "./package.json"
|
|
55
37
|
},
|
|
56
38
|
"devDependencies": {
|
|
57
|
-
"@
|
|
58
|
-
"@
|
|
39
|
+
"@alinea/suite": "^0.6.2",
|
|
40
|
+
"@js-temporal/polyfill": "^0.5.1",
|
|
41
|
+
"@std/assert": "npm:@jsr/std__assert@^1.0.13",
|
|
42
|
+
"@std/async": "npm:@jsr/std__async@^1.0.13",
|
|
43
|
+
"@types/amqplib": "^0.10.7",
|
|
44
|
+
"tsdown": "^0.12.7",
|
|
45
|
+
"typescript": "^5.8.3"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"@fedify/fedify": "^1.5.0",
|
|
49
|
+
"amqplib": "^0.10.8"
|
|
59
50
|
},
|
|
60
|
-
"
|
|
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,113 @@
|
|
|
1
|
+
import { suite } from "@alinea/suite";
|
|
2
|
+
import * as temporal from "@js-temporal/polyfill";
|
|
3
|
+
import { assertEquals, 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", async () => {
|
|
25
|
+
const conn = await getConnection();
|
|
26
|
+
const conn2 = await getConnection();
|
|
27
|
+
const queue = `fedify_queue_${Math.random().toString(36).slice(5)}`;
|
|
28
|
+
const delayedQueuePrefix = `fedify_delayed_${
|
|
29
|
+
Math.random().toString(36).slice(5)
|
|
30
|
+
}_`;
|
|
31
|
+
const mq = new AmqpMessageQueue(conn, { queue, delayedQueuePrefix });
|
|
32
|
+
const mq2 = new AmqpMessageQueue(conn2, { queue, delayedQueuePrefix });
|
|
33
|
+
|
|
34
|
+
const messages1: string[] = [];
|
|
35
|
+
const messages2: string[] = [];
|
|
36
|
+
const allMessages: string[] = [];
|
|
37
|
+
const controller = new AbortController();
|
|
38
|
+
const listening = mq.listen((message: string) => {
|
|
39
|
+
messages1.push(message);
|
|
40
|
+
allMessages.push(message);
|
|
41
|
+
}, { signal: controller.signal });
|
|
42
|
+
const listening2 = mq2.listen((message: string) => {
|
|
43
|
+
messages2.push(message);
|
|
44
|
+
allMessages.push(message);
|
|
45
|
+
}, { signal: controller.signal });
|
|
46
|
+
|
|
47
|
+
await mq.enqueue("Hello, world!");
|
|
48
|
+
|
|
49
|
+
await waitFor(() => allMessages.length > 0, 15_000);
|
|
50
|
+
|
|
51
|
+
assertEquals(allMessages.includes("Hello, world!"), true);
|
|
52
|
+
|
|
53
|
+
// enqueue() with delay
|
|
54
|
+
const started = Date.now();
|
|
55
|
+
await mq.enqueue(
|
|
56
|
+
"Delayed message",
|
|
57
|
+
{ delay: Temporal.Duration.from({ seconds: 3 }) },
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
await waitFor(() => allMessages.includes("Delayed message"), 15_000);
|
|
61
|
+
|
|
62
|
+
// listen() with delay
|
|
63
|
+
assertEquals(allMessages.includes("Delayed message"), true);
|
|
64
|
+
assertGreater(Date.now() - started, 3_000);
|
|
65
|
+
|
|
66
|
+
await mq.enqueueMany(["Message 1", "Message 2", "Message 3"]);
|
|
67
|
+
|
|
68
|
+
await waitFor(() =>
|
|
69
|
+
allMessages.includes("Message 1") &&
|
|
70
|
+
allMessages.includes("Message 2") &&
|
|
71
|
+
allMessages.includes("Message 3"), 15_000);
|
|
72
|
+
|
|
73
|
+
// listen() after enqueueMany()
|
|
74
|
+
assertEquals(allMessages.includes("Message 1"), true);
|
|
75
|
+
assertEquals(allMessages.includes("Message 2"), true);
|
|
76
|
+
assertEquals(allMessages.includes("Message 3"), true);
|
|
77
|
+
|
|
78
|
+
// enqueueMany() with delay
|
|
79
|
+
const manyStarted = Date.now();
|
|
80
|
+
await mq.enqueueMany(
|
|
81
|
+
["Delayed batch 1", "Delayed batch 2"],
|
|
82
|
+
{ delay: Temporal.Duration.from({ seconds: 3 }) },
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
await waitFor(() =>
|
|
86
|
+
allMessages.includes("Delayed batch 1") &&
|
|
87
|
+
allMessages.includes("Delayed batch 2"), 15_000);
|
|
88
|
+
|
|
89
|
+
// listen() after enqueueMany() with delay
|
|
90
|
+
assertEquals(allMessages.includes("Delayed batch 1"), true);
|
|
91
|
+
assertEquals(allMessages.includes("Delayed batch 2"), true);
|
|
92
|
+
assertGreater(Date.now() - manyStarted, 3_000);
|
|
93
|
+
|
|
94
|
+
controller.abort();
|
|
95
|
+
await listening;
|
|
96
|
+
await listening2;
|
|
97
|
+
|
|
98
|
+
await conn.close();
|
|
99
|
+
await conn2.close();
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
async function waitFor(
|
|
103
|
+
predicate: () => boolean,
|
|
104
|
+
timeoutMs: number,
|
|
105
|
+
): Promise<void> {
|
|
106
|
+
const started = Date.now();
|
|
107
|
+
while (!predicate()) {
|
|
108
|
+
await delay(500);
|
|
109
|
+
if (Date.now() - started > timeoutMs) {
|
|
110
|
+
throw new Error("Timeout");
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
package/src/mq.ts
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
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
|
+
/**
|
|
35
|
+
* A message queue that uses AMQP.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ``` typescript
|
|
39
|
+
* import { createFederation } from "@fedify/fedify";
|
|
40
|
+
* import { AmqpMessageQueue } from "@fedify/amqp";
|
|
41
|
+
* import { connect } from "amqplib";
|
|
42
|
+
*
|
|
43
|
+
* const federation = createFederation({
|
|
44
|
+
* queue: new AmqpMessageQueue(await connect("amqp://localhost")),
|
|
45
|
+
* // ... other configurations
|
|
46
|
+
* });
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export class AmqpMessageQueue implements MessageQueue {
|
|
50
|
+
#connection: ChannelModel;
|
|
51
|
+
#queue: string;
|
|
52
|
+
#delayedQueuePrefix: string;
|
|
53
|
+
#durable: boolean;
|
|
54
|
+
#senderChannel?: Channel;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Creates a new `AmqpMessageQueue`.
|
|
58
|
+
* @param connection A connection to the AMQP server.
|
|
59
|
+
* @param options Options for the message queue.
|
|
60
|
+
*/
|
|
61
|
+
constructor(
|
|
62
|
+
connection: ChannelModel,
|
|
63
|
+
options: AmqpMessageQueueOptions = {},
|
|
64
|
+
) {
|
|
65
|
+
this.#connection = connection;
|
|
66
|
+
this.#queue = options.queue ?? "fedify_queue";
|
|
67
|
+
this.#delayedQueuePrefix = options.delayedQueuePrefix ?? "fedify_delayed_";
|
|
68
|
+
this.#durable = options.durable ?? true;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async #prepareQueue(channel: Channel): Promise<void> {
|
|
72
|
+
await channel.assertQueue(this.#queue, {
|
|
73
|
+
durable: this.#durable,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async #getSenderChannel(): Promise<Channel> {
|
|
78
|
+
if (this.#senderChannel != null) return this.#senderChannel;
|
|
79
|
+
const channel = await this.#connection.createChannel();
|
|
80
|
+
this.#senderChannel = channel;
|
|
81
|
+
this.#prepareQueue(channel);
|
|
82
|
+
return channel;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async enqueue(
|
|
86
|
+
// deno-lint-ignore no-explicit-any
|
|
87
|
+
message: any,
|
|
88
|
+
options?: MessageQueueEnqueueOptions,
|
|
89
|
+
): Promise<void> {
|
|
90
|
+
const channel = await this.#getSenderChannel();
|
|
91
|
+
const delay = options?.delay?.total("millisecond");
|
|
92
|
+
let queue: string;
|
|
93
|
+
if (delay == null || delay <= 0) {
|
|
94
|
+
queue = this.#queue;
|
|
95
|
+
} else {
|
|
96
|
+
const delayStr = delay.toLocaleString("en", { useGrouping: false });
|
|
97
|
+
queue = this.#delayedQueuePrefix + delayStr;
|
|
98
|
+
await channel.assertQueue(queue, {
|
|
99
|
+
autoDelete: true,
|
|
100
|
+
durable: this.#durable,
|
|
101
|
+
deadLetterExchange: "",
|
|
102
|
+
deadLetterRoutingKey: this.#queue,
|
|
103
|
+
messageTtl: delay,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
channel.sendToQueue(
|
|
107
|
+
queue,
|
|
108
|
+
Buffer.from(JSON.stringify(message), "utf-8"),
|
|
109
|
+
{
|
|
110
|
+
persistent: this.#durable,
|
|
111
|
+
contentType: "application/json",
|
|
112
|
+
},
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async enqueueMany(
|
|
117
|
+
// deno-lint-ignore no-explicit-any
|
|
118
|
+
messages: any[],
|
|
119
|
+
options?: MessageQueueEnqueueOptions,
|
|
120
|
+
): Promise<void> {
|
|
121
|
+
const channel = await this.#getSenderChannel();
|
|
122
|
+
const delay = options?.delay?.total("millisecond");
|
|
123
|
+
let queue: string;
|
|
124
|
+
if (delay == null || delay <= 0) {
|
|
125
|
+
queue = this.#queue;
|
|
126
|
+
} else {
|
|
127
|
+
const delayStr = delay.toLocaleString("en", { useGrouping: false });
|
|
128
|
+
queue = this.#delayedQueuePrefix + delayStr;
|
|
129
|
+
await channel.assertQueue(queue, {
|
|
130
|
+
autoDelete: true,
|
|
131
|
+
durable: this.#durable,
|
|
132
|
+
deadLetterExchange: "",
|
|
133
|
+
deadLetterRoutingKey: this.#queue,
|
|
134
|
+
messageTtl: delay,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
for (const message of messages) {
|
|
139
|
+
channel.sendToQueue(
|
|
140
|
+
queue,
|
|
141
|
+
Buffer.from(JSON.stringify(message), "utf-8"),
|
|
142
|
+
{
|
|
143
|
+
persistent: this.#durable,
|
|
144
|
+
contentType: "application/json",
|
|
145
|
+
},
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async listen(
|
|
151
|
+
// deno-lint-ignore no-explicit-any
|
|
152
|
+
handler: (message: any) => void | Promise<void>,
|
|
153
|
+
options: MessageQueueListenOptions = {},
|
|
154
|
+
): Promise<void> {
|
|
155
|
+
const channel = await this.#connection.createChannel();
|
|
156
|
+
await this.#prepareQueue(channel);
|
|
157
|
+
await channel.prefetch(1);
|
|
158
|
+
const reply = await channel.consume(this.#queue, (msg) => {
|
|
159
|
+
if (msg == null) return;
|
|
160
|
+
const message = JSON.parse(msg.content.toString("utf-8"));
|
|
161
|
+
const result = handler(message);
|
|
162
|
+
if (result instanceof Promise) {
|
|
163
|
+
result.finally(() => channel.ack(msg));
|
|
164
|
+
} else {
|
|
165
|
+
channel.ack(msg);
|
|
166
|
+
}
|
|
167
|
+
}, {
|
|
168
|
+
noAck: false,
|
|
169
|
+
});
|
|
170
|
+
return await new Promise((resolve) => {
|
|
171
|
+
options.signal?.addEventListener("abort", () => {
|
|
172
|
+
channel.cancel(reply.consumerTag).then(() => {
|
|
173
|
+
channel.close().then(() => resolve());
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
package/tsdown.config.ts
ADDED
package/esm/mod.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./src/mod.js";
|
package/esm/package.json
DELETED
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);
|
package/script/package.json
DELETED
package/script/src/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("./mq.js"), exports);
|