@fedify/fedify 1.0.0-dev.405 → 1.0.0-dev.408

Sign up to get free protection for your applications and to get access to all the features.
package/CHANGES.md CHANGED
@@ -109,10 +109,14 @@ To be released.
109
109
  the activity to be sent only once. It had added Object Integrity Proofs
110
110
  to the activity for every recipient before.
111
111
 
112
+ - Added `ParallelMessageQueue` class. [[#106]]
113
+
112
114
  - WebFinger responses now include <http://webfinger.net/rel/avatar> links
113
115
  if the `Actor` object returned by the actor dispatcher has `icon`/`icons`
114
116
  property.
115
117
 
118
+ - `DenoKvMessageQueue` now implements `Disposable` interface.
119
+
116
120
  - The `fedify inbox` command now sends `Delete(Application)` activities when
117
121
  it's terminated so that the peers can clean up data related to the temporary
118
122
  actor. [[#135]]
@@ -123,6 +127,7 @@ To be released.
123
127
  - `["fedify", "sig", "ld"]`
124
128
 
125
129
  [Linked Data Signatures]: https://web.archive.org/web/20170923124140/https://w3c-dvcg.github.io/ld-signatures/
130
+ [#106]: https://github.com/dahlia/fedify/issues/106
126
131
  [#135]: https://github.com/dahlia/fedify/issues/135
127
132
  [#137]: https://github.com/dahlia/fedify/issues/137
128
133
 
@@ -1,4 +1,10 @@
1
1
  // deno-lint-ignore-file no-explicit-any
2
+ /**
3
+ * Additional options for enqueuing a message in a queue.
4
+ *
5
+ * @since 0.5.0
6
+ */
7
+ import * as dntShim from "../_dnt.shims.js";
2
8
  /**
3
9
  * A message queue that processes messages in the same process.
4
10
  * Do not use this in production as it does not persist messages.
@@ -7,9 +13,6 @@
7
13
  */
8
14
  export class InProcessMessageQueue {
9
15
  #handlers = [];
10
- /**
11
- * {@inheritDoc Queue.enqueue}
12
- */
13
16
  enqueue(message, options) {
14
17
  const delay = options?.delay == null
15
18
  ? 0
@@ -20,10 +23,65 @@ export class InProcessMessageQueue {
20
23
  }, delay);
21
24
  return Promise.resolve();
22
25
  }
26
+ listen(handler) {
27
+ this.#handlers.push(handler);
28
+ }
29
+ }
30
+ /**
31
+ * A message queue that processes messages in parallel. It takes another
32
+ * {@link MessageQueue}, and processes messages in parallel up to a certain
33
+ * number of workers.
34
+ *
35
+ * Actually, it's rather a decorator than a queue itself.
36
+ *
37
+ * Note that the workers do not run in truly parallel, in the sense that they
38
+ * are not running in separate threads or processes. They are running in the
39
+ * same process, but are scheduled to run in parallel. Hence, this is useful
40
+ * for I/O-bound tasks, but not for CPU-bound tasks, which is okay for Fedify's
41
+ * workloads.
42
+ *
43
+ * @since 1.0.0
44
+ */
45
+ export class ParallelMessageQueue {
46
+ queue;
47
+ workers;
23
48
  /**
24
- * {@inheritDoc Queue.listen}
49
+ * Constructs a new {@link ParallelMessageQueue} with the given queue and
50
+ * number of workers.
51
+ * @param queue The message queue to use under the hood. Note that
52
+ * {@link ParallelMessageQueue} cannot be nested.
53
+ * @param workers The number of workers to process messages in parallel.
54
+ * @throws {TypeError} If the given queue is an instance of
55
+ * {@link ParallelMessageQueue}.
25
56
  */
57
+ constructor(queue, workers) {
58
+ if (queue instanceof ParallelMessageQueue) {
59
+ throw new TypeError("Cannot nest ParallelMessageQueue.");
60
+ }
61
+ this.queue = queue;
62
+ this.workers = workers;
63
+ }
64
+ enqueue(message, options) {
65
+ return this.queue.enqueue(message, options);
66
+ }
26
67
  listen(handler) {
27
- this.#handlers.push(handler);
68
+ const workers = new Map();
69
+ this.queue.listen(async (message) => {
70
+ while (workers.size >= this.workers) {
71
+ const consumedId = await Promise.any(workers.values());
72
+ workers.delete(consumedId);
73
+ }
74
+ const workerId = dntShim.crypto.randomUUID();
75
+ const promise = this.#work(workerId, handler, message);
76
+ workers.set(workerId, promise);
77
+ });
78
+ }
79
+ async #work(workerId, handler, message) {
80
+ await this.#sleep(0);
81
+ await handler(message);
82
+ return workerId;
83
+ }
84
+ #sleep(ms) {
85
+ return new Promise((resolve) => setTimeout(resolve, ms));
28
86
  }
29
87
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fedify/fedify",
3
- "version": "1.0.0-dev.405+276c412a",
3
+ "version": "1.0.0-dev.408+f4e245b4",
4
4
  "description": "An ActivityPub server framework",
5
5
  "keywords": [
6
6
  "ActivityPub",
@@ -38,13 +38,39 @@ export interface MessageQueue {
38
38
  */
39
39
  export declare class InProcessMessageQueue implements MessageQueue {
40
40
  #private;
41
- /**
42
- * {@inheritDoc Queue.enqueue}
43
- */
44
41
  enqueue(message: any, options?: MessageQueueEnqueueOptions): Promise<void>;
42
+ listen(handler: (message: any) => Promise<void> | void): void;
43
+ }
44
+ /**
45
+ * A message queue that processes messages in parallel. It takes another
46
+ * {@link MessageQueue}, and processes messages in parallel up to a certain
47
+ * number of workers.
48
+ *
49
+ * Actually, it's rather a decorator than a queue itself.
50
+ *
51
+ * Note that the workers do not run in truly parallel, in the sense that they
52
+ * are not running in separate threads or processes. They are running in the
53
+ * same process, but are scheduled to run in parallel. Hence, this is useful
54
+ * for I/O-bound tasks, but not for CPU-bound tasks, which is okay for Fedify's
55
+ * workloads.
56
+ *
57
+ * @since 1.0.0
58
+ */
59
+ export declare class ParallelMessageQueue implements MessageQueue {
60
+ #private;
61
+ readonly queue: MessageQueue;
62
+ readonly workers: number;
45
63
  /**
46
- * {@inheritDoc Queue.listen}
64
+ * Constructs a new {@link ParallelMessageQueue} with the given queue and
65
+ * number of workers.
66
+ * @param queue The message queue to use under the hood. Note that
67
+ * {@link ParallelMessageQueue} cannot be nested.
68
+ * @param workers The number of workers to process messages in parallel.
69
+ * @throws {TypeError} If the given queue is an instance of
70
+ * {@link ParallelMessageQueue}.
47
71
  */
72
+ constructor(queue: MessageQueue, workers: number);
73
+ enqueue(message: any, options?: MessageQueueEnqueueOptions): Promise<void>;
48
74
  listen(handler: (message: any) => Promise<void> | void): void;
49
75
  }
50
76
  //# sourceMappingURL=mq.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mq.d.ts","sourceRoot":"","sources":["../../src/federation/mq.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAC;AAE5C,MAAM,WAAW,0BAA0B;IACzC;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;CACnC;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3E;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;CAC/D;AAED;;;;;GAKG;AACH,qBAAa,qBAAsB,YAAW,YAAY;;IAGxD;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC;IAU1E;;OAEG;IACH,MAAM,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;CAG9D"}
1
+ {"version":3,"file":"mq.d.ts","sourceRoot":"","sources":["../../src/federation/mq.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAC;AAE5C,MAAM,WAAW,0BAA0B;IACzC;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;CACnC;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3E;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;CAC/D;AAED;;;;;GAKG;AACH,qBAAa,qBAAsB,YAAW,YAAY;;IAGxD,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC;IAU1E,MAAM,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;CAG9D;AAID;;;;;;;;;;;;;;GAcG;AACH,qBAAa,oBAAqB,YAAW,YAAY;;IACvD,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB;;;;;;;;OAQG;gBACS,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM;IAQhD,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1E,MAAM,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;CA0B9D"}