@fedify/fedify 1.6.1-pr.242.861 → 1.6.1-pr.242.863

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.
@@ -1,19 +1,21 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
3
  import { KvKey, KvStore, KvStoreSetOptions } from "../federation/kv.js";
4
- import { KVNamespace } from "@cloudflare/workers-types/experimental";
4
+ import { MessageQueue, MessageQueueEnqueueOptions, MessageQueueListenOptions } from "../federation/mq.js";
5
+ import { KVNamespace, Queue } from "@cloudflare/workers-types/experimental";
5
6
 
6
7
  //#region x/cfworkers.d.ts
7
8
  /**
8
- * Implementation of the KvStore interface for Cloudflare Workers KV binding.
9
- * This class provides a wrapper around Cloudflare's KV namespace to store and
10
- * retrieve JSON-serializable values using structured keys.
9
+ * Implementation of the {@link KvStore} interface for Cloudflare Workers KV
10
+ * binding. This class provides a wrapper around Cloudflare's KV namespace to
11
+ * store and retrieve JSON-serializable values using structured keys.
11
12
  * @since 1.6.0
12
13
  */
14
+
13
15
  /**
14
- * Implementation of the KvStore interface for Cloudflare Workers KV binding.
15
- * This class provides a wrapper around Cloudflare's KV namespace to store and
16
- * retrieve JSON-serializable values using structured keys.
16
+ * Implementation of the {@link KvStore} interface for Cloudflare Workers KV
17
+ * binding. This class provides a wrapper around Cloudflare's KV namespace to
18
+ * store and retrieve JSON-serializable values using structured keys.
17
19
  * @since 1.6.0
18
20
  */
19
21
  declare class WorkersKvStore implements KvStore {
@@ -23,6 +25,25 @@ declare class WorkersKvStore implements KvStore {
23
25
  set(key: KvKey, value: unknown, options?: KvStoreSetOptions): Promise<void>;
24
26
  delete(key: KvKey): Promise<void>;
25
27
  }
28
+ /**
29
+ * Implementation of the {@link MessageQueue} interface for Cloudflare
30
+ * Workers Queues binding. This class provides a wrapper around Cloudflare's
31
+ * Queues to send messages to a queue.
32
+ *
33
+ * Note that this implementation does not support the `listen()` method,
34
+ * as Cloudflare Workers Queues do not support message consumption in the same
35
+ * way as other message queue systems. Instead, you should use
36
+ * the {@link Federation.processQueuedTask} method to process messages
37
+ * passed to the queue.
38
+ * @since 1.6.0
39
+ */
40
+ declare class WorkersMessageQueue implements MessageQueue {
41
+ #private;
42
+ constructor(queue: Queue);
43
+ enqueue(message: any, options?: MessageQueueEnqueueOptions): Promise<void>;
44
+ enqueueMany(messages: any[], options?: MessageQueueEnqueueOptions): Promise<void>;
45
+ listen(_handler: (message: any) => Promise<void> | void, _options?: MessageQueueListenOptions): Promise<void>;
46
+ }
26
47
 
27
48
  //#endregion
28
- export { WorkersKvStore };
49
+ export { WorkersKvStore, WorkersMessageQueue };
@@ -4,9 +4,9 @@
4
4
 
5
5
  //#region x/cfworkers.ts
6
6
  /**
7
- * Implementation of the KvStore interface for Cloudflare Workers KV binding.
8
- * This class provides a wrapper around Cloudflare's KV namespace to store and
9
- * retrieve JSON-serializable values using structured keys.
7
+ * Implementation of the {@link KvStore} interface for Cloudflare Workers KV
8
+ * binding. This class provides a wrapper around Cloudflare's KV namespace to
9
+ * store and retrieve JSON-serializable values using structured keys.
10
10
  * @since 1.6.0
11
11
  */
12
12
  var WorkersKvStore = class {
@@ -34,6 +34,40 @@ var WorkersKvStore = class {
34
34
  return this.#namespace.delete(this.#encodeKey(key));
35
35
  }
36
36
  };
37
+ /**
38
+ * Implementation of the {@link MessageQueue} interface for Cloudflare
39
+ * Workers Queues binding. This class provides a wrapper around Cloudflare's
40
+ * Queues to send messages to a queue.
41
+ *
42
+ * Note that this implementation does not support the `listen()` method,
43
+ * as Cloudflare Workers Queues do not support message consumption in the same
44
+ * way as other message queue systems. Instead, you should use
45
+ * the {@link Federation.processQueuedTask} method to process messages
46
+ * passed to the queue.
47
+ * @since 1.6.0
48
+ */
49
+ var WorkersMessageQueue = class {
50
+ #queue;
51
+ constructor(queue) {
52
+ this.#queue = queue;
53
+ }
54
+ enqueue(message, options) {
55
+ return this.#queue.send(message, {
56
+ contentType: "json",
57
+ delaySeconds: options?.delay?.total("seconds") ?? 0
58
+ });
59
+ }
60
+ enqueueMany(messages, options) {
61
+ const requests = messages.map((msg) => ({
62
+ body: msg,
63
+ contentType: "json"
64
+ }));
65
+ return this.#queue.sendBatch(requests, { delaySeconds: options?.delay?.total("seconds") ?? 0 });
66
+ }
67
+ listen(_handler, _options) {
68
+ throw new TypeError("WorkersMessageQueue does not support listen(). Use Federation.processQueuedTask() method instead.");
69
+ }
70
+ };
37
71
 
