@fedify/fedify 1.5.0-dev.731 → 1.5.0-dev.732

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/CHANGES.md CHANGED
@@ -64,6 +64,9 @@ To be released.
64
64
  - Deprecated the fourth parameter of the `ObjectAuthorizePredicate` type
65
65
  in favor of the `RequestContext.getSignedKeyOwner()` method.
66
66
 
67
+ - Added an optional method `enqueueMany()` to `MessageQueue` interface
68
+ for sending multiple activities at once.
69
+
67
70
  - Fixed a bug of the `fedify inbox` command where it had failed to render
68
71
  the web interface when the `fedify` command was installed using
69
72
  `deno install` command from JSR.
package/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "@fedify/fedify",
3
- "version": "1.5.0-dev.731+6bb4c90e",
3
+ "version": "1.5.0-dev.732+7b169275",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": "./mod.ts",
@@ -1289,7 +1289,7 @@ export class FederationImpl {
1289
1289
  this._startQueueInternal(ctx.data);
1290
1290
  const carrier = {};
1291
1291
  propagation.inject(context.active(), carrier);
1292
- const promises = [];
1292
+ const messages = [];
1293
1293
  for (const inbox in inboxes) {
1294
1294
  const message = {
1295
1295
  type: "outbox",
@@ -1308,18 +1308,31 @@ export class FederationImpl {
1308
1308
  },
1309
1309
  traceContext: carrier,
1310
1310
  };
1311
- promises.push(this.outboxQueue.enqueue(message));
1311
+ messages.push(message);
1312
+ }
1313
+ const { outboxQueue } = this;
1314
+ if (outboxQueue.enqueueMany == null) {
1315
+ const promises = messages.map((m) => outboxQueue.enqueue(m));
1316
+ const results = await Promise.allSettled(promises);
1317
+ const errors = results
1318
+ .filter((r) => r.status === "rejected")
1319
+ .map((r) => r.reason);
1320
+ if (errors.length > 0) {
1321
+ logger.error("Failed to enqueue activity {activityId} to send later: {errors}", { activityId: activity.id.href, errors });
1322
+ if (errors.length > 1) {
1323
+ throw new AggregateError(errors, `Failed to enqueue activity ${activityId} to send later.`);
1324
+ }
1325
+ throw errors[0];
1326
+ }
1312
1327
  }
1313
- const results = await Promise.allSettled(promises);
1314
- const errors = results
1315
- .filter((r) => r.status === "rejected")
1316
- .map((r) => r.reason);
1317
- if (errors.length > 0) {
1318
- logger.error("Failed to enqueue activity {activityId} to send later: {errors}", { activityId: activity.id.href, errors });
1319
- if (errors.length > 1) {
1320
- throw new AggregateError(errors, `Failed to enqueue activity ${activityId} to send later.`);
1328
+ else {
1329
+ try {
1330
+ await outboxQueue.enqueueMany(messages);
1331
+ }
1332
+ catch (error) {
1333
+ logger.error("Failed to enqueue activity {activityId} to send later: {error}", { activityId: activity.id.href, error });
1334
+ throw error;
1321
1335
  }
1322
- throw errors[0];
1323
1336
  }
1324
1337
  }
1325
1338
  fetch(request, options) {
@@ -2516,7 +2529,7 @@ export class InboxContextImpl extends ContextImpl {
2516
2529
  }
2517
2530
  const carrier = {};
2518
2531
  propagation.inject(context.active(), carrier);
2519
- const promises = [];
2532
+ const messages = [];
2520
2533
  for (const inbox in inboxes) {
2521
2534
  const message = {
2522
2535
  type: "outbox",
@@ -2533,18 +2546,31 @@ export class InboxContextImpl extends ContextImpl {
2533
2546
  headers: {},
2534
2547
  traceContext: carrier,
2535
2548
  };
2536
- promises.push(this.federation.outboxQueue.enqueue(message));
2537
- }
2538
- const results = await Promise.allSettled(promises);
2539
- const errors = results
2540
- .filter((r) => r.status === "rejected")
2541
- .map((r) => r.reason);
2542
- if (errors.length > 0) {
2543
- logger.error("Failed to enqueue activity {activityId} to forward later:\n{errors}", { activityId: this.activityId, errors });
2544
- if (errors.length > 1) {
2545
- throw new AggregateError(errors, `Failed to enqueue activity ${this.activityId} to forward later.`);
2546
- }
2547
- throw errors[0];
2549
+ messages.push(message);
2550
+ }
2551
+ const { outboxQueue } = this.federation;
2552
+ if (outboxQueue.enqueueMany == null) {
2553
+ const promises = messages.map((m) => outboxQueue.enqueue(m));
2554
+ const results = await Promise.allSettled(promises);
2555
+ const errors = results
2556
+ .filter((r) => r.status === "rejected")
2557
+ .map((r) => r.reason);
2558
+ if (errors.length > 0) {
2559
+ logger.error("Failed to enqueue activity {activityId} to forward later:\n{errors}", { activityId: this.activityId, errors });
2560
+ if (errors.length > 1) {
2561
+ throw new AggregateError(errors, `Failed to enqueue activity ${this.activityId} to forward later.`);
2562
+ }
2563
+ throw errors[0];
2564
+ }
2565
+ }
2566
+ else {
2567
+ try {
2568
+ await outboxQueue.enqueueMany(messages);
2569
+ }
2570
+ catch (error) {
2571
+ logger.error("Failed to enqueue activity {activityId} to forward later:\n{error}", { activityId: this.activityId, error });
2572
+ throw error;
2573
+ }
2548
2574
  }
2549
2575
  }
2550
2576
  }
@@ -39,6 +39,22 @@ export class InProcessMessageQueue {
39
39
  }
40
40
  return Promise.resolve();
41
41
  }
42
+ enqueueMany(messages, options) {
43
+ if (messages.length === 0)
44
+ return Promise.resolve();
45
+ const delay = options?.delay == null
46
+ ? 0
47
+ : Math.max(options.delay.total("millisecond"), 0);
48
+ if (delay > 0) {
49
+ setTimeout(() => this.enqueueMany(messages, { ...options, delay: undefined }), delay);
50
+ return Promise.resolve();
51
+ }
52
+ this.#messages.push(...messages);
53
+ for (const monitorId in this.#monitors) {
54
+ this.#monitors[monitorId]();
55
+ }
56
+ return Promise.resolve();
57
+ }
42
58
  async listen(handler, options = {}) {
43
59
  const signal = options.signal;
44
60
  while (signal == null || !signal.aborted) {
@@ -107,6 +123,21 @@ export class ParallelMessageQueue {
107
123
  enqueue(message, options) {
108
124
  return this.queue.enqueue(message, options);
109
125
  }
126
+ async enqueueMany(messages, options) {
127
+ if (this.queue.enqueueMany == null) {
128
+ const results = await Promise.allSettled(messages.map((message) => this.queue.enqueue(message, options)));
129
+ const errors = results
130
+ .filter((r) => r.status === "rejected")
131
+ .map((r) => r.reason);
132
+ if (errors.length > 1) {
133
+ throw new AggregateError(errors, "Failed to enqueue messages.");
134
+ }
135
+ else if (errors.length === 1)
136
+ throw errors[0];
137
+ return;
138
+ }
139
+ await this.queue.enqueueMany(messages, options);
140
+ }
110
141
  listen(handler, options = {}) {
111
142
  const workers = new Map();
112
143
  return this.queue.listen(async (message) => {