38
72
  //#endregion
39
- export { WorkersKvStore };
73
+ export { WorkersKvStore, WorkersMessageQueue };
@@ -4,7 +4,8 @@
4
4
 
5
5
  import { assertEquals } from "../node_modules/.pnpm/@jsr_std__assert@0.226.0/node_modules/@jsr/std__assert/assert_equals.js";
6
6
  import { test } from "../testing/mod.js";
7
- import { WorkersKvStore } from "./cfworkers.js";
7
+ import { WorkersKvStore, WorkersMessageQueue } from "./cfworkers.js";
8
+ import { delay } from "@es-toolkit/es-toolkit";
8
9
 
9
10
  //#region x/cfworkers.test.ts
10
11
  test({
@@ -32,5 +33,46 @@ test({
32
33
  });
33
34
  }
34
35
  });
36
+ test({
37
+ name: "WorkersMessageQueue",
38
+ ignore: !("navigator" in globalThis && navigator.userAgent === "Cloudflare-Workers"),
39
+ async fn(t) {
40
+ const { env, messageBatches } = t;
41
+ const queue = new WorkersMessageQueue(env.Q1);
42
+ await queue.enqueue({
43
+ foo: 1,
44
+ bar: 2
45
+ });
46
+ await waitFor(() => messageBatches.length > 0, 5e3);
47
+ assertEquals(messageBatches.length, 1);
48
+ assertEquals(messageBatches[0].queue, "Q1");
49
+ assertEquals(messageBatches[0].messages.length, 1);
50
+ assertEquals(messageBatches[0].messages[0].body, {
51
+ foo: 1,
52
+ bar: 2
53
+ });
54
+ await queue.enqueue({
55
+ baz: 3,
56
+ qux: 4
57
+ }, { delay: Temporal.Duration.from({ seconds: 3 }) });
58
+ await delay(2e3);
59
+ assertEquals(messageBatches.length, 1);
60
+ await waitFor(() => messageBatches.length > 1, 6e3);
61
+ assertEquals(messageBatches[1].queue, "Q1");
62
+ assertEquals(messageBatches[1].messages.length, 1);
63
+ assertEquals(messageBatches[1].messages[0].body, {
64
+ baz: 3,
65
+ qux: 4
66
+ });
67
+ }
68
+ });
69
+ async function waitFor(predicate, timeoutMs) {
70
+ let delayed = 0;
71
+ while (!predicate()) {
72
+ await delay(500);
73
+ delayed += 500;
74
+ if (delayed > timeoutMs) throw new Error("Timeout");
75
+ }
76
+ }
35
77
 
36
78
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fedify/fedify",
3
- "version": "1.6.1-pr.242.861+0aad6d7f",
3
+ "version": "1.6.1-pr.242.863+a0e491e3",
4
4
  "description": "An ActivityPub server framework",
5
5
  "keywords": [
6
6
  "ActivityPub",