@fedify/fedify 2.0.0-dev.237 → 2.0.0-dev.279
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/dist/{builder-D9GtbwtV.js → builder-B7WWCOdc.js} +3 -3
- package/dist/compat/mod.d.cts +2 -2
- package/dist/compat/mod.d.ts +2 -2
- package/dist/compat/transformers.test.js +12 -12
- package/dist/{context-C7vzWilY.d.ts → context-BNNWbaZL.d.ts} +51 -8
- package/dist/{context-Bns6uTJq.js → context-CZ5llAss.js} +12 -12
- package/dist/{context-CrB9RFy5.d.cts → context-D7JEVvXJ.d.cts} +51 -8
- package/dist/{deno-RfS7RWmL.js → deno-fe0u4LiE.js} +8 -2
- package/dist/{docloader-DvECEZ5H.js → docloader-C9Dmxf-K.js} +2 -2
- package/dist/federation/builder.test.js +3 -3
- package/dist/federation/handler.test.js +13 -13
- package/dist/federation/idempotency.test.js +12 -12
- package/dist/federation/inbox.test.js +2 -2
- package/dist/federation/middleware.test.js +64 -12
- package/dist/federation/mod.cjs +5 -5
- package/dist/federation/mod.d.cts +2 -2
- package/dist/federation/mod.d.ts +2 -2
- package/dist/federation/mod.js +5 -5
- package/dist/federation/mq.test.js +162 -10
- package/dist/federation/send.test.js +5 -5
- package/dist/federation/webfinger.test.js +13 -13
- package/dist/{federation-B431K2gm.cjs → federation-CE0CJ_0G.cjs} +94 -10
- package/dist/{federation-BbZwNNWj.js → federation-D6FVaeAR.js} +94 -10
- package/dist/{http-Cc7n4Qoh.js → http-7r8B3dF_.js} +8 -2
- package/dist/{http-8TlrsZoL.cjs → http-DMi5iyiI.cjs} +8 -2
- package/dist/{http-CE72P83O.js → http-oCBlFLKT.js} +2 -2
- package/dist/{inbox-CgoFwrkP.js → inbox-Dm1rfkdg.js} +1 -1
- package/dist/{key-COCrawtF.js → key-BGzsKfpZ.js} +1 -1
- package/dist/{kv-cache-BEeqyGER.js → kv-cache-B__dHl7g.js} +1 -1
- package/dist/{kv-cache-BV0LKQyf.cjs → kv-cache-C0AvpI7U.cjs} +2 -2
- package/dist/{kv-cache-DRGsvqdV.js → kv-cache-CETRZwoP.js} +2 -2
- package/dist/{ld-BaGGiySp.js → ld-BaO1-A5Y.js} +2 -2
- package/dist/{middleware-C1a3efyY.js → middleware-BDJNulB_.js} +4 -4
- package/dist/{middleware-BNd2OPEY.js → middleware-BlOT9luD.js} +66 -23
- package/dist/{middleware-DJQ_PWmN.cjs → middleware-C0Vj7vNo.cjs} +59 -16
- package/dist/{middleware-CmBe73ju.js → middleware-CnGBoMop.js} +12 -12
- package/dist/middleware-DT3JkH-g.cjs +12 -0
- package/dist/{middleware-B_oUqHDl.js → middleware-R0w-WauH.js} +59 -16
- package/dist/{mod-0qnPv4EC.d.cts → mod-054TSUXs.d.cts} +1 -1
- package/dist/{mod-0p9zUdzg.d.cts → mod-BHXq4Q3x.d.cts} +1 -1
- package/dist/{mod-C3SOvTD1.d.ts → mod-BhDb3RBS.d.ts} +1 -1
- package/dist/{mod-D6pS5_xJ.d.cts → mod-C74sRHP8.d.cts} +1 -1
- package/dist/{mod-xc20HhMD.d.ts → mod-DZmuPaKv.d.ts} +1 -1
- package/dist/{mod-waqu-BL_.d.ts → mod-YpmzboJc.d.ts} +1 -1
- package/dist/mod.cjs +5 -5
- package/dist/mod.d.cts +4 -4
- package/dist/mod.d.ts +4 -4
- package/dist/mod.js +5 -5
- package/dist/nodeinfo/handler.test.js +13 -13
- package/dist/{owner-UVBc7UEt.js → owner-BqIhDQWW.js} +1 -1
- package/dist/{proof-CPysx9bF.js → proof-Cg6AAAWI.js} +1 -1
- package/dist/{proof-DSF9PSv9.js → proof-DoHt7qrS.js} +2 -2
- package/dist/{proof-Cu_UY89a.cjs → proof-vSvvLbTh.cjs} +1 -1
- package/dist/{send-DoACJ0D8.js → send-CO2ZYT96.js} +2 -2
- package/dist/sig/http.test.js +3 -3
- package/dist/sig/key.test.js +2 -2
- package/dist/sig/ld.test.js +3 -3
- package/dist/sig/mod.cjs +2 -2
- package/dist/sig/mod.js +2 -2
- package/dist/sig/owner.test.js +3 -3
- package/dist/sig/proof.test.js +3 -3
- package/dist/testing/mod.d.ts +23 -7
- package/dist/testing/mod.js +1 -1
- package/dist/utils/docloader.test.js +4 -4
- package/dist/utils/kv-cache.test.js +1 -1
- package/dist/utils/mod.cjs +2 -2
- package/dist/utils/mod.d.cts +1 -1
- package/dist/utils/mod.d.ts +1 -1
- package/dist/utils/mod.js +2 -2
- package/package.json +12 -9
- package/dist/middleware-XqO4Y-9s.cjs +0 -12
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
import { URLPattern } from "urlpattern-polyfill";
|
|
4
4
|
globalThis.addEventListener = () => {};
|
|
5
5
|
|
|
6
|
-
import { deno_default } from "./deno-
|
|
6
|
+
import { deno_default } from "./deno-fe0u4LiE.js";
|
|
7
7
|
import { Router, RouterError } from "./router-D9eI0s4b.js";
|
|
8
|
-
import { InboxListenerSet } from "./inbox-
|
|
8
|
+
import { InboxListenerSet } from "./inbox-Dm1rfkdg.js";
|
|
9
9
|
import { getLogger } from "@logtape/logtape";
|
|
10
10
|
import { getTypeId } from "@fedify/vocab";
|
|
11
11
|
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
@@ -44,7 +44,7 @@ var FederationBuilderImpl = class {
|
|
|
44
44
|
this.collectionTypeIds = {};
|
|
45
45
|
}
|
|
46
46
|
async build(options) {
|
|
47
|
-
const { FederationImpl } = await import("./middleware-
|
|
47
|
+
const { FederationImpl } = await import("./middleware-CnGBoMop.js");
|
|
48
48
|
const f = new FederationImpl(options);
|
|
49
49
|
const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
|
|
50
50
|
f.router = this.router.clone();
|
package/dist/compat/mod.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "../client-by-PEGAJ.cjs";
|
|
2
2
|
import "../http-ClB3pLcL.cjs";
|
|
3
3
|
import "../owner-C-zfmVAD.cjs";
|
|
4
|
-
import { ActivityTransformer } from "../context-
|
|
4
|
+
import { ActivityTransformer } from "../context-D7JEVvXJ.cjs";
|
|
5
5
|
import "../kv-B4vFhIYL.cjs";
|
|
6
|
-
import { actorDehydrator, autoIdAssigner, getDefaultActivityTransformers } from "../mod-
|
|
6
|
+
import { actorDehydrator, autoIdAssigner, getDefaultActivityTransformers } from "../mod-C74sRHP8.cjs";
|
|
7
7
|
export { ActivityTransformer, actorDehydrator, autoIdAssigner, getDefaultActivityTransformers };
|
package/dist/compat/mod.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { URLPattern } from "urlpattern-polyfill";
|
|
|
3
3
|
import "../client-CUTUGgvJ.js";
|
|
4
4
|
import "../http-DLBDPal9.js";
|
|
5
5
|
import "../owner-BgI8C-VY.js";
|
|
6
|
-
import { ActivityTransformer } from "../context-
|
|
6
|
+
import { ActivityTransformer } from "../context-BNNWbaZL.js";
|
|
7
7
|
import "../kv-CYySNrsn.js";
|
|
8
|
-
import { actorDehydrator, autoIdAssigner, getDefaultActivityTransformers } from "../mod-
|
|
8
|
+
import { actorDehydrator, autoIdAssigner, getDefaultActivityTransformers } from "../mod-YpmzboJc.js";
|
|
9
9
|
export { ActivityTransformer, actorDehydrator, autoIdAssigner, getDefaultActivityTransformers };
|
|
@@ -8,25 +8,25 @@ import { assertEquals } from "../assert_equals-DSbWqCm3.js";
|
|
|
8
8
|
import { assert } from "../assert-MZs1qjMx.js";
|
|
9
9
|
import { assertInstanceOf } from "../assert_instance_of-DHz7EHNU.js";
|
|
10
10
|
import { MemoryKvStore } from "../kv-QzKcOQgP.js";
|
|
11
|
-
import "../deno-
|
|
12
|
-
import { FederationImpl, actorDehydrator, autoIdAssigner } from "../middleware-
|
|
11
|
+
import "../deno-fe0u4LiE.js";
|
|
12
|
+
import { FederationImpl, actorDehydrator, autoIdAssigner } from "../middleware-BlOT9luD.js";
|
|
13
13
|
import "../client-Dg7OfUDA.js";
|
|
14
14
|
import "../router-D9eI0s4b.js";
|
|
15
15
|
import "../types-CPz01LGH.js";
|
|
16
|
-
import "../key-
|
|
17
|
-
import "../http-
|
|
18
|
-
import "../ld-
|
|
19
|
-
import "../owner-
|
|
20
|
-
import "../proof-
|
|
21
|
-
import "../docloader-
|
|
22
|
-
import "../kv-cache-
|
|
23
|
-
import "../inbox-
|
|
24
|
-
import "../builder-
|
|
16
|
+
import "../key-BGzsKfpZ.js";
|
|
17
|
+
import "../http-oCBlFLKT.js";
|
|
18
|
+
import "../ld-BaO1-A5Y.js";
|
|
19
|
+
import "../owner-BqIhDQWW.js";
|
|
20
|
+
import "../proof-DoHt7qrS.js";
|
|
21
|
+
import "../docloader-C9Dmxf-K.js";
|
|
22
|
+
import "../kv-cache-B__dHl7g.js";
|
|
23
|
+
import "../inbox-Dm1rfkdg.js";
|
|
24
|
+
import "../builder-B7WWCOdc.js";
|
|
25
25
|
import "../collection-CcnIw1qY.js";
|
|
26
26
|
import "../keycache-DRxpZ5r9.js";
|
|
27
27
|
import "../negotiation-5NPJL6zp.js";
|
|
28
28
|
import "../retry-D4GJ670a.js";
|
|
29
|
-
import "../send-
|
|
29
|
+
import "../send-CO2ZYT96.js";
|
|
30
30
|
import { Follow, Person } from "@fedify/vocab";
|
|
31
31
|
|
|
32
32
|
//#region src/compat/transformers.test.ts
|
|
@@ -317,7 +317,19 @@ interface MessageQueueEnqueueOptions {
|
|
|
317
317
|
*
|
|
318
318
|
* It must not be negative.
|
|
319
319
|
*/
|
|
320
|
-
delay?: Temporal.Duration;
|
|
320
|
+
readonly delay?: Temporal.Duration;
|
|
321
|
+
/**
|
|
322
|
+
* An optional key that ensures messages with the same ordering key are
|
|
323
|
+
* processed sequentially (one at a time). Messages with different ordering
|
|
324
|
+
* keys (or no ordering key) may be processed in parallel.
|
|
325
|
+
*
|
|
326
|
+
* This is useful for ensuring that related messages are processed in order,
|
|
327
|
+
* such as ensuring that a `Delete` activity is processed after a `Create`
|
|
328
|
+
* activity for the same object.
|
|
329
|
+
*
|
|
330
|
+
* @since 2.0.0
|
|
331
|
+
*/
|
|
332
|
+
readonly orderingKey?: string;
|
|
321
333
|
}
|
|
322
334
|
/**
|
|
323
335
|
* Additional options for listening to a message queue.
|
|
@@ -418,6 +430,21 @@ declare class InProcessMessageQueue implements MessageQueue {
|
|
|
418
430
|
* for I/O-bound tasks, but not for CPU-bound tasks, which is okay for Fedify's
|
|
419
431
|
* workloads.
|
|
420
432
|
*
|
|
433
|
+
* When using `ParallelMessageQueue`, the ordering guarantee is preserved
|
|
434
|
+
* *only if* the underlying queue implementation delivers messages in a wrapper
|
|
435
|
+
* format that includes the `__fedify_ordering_key__` property. Currently,
|
|
436
|
+
* only `DenoKvMessageQueue` and `WorkersMessageQueue` use this format.
|
|
437
|
+
* For other queue implementations (e.g., `InProcessMessageQueue`,
|
|
438
|
+
* `RedisMessageQueue`, `PostgresMessageQueue`, `SqliteMessageQueue`,
|
|
439
|
+
* `AmqpMessageQueue`), the ordering key cannot be detected by
|
|
440
|
+
* `ParallelMessageQueue`, so ordering guarantees are handled by those
|
|
441
|
+
* implementations directly rather than at the `ParallelMessageQueue` level.
|
|
442
|
+
*
|
|
443
|
+
* Messages with the same ordering key will never be processed concurrently
|
|
444
|
+
* by different workers, ensuring sequential processing within each key.
|
|
445
|
+
* Messages with different ordering keys (or no ordering key) can still be
|
|
446
|
+
* processed in parallel.
|
|
447
|
+
*
|
|
421
448
|
* @since 1.0.0
|
|
422
449
|
*/
|
|
423
450
|
declare class ParallelMessageQueue implements MessageQueue {
|
|
@@ -597,6 +624,7 @@ interface FanoutMessage {
|
|
|
597
624
|
readonly activityId?: string;
|
|
598
625
|
readonly activityType: string;
|
|
599
626
|
readonly collectionSync?: string;
|
|
627
|
+
readonly orderingKey?: string;
|
|
600
628
|
readonly traceContext: Readonly<Record<string, string>>;
|
|
601
629
|
}
|
|
602
630
|
interface OutboxMessage {
|
|
@@ -612,6 +640,7 @@ interface OutboxMessage {
|
|
|
612
640
|
readonly started: string;
|
|
613
641
|
readonly attempt: number;
|
|
614
642
|
readonly headers: Readonly<Record<string, string>>;
|
|
643
|
+
readonly orderingKey?: string;
|
|
615
644
|
readonly traceContext: Readonly<Record<string, string>>;
|
|
616
645
|
}
|
|
617
646
|
interface InboxMessage {
|
|
@@ -1047,7 +1076,7 @@ interface Federatable<TContextData> {
|
|
|
1047
1076
|
* ([RFC 6570](https://tools.ietf.org/html/rfc6570)).
|
|
1048
1077
|
* The path must have no variables.
|
|
1049
1078
|
* @returns An object to register inbox listeners.
|
|
1050
|
-
* @throws {
|
|
1079
|
+
* @throws {RouterError} Thrown if the path pattern is invalid.
|
|
1051
1080
|
*/
|
|
1052
1081
|
setInboxListeners(inboxPath: `${string}${Rfc6570Expression<"identifier">}${string}` | `${string}${Rfc6570Expression<"handle">}${string}`, sharedInboxPath?: string): InboxListenerSetters<TContextData>;
|
|
1053
1082
|
/**
|
|
@@ -1766,7 +1795,7 @@ interface Context<TContextData> {
|
|
|
1766
1795
|
* @param cls The class of the object.
|
|
1767
1796
|
* @param values The values to pass to the object dispatcher.
|
|
1768
1797
|
* @returns The object's URI.
|
|
1769
|
-
* @throws {
|
|
1798
|
+
* @throws {RouterError} If no object dispatcher is available for the class.
|
|
1770
1799
|
* @throws {TypeError} If values are invalid.
|
|
1771
1800
|
* @since 0.7.0
|
|
1772
1801
|
*/
|
|
@@ -1998,7 +2027,7 @@ interface Context<TContextData> {
|
|
|
1998
2027
|
handle: string;
|
|
1999
2028
|
}, recipients: Recipient | Recipient[], activity: Activity, options?: SendActivityOptions): Promise<void>;
|
|
2000
2029
|
/**
|
|
2001
|
-
* Sends an activity to the
|
|
2030
|
+
* Sends an activity to the inboxes of the sender's followers.
|
|
2002
2031
|
* @param sender The sender's identifier or the sender's username.
|
|
2003
2032
|
* @param recipients In this case, it must be `"followers"`.
|
|
2004
2033
|
* @param activity The activity to send.
|
|
@@ -2039,7 +2068,7 @@ interface Context<TContextData> {
|
|
|
2039
2068
|
* @param name The name of the collection, which can be a string or a symbol.
|
|
2040
2069
|
* @param values The values of the URI parameters.
|
|
2041
2070
|
* @return The URI of the collection.
|
|
2042
|
-
* @throws {
|
|
2071
|
+
* @throws {RouterError} If no object dispatcher is available for the name.
|
|
2043
2072
|
* @throws {TypeError} If values are invalid.
|
|
2044
2073
|
* @since 1.8.0
|
|
2045
2074
|
*/
|
|
@@ -2318,7 +2347,7 @@ interface SendActivityOptions {
|
|
|
2318
2347
|
/**
|
|
2319
2348
|
* Whether to prefer the shared inbox for the recipients.
|
|
2320
2349
|
*/
|
|
2321
|
-
preferSharedInbox?: boolean;
|
|
2350
|
+
readonly preferSharedInbox?: boolean;
|
|
2322
2351
|
/**
|
|
2323
2352
|
* Whether to send the activity immediately, without enqueuing it.
|
|
2324
2353
|
* If `true`, the activity will be sent immediately and the retrial
|
|
@@ -2326,7 +2355,7 @@ interface SendActivityOptions {
|
|
|
2326
2355
|
*
|
|
2327
2356
|
* @since 0.3.0
|
|
2328
2357
|
*/
|
|
2329
|
-
immediate?: boolean;
|
|
2358
|
+
readonly immediate?: boolean;
|
|
2330
2359
|
/**
|
|
2331
2360
|
* Determines how activities are queued when sent to multiple recipients.
|
|
2332
2361
|
*
|
|
@@ -2343,7 +2372,7 @@ interface SendActivityOptions {
|
|
|
2343
2372
|
* @default `"auto"`
|
|
2344
2373
|
* @since 1.5.0
|
|
2345
2374
|
*/
|
|
2346
|
-
fanout?: "auto" | "skip" | "force";
|
|
2375
|
+
readonly fanout?: "auto" | "skip" | "force";
|
|
2347
2376
|
/**
|
|
2348
2377
|
* The base URIs to exclude from the recipients' inboxes. It is useful
|
|
2349
2378
|
* for excluding the recipients having the same shared inbox with the sender.
|
|
@@ -2353,6 +2382,20 @@ interface SendActivityOptions {
|
|
|
2353
2382
|
* @since 0.9.0
|
|
2354
2383
|
*/
|
|
2355
2384
|
readonly excludeBaseUris?: readonly URL[];
|
|
2385
|
+
/**
|
|
2386
|
+
* An optional key to ensure ordered delivery of activities. Activities with
|
|
2387
|
+
* the same `orderingKey` are guaranteed to be delivered in the order they
|
|
2388
|
+
* were enqueued, per recipient server.
|
|
2389
|
+
*
|
|
2390
|
+
* Typical use case: pass the object ID (e.g., `Note` ID) to ensure that
|
|
2391
|
+
* `Create`, `Update`, and `Delete` activities for the same object are
|
|
2392
|
+
* delivered in order.
|
|
2393
|
+
*
|
|
2394
|
+
* When omitted, no ordering is guaranteed (maximum parallelism).
|
|
2395
|
+
*
|
|
2396
|
+
* @since 2.0.0
|
|
2397
|
+
*/
|
|
2398
|
+
readonly orderingKey?: string;
|
|
2356
2399
|
}
|
|
2357
2400
|
/**
|
|
2358
2401
|
* Options for {@link Context.sendActivity} method when sending to a collection.
|
|
@@ -12,7 +12,7 @@ import { trace } from "@opentelemetry/api";
|
|
|
12
12
|
//#region src/testing/context.ts
|
|
13
13
|
function createContext(values) {
|
|
14
14
|
const { federation, url = new URL("http://example.com/"), canonicalOrigin, data, documentLoader, contextLoader, tracerProvider, clone, getNodeInfoUri, getActorUri, getObjectUri, getCollectionUri, getOutboxUri, getInboxUri, getFollowingUri, getFollowersUri, getLikedUri, getFeaturedUri, getFeaturedTagsUri, parseUri, getActorKeyPairs, getDocumentLoader, lookupObject: lookupObject$1, traverseCollection: traverseCollection$1, lookupNodeInfo, lookupWebFinger: lookupWebFinger$1, sendActivity, routeActivity } = values;
|
|
15
|
-
function
|
|
15
|
+
function throwRouterError() {
|
|
16
16
|
throw new RouterError("Not implemented");
|
|
17
17
|
}
|
|
18
18
|
return {
|
|
@@ -29,17 +29,17 @@ function createContext(values) {
|
|
|
29
29
|
...values,
|
|
30
30
|
data: data$1
|
|
31
31
|
})),
|
|
32
|
-
getNodeInfoUri: getNodeInfoUri ??
|
|
33
|
-
getActorUri: getActorUri ??
|
|
34
|
-
getObjectUri: getObjectUri ??
|
|
35
|
-
getCollectionUri: getCollectionUri ??
|
|
36
|
-
getOutboxUri: getOutboxUri ??
|
|
37
|
-
getInboxUri: getInboxUri ??
|
|
38
|
-
getFollowingUri: getFollowingUri ??
|
|
39
|
-
getFollowersUri: getFollowersUri ??
|
|
40
|
-
getLikedUri: getLikedUri ??
|
|
41
|
-
getFeaturedUri: getFeaturedUri ??
|
|
42
|
-
getFeaturedTagsUri: getFeaturedTagsUri ??
|
|
32
|
+
getNodeInfoUri: getNodeInfoUri ?? throwRouterError,
|
|
33
|
+
getActorUri: getActorUri ?? throwRouterError,
|
|
34
|
+
getObjectUri: getObjectUri ?? throwRouterError,
|
|
35
|
+
getCollectionUri: getCollectionUri ?? throwRouterError,
|
|
36
|
+
getOutboxUri: getOutboxUri ?? throwRouterError,
|
|
37
|
+
getInboxUri: getInboxUri ?? throwRouterError,
|
|
38
|
+
getFollowingUri: getFollowingUri ?? throwRouterError,
|
|
39
|
+
getFollowersUri: getFollowersUri ?? throwRouterError,
|
|
40
|
+
getLikedUri: getLikedUri ?? throwRouterError,
|
|
41
|
+
getFeaturedUri: getFeaturedUri ?? throwRouterError,
|
|
42
|
+
getFeaturedTagsUri: getFeaturedTagsUri ?? throwRouterError,
|
|
43
43
|
parseUri: parseUri ?? ((_uri) => {
|
|
44
44
|
throw new Error("Not implemented");
|
|
45
45
|
}),
|
|
@@ -315,7 +315,19 @@ interface MessageQueueEnqueueOptions {
|
|
|
315
315
|
*
|
|
316
316
|
* It must not be negative.
|
|
317
317
|
*/
|
|
318
|
-
delay?: Temporal.Duration;
|
|
318
|
+
readonly delay?: Temporal.Duration;
|
|
319
|
+
/**
|
|
320
|
+
* An optional key that ensures messages with the same ordering key are
|
|
321
|
+
* processed sequentially (one at a time). Messages with different ordering
|
|
322
|
+
* keys (or no ordering key) may be processed in parallel.
|
|
323
|
+
*
|
|
324
|
+
* This is useful for ensuring that related messages are processed in order,
|
|
325
|
+
* such as ensuring that a `Delete` activity is processed after a `Create`
|
|
326
|
+
* activity for the same object.
|
|
327
|
+
*
|
|
328
|
+
* @since 2.0.0
|
|
329
|
+
*/
|
|
330
|
+
readonly orderingKey?: string;
|
|
319
331
|
}
|
|
320
332
|
/**
|
|
321
333
|
* Additional options for listening to a message queue.
|
|
@@ -416,6 +428,21 @@ declare class InProcessMessageQueue implements MessageQueue {
|
|
|
416
428
|
* for I/O-bound tasks, but not for CPU-bound tasks, which is okay for Fedify's
|
|
417
429
|
* workloads.
|
|
418
430
|
*
|
|
431
|
+
* When using `ParallelMessageQueue`, the ordering guarantee is preserved
|
|
432
|
+
* *only if* the underlying queue implementation delivers messages in a wrapper
|
|
433
|
+
* format that includes the `__fedify_ordering_key__` property. Currently,
|
|
434
|
+
* only `DenoKvMessageQueue` and `WorkersMessageQueue` use this format.
|
|
435
|
+
* For other queue implementations (e.g., `InProcessMessageQueue`,
|
|
436
|
+
* `RedisMessageQueue`, `PostgresMessageQueue`, `SqliteMessageQueue`,
|
|
437
|
+
* `AmqpMessageQueue`), the ordering key cannot be detected by
|
|
438
|
+
* `ParallelMessageQueue`, so ordering guarantees are handled by those
|
|
439
|
+
* implementations directly rather than at the `ParallelMessageQueue` level.
|
|
440
|
+
*
|
|
441
|
+
* Messages with the same ordering key will never be processed concurrently
|
|
442
|
+
* by different workers, ensuring sequential processing within each key.
|
|
443
|
+
* Messages with different ordering keys (or no ordering key) can still be
|
|
444
|
+
* processed in parallel.
|
|
445
|
+
*
|
|
419
446
|
* @since 1.0.0
|
|
420
447
|
*/
|
|
421
448
|
declare class ParallelMessageQueue implements MessageQueue {
|
|
@@ -595,6 +622,7 @@ interface FanoutMessage {
|
|
|
595
622
|
readonly activityId?: string;
|
|
596
623
|
readonly activityType: string;
|
|
597
624
|
readonly collectionSync?: string;
|
|
625
|
+
readonly orderingKey?: string;
|
|
598
626
|
readonly traceContext: Readonly<Record<string, string>>;
|
|
599
627
|
}
|
|
600
628
|
interface OutboxMessage {
|
|
@@ -610,6 +638,7 @@ interface OutboxMessage {
|
|
|
610
638
|
readonly started: string;
|
|
611
639
|
readonly attempt: number;
|
|
612
640
|
readonly headers: Readonly<Record<string, string>>;
|
|
641
|
+
readonly orderingKey?: string;
|
|
613
642
|
readonly traceContext: Readonly<Record<string, string>>;
|
|
614
643
|
}
|
|
615
644
|
interface InboxMessage {
|
|
@@ -1045,7 +1074,7 @@ interface Federatable<TContextData> {
|
|
|
1045
1074
|
* ([RFC 6570](https://tools.ietf.org/html/rfc6570)).
|
|
1046
1075
|
* The path must have no variables.
|
|
1047
1076
|
* @returns An object to register inbox listeners.
|
|
1048
|
-
* @throws {
|
|
1077
|
+
* @throws {RouterError} Thrown if the path pattern is invalid.
|
|
1049
1078
|
*/
|
|
1050
1079
|
setInboxListeners(inboxPath: `${string}${Rfc6570Expression<"identifier">}${string}` | `${string}${Rfc6570Expression<"handle">}${string}`, sharedInboxPath?: string): InboxListenerSetters<TContextData>;
|
|
1051
1080
|
/**
|
|
@@ -1764,7 +1793,7 @@ interface Context<TContextData> {
|
|
|
1764
1793
|
* @param cls The class of the object.
|
|
1765
1794
|
* @param values The values to pass to the object dispatcher.
|
|
1766
1795
|
* @returns The object's URI.
|
|
1767
|
-
* @throws {
|
|
1796
|
+
* @throws {RouterError} If no object dispatcher is available for the class.
|
|
1768
1797
|
* @throws {TypeError} If values are invalid.
|
|
1769
1798
|
* @since 0.7.0
|
|
1770
1799
|
*/
|
|
@@ -1996,7 +2025,7 @@ interface Context<TContextData> {
|
|
|
1996
2025
|
handle: string;
|
|
1997
2026
|
}, recipients: Recipient | Recipient[], activity: Activity, options?: SendActivityOptions): Promise<void>;
|
|
1998
2027
|
/**
|
|
1999
|
-
* Sends an activity to the
|
|
2028
|
+
* Sends an activity to the inboxes of the sender's followers.
|
|
2000
2029
|
* @param sender The sender's identifier or the sender's username.
|
|
2001
2030
|
* @param recipients In this case, it must be `"followers"`.
|
|
2002
2031
|
* @param activity The activity to send.
|
|
@@ -2037,7 +2066,7 @@ interface Context<TContextData> {
|
|
|
2037
2066
|
* @param name The name of the collection, which can be a string or a symbol.
|
|
2038
2067
|
* @param values The values of the URI parameters.
|
|
2039
2068
|
* @return The URI of the collection.
|
|
2040
|
-
* @throws {
|
|
2069
|
+
* @throws {RouterError} If no object dispatcher is available for the name.
|
|
2041
2070
|
* @throws {TypeError} If values are invalid.
|
|
2042
2071
|
* @since 1.8.0
|
|
2043
2072
|
*/
|
|
@@ -2316,7 +2345,7 @@ interface SendActivityOptions {
|
|
|
2316
2345
|
/**
|
|
2317
2346
|
* Whether to prefer the shared inbox for the recipients.
|
|
2318
2347
|
*/
|
|
2319
|
-
preferSharedInbox?: boolean;
|
|
2348
|
+
readonly preferSharedInbox?: boolean;
|
|
2320
2349
|
/**
|
|
2321
2350
|
* Whether to send the activity immediately, without enqueuing it.
|
|
2322
2351
|
* If `true`, the activity will be sent immediately and the retrial
|
|
@@ -2324,7 +2353,7 @@ interface SendActivityOptions {
|
|
|
2324
2353
|
*
|
|
2325
2354
|
* @since 0.3.0
|
|
2326
2355
|
*/
|
|
2327
|
-
immediate?: boolean;
|
|
2356
|
+
readonly immediate?: boolean;
|
|
2328
2357
|
/**
|
|
2329
2358
|
* Determines how activities are queued when sent to multiple recipients.
|
|
2330
2359
|
*
|
|
@@ -2341,7 +2370,7 @@ interface SendActivityOptions {
|
|
|
2341
2370
|
* @default `"auto"`
|
|
2342
2371
|
* @since 1.5.0
|
|
2343
2372
|
*/
|
|
2344
|
-
fanout?: "auto" | "skip" | "force";
|
|
2373
|
+
readonly fanout?: "auto" | "skip" | "force";
|
|
2345
2374
|
/**
|
|
2346
2375
|
* The base URIs to exclude from the recipients' inboxes. It is useful
|
|
2347
2376
|
* for excluding the recipients having the same shared inbox with the sender.
|
|
@@ -2351,6 +2380,20 @@ interface SendActivityOptions {
|
|
|
2351
2380
|
* @since 0.9.0
|
|
2352
2381
|
*/
|
|
2353
2382
|
readonly excludeBaseUris?: readonly URL[];
|
|
2383
|
+
/**
|
|
2384
|
+
* An optional key to ensure ordered delivery of activities. Activities with
|
|
2385
|
+
* the same `orderingKey` are guaranteed to be delivered in the order they
|
|
2386
|
+
* were enqueued, per recipient server.
|
|
2387
|
+
*
|
|
2388
|
+
* Typical use case: pass the object ID (e.g., `Note` ID) to ensure that
|
|
2389
|
+
* `Create`, `Update`, and `Delete` activities for the same object are
|
|
2390
|
+
* delivered in order.
|
|
2391
|
+
*
|
|
2392
|
+
* When omitted, no ordering is guaranteed (maximum parallelism).
|
|
2393
|
+
*
|
|
2394
|
+
* @since 2.0.0
|
|
2395
|
+
*/
|
|
2396
|
+
readonly orderingKey?: string;
|
|
2354
2397
|
}
|
|
2355
2398
|
/**
|
|
2356
2399
|
* Options for {@link Context.sendActivity} method when sending to a collection.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
//#region deno.json
|
|
7
7
|
var name = "@fedify/fedify";
|
|
8
|
-
var version = "2.0.0-dev.
|
|
8
|
+
var version = "2.0.0-dev.279+ce1bdc22";
|
|
9
9
|
var license = "MIT";
|
|
10
10
|
var exports = {
|
|
11
11
|
".": "./src/mod.ts",
|
|
@@ -49,7 +49,13 @@ var exclude = [
|
|
|
49
49
|
"src/cfworkers/server.js",
|
|
50
50
|
"src/cfworkers/server.js.map"
|
|
51
51
|
];
|
|
52
|
-
var publish = { "exclude": [
|
|
52
|
+
var publish = { "exclude": [
|
|
53
|
+
"**/*.test.ts",
|
|
54
|
+
"src/testing/",
|
|
55
|
+
"tsdown.config.ts",
|
|
56
|
+
"scripts/",
|
|
57
|
+
"wrangler.toml"
|
|
58
|
+
] };
|
|
53
59
|
var tasks = {
|
|
54
60
|
"codegen": "deno task -f @fedify/vocab compile",
|
|
55
61
|
"cache": {
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
import { URLPattern } from "urlpattern-polyfill";
|
|
4
4
|
globalThis.addEventListener = () => {};
|
|
5
5
|
|
|
6
|
-
import { validateCryptoKey } from "./key-
|
|
7
|
-
import { doubleKnock } from "./http-
|
|
6
|
+
import { validateCryptoKey } from "./key-BGzsKfpZ.js";
|
|
7
|
+
import { doubleKnock } from "./http-oCBlFLKT.js";
|
|
8
8
|
import { getLogger } from "@logtape/logtape";
|
|
9
9
|
import { curry } from "es-toolkit";
|
|
10
10
|
import { UrlError, createActivityPubRequest, getDocumentLoader, getRemoteDocument, logRequest, validatePublicUrl } from "@fedify/vocab-runtime";
|
|
@@ -8,10 +8,10 @@ import { assertEquals } from "../assert_equals-DSbWqCm3.js";
|
|
|
8
8
|
import "../assert-MZs1qjMx.js";
|
|
9
9
|
import "../assert_instance_of-DHz7EHNU.js";
|
|
10
10
|
import { MemoryKvStore } from "../kv-QzKcOQgP.js";
|
|
11
|
-
import "../deno-
|
|
11
|
+
import "../deno-fe0u4LiE.js";
|
|
12
12
|
import "../router-D9eI0s4b.js";
|
|
13
|
-
import "../inbox-
|
|
14
|
-
import { createFederationBuilder } from "../builder-
|
|
13
|
+
import "../inbox-Dm1rfkdg.js";
|
|
14
|
+
import { createFederationBuilder } from "../builder-B7WWCOdc.js";
|
|
15
15
|
import { assertExists } from "../std__assert-DWivtrGR.js";
|
|
16
16
|
import "../assert_rejects-Ce45JcFg.js";
|
|
17
17
|
import { assertThrows } from "../assert_throws-BNXdRGWP.js";
|
|
@@ -8,30 +8,30 @@ import { assertEquals } from "../assert_equals-DSbWqCm3.js";
|
|
|
8
8
|
import { assert } from "../assert-MZs1qjMx.js";
|
|
9
9
|
import "../assert_instance_of-DHz7EHNU.js";
|
|
10
10
|
import { MemoryKvStore } from "../kv-QzKcOQgP.js";
|
|
11
|
-
import "../deno-
|
|
12
|
-
import { createFederation, handleActor, handleCollection, handleCustomCollection, handleInbox, handleObject, respondWithObject, respondWithObjectIfAcceptable } from "../middleware-
|
|
11
|
+
import "../deno-fe0u4LiE.js";
|
|
12
|
+
import { createFederation, handleActor, handleCollection, handleCustomCollection, handleInbox, handleObject, respondWithObject, respondWithObjectIfAcceptable } from "../middleware-BlOT9luD.js";
|
|
13
13
|
import "../client-Dg7OfUDA.js";
|
|
14
14
|
import "../router-D9eI0s4b.js";
|
|
15
15
|
import "../types-CPz01LGH.js";
|
|
16
|
-
import "../key-
|
|
17
|
-
import { signRequest } from "../http-
|
|
18
|
-
import "../ld-
|
|
19
|
-
import "../owner-
|
|
20
|
-
import "../proof-
|
|
21
|
-
import "../docloader-
|
|
22
|
-
import "../kv-cache-
|
|
23
|
-
import { InboxListenerSet } from "../inbox-
|
|
24
|
-
import "../builder-
|
|
16
|
+
import "../key-BGzsKfpZ.js";
|
|
17
|
+
import { signRequest } from "../http-oCBlFLKT.js";
|
|
18
|
+
import "../ld-BaO1-A5Y.js";
|
|
19
|
+
import "../owner-BqIhDQWW.js";
|
|
20
|
+
import "../proof-DoHt7qrS.js";
|
|
21
|
+
import "../docloader-C9Dmxf-K.js";
|
|
22
|
+
import "../kv-cache-B__dHl7g.js";
|
|
23
|
+
import { InboxListenerSet } from "../inbox-Dm1rfkdg.js";
|
|
24
|
+
import "../builder-B7WWCOdc.js";
|
|
25
25
|
import "../collection-CcnIw1qY.js";
|
|
26
26
|
import "../keycache-DRxpZ5r9.js";
|
|
27
27
|
import "../negotiation-5NPJL6zp.js";
|
|
28
28
|
import "../retry-D4GJ670a.js";
|
|
29
|
-
import "../send-
|
|
29
|
+
import "../send-CO2ZYT96.js";
|
|
30
30
|
import "../std__assert-DWivtrGR.js";
|
|
31
31
|
import "../assert_rejects-Ce45JcFg.js";
|
|
32
32
|
import "../assert_throws-BNXdRGWP.js";
|
|
33
33
|
import "../assert_not_equals-C80BG-_5.js";
|
|
34
|
-
import { createInboxContext, createRequestContext } from "../context-
|
|
34
|
+
import { createInboxContext, createRequestContext } from "../context-CZ5llAss.js";
|
|
35
35
|
import { rsaPrivateKey3, rsaPublicKey2, rsaPublicKey3 } from "../keys-ZbcByPg9.js";
|
|
36
36
|
import { Create, Note, Person } from "@fedify/vocab";
|
|
37
37
|
|
|
@@ -8,25 +8,25 @@ import { assertEquals } from "../assert_equals-DSbWqCm3.js";
|
|
|
8
8
|
import "../assert-MZs1qjMx.js";
|
|
9
9
|
import "../assert_instance_of-DHz7EHNU.js";
|
|
10
10
|
import { MemoryKvStore } from "../kv-QzKcOQgP.js";
|
|
11
|
-
import "../deno-
|
|
12
|
-
import { createFederation } from "../middleware-
|
|
11
|
+
import "../deno-fe0u4LiE.js";
|
|
12
|
+
import { createFederation } from "../middleware-BlOT9luD.js";
|
|
13
13
|
import "../client-Dg7OfUDA.js";
|
|
14
14
|
import "../router-D9eI0s4b.js";
|
|
15
15
|
import "../types-CPz01LGH.js";
|
|
16
|
-
import "../key-
|
|
17
|
-
import "../http-
|
|
18
|
-
import "../ld-
|
|
19
|
-
import "../owner-
|
|
20
|
-
import { signObject } from "../proof-
|
|
21
|
-
import "../docloader-
|
|
22
|
-
import "../kv-cache-
|
|
23
|
-
import "../inbox-
|
|
24
|
-
import "../builder-
|
|
16
|
+
import "../key-BGzsKfpZ.js";
|
|
17
|
+
import "../http-oCBlFLKT.js";
|
|
18
|
+
import "../ld-BaO1-A5Y.js";
|
|
19
|
+
import "../owner-BqIhDQWW.js";
|
|
20
|
+
import { signObject } from "../proof-DoHt7qrS.js";
|
|
21
|
+
import "../docloader-C9Dmxf-K.js";
|
|
22
|
+
import "../kv-cache-B__dHl7g.js";
|
|
23
|
+
import "../inbox-Dm1rfkdg.js";
|
|
24
|
+
import "../builder-B7WWCOdc.js";
|
|
25
25
|
import "../collection-CcnIw1qY.js";
|
|
26
26
|
import "../keycache-DRxpZ5r9.js";
|
|
27
27
|
import "../negotiation-5NPJL6zp.js";
|
|
28
28
|
import "../retry-D4GJ670a.js";
|
|
29
|
-
import "../send-
|
|
29
|
+
import "../send-CO2ZYT96.js";
|
|
30
30
|
import "../std__assert-DWivtrGR.js";
|
|
31
31
|
import "../assert_rejects-Ce45JcFg.js";
|
|
32
32
|
import "../assert_throws-BNXdRGWP.js";
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
import { test } from "../dist-B5f6a8Tt.js";
|
|
7
7
|
import { assertEquals } from "../assert_equals-DSbWqCm3.js";
|
|
8
|
-
import "../deno-
|
|
9
|
-
import { InboxListenerSet } from "../inbox-
|
|
8
|
+
import "../deno-fe0u4LiE.js";
|
|
9
|
+
import { InboxListenerSet } from "../inbox-Dm1rfkdg.js";
|
|
10
10
|
import { assertThrows } from "../assert_throws-BNXdRGWP.js";
|
|
11
11
|
import { Activity, Create, Invite, Offer, Update } from "@fedify/vocab";
|
|
12
12
|
|
|
@@ -8,25 +8,25 @@ import { assertEquals } from "../assert_equals-DSbWqCm3.js";
|
|
|
8
8
|
import { assert } from "../assert-MZs1qjMx.js";
|
|
9
9
|
import { assertInstanceOf } from "../assert_instance_of-DHz7EHNU.js";
|
|
10
10
|
import { MemoryKvStore } from "../kv-QzKcOQgP.js";
|
|
11
|
-
import "../deno-
|
|
12
|
-
import { ContextImpl, FederationImpl, InboxContextImpl, KvSpecDeterminer, createFederation } from "../middleware-
|
|
11
|
+
import "../deno-fe0u4LiE.js";
|
|
12
|
+
import { ContextImpl, FederationImpl, InboxContextImpl, KvSpecDeterminer, createFederation } from "../middleware-BlOT9luD.js";
|
|
13
13
|
import "../client-Dg7OfUDA.js";
|
|
14
14
|
import { RouterError } from "../router-D9eI0s4b.js";
|
|
15
15
|
import "../types-CPz01LGH.js";
|
|
16
|
-
import "../key-
|
|
17
|
-
import { signRequest, verifyRequest } from "../http-
|
|
18
|
-
import { detachSignature, signJsonLd, verifyJsonLd } from "../ld-
|
|
19
|
-
import { doesActorOwnKey } from "../owner-
|
|
20
|
-
import { signObject, verifyObject } from "../proof-
|
|
21
|
-
import { fetchDocumentLoader, getAuthenticatedDocumentLoader } from "../docloader-
|
|
22
|
-
import "../kv-cache-
|
|
23
|
-
import "../inbox-
|
|
24
|
-
import "../builder-
|
|
16
|
+
import "../key-BGzsKfpZ.js";
|
|
17
|
+
import { signRequest, verifyRequest } from "../http-oCBlFLKT.js";
|
|
18
|
+
import { detachSignature, signJsonLd, verifyJsonLd } from "../ld-BaO1-A5Y.js";
|
|
19
|
+
import { doesActorOwnKey } from "../owner-BqIhDQWW.js";
|
|
20
|
+
import { signObject, verifyObject } from "../proof-DoHt7qrS.js";
|
|
21
|
+
import { fetchDocumentLoader, getAuthenticatedDocumentLoader } from "../docloader-C9Dmxf-K.js";
|
|
22
|
+
import "../kv-cache-B__dHl7g.js";
|
|
23
|
+
import "../inbox-Dm1rfkdg.js";
|
|
24
|
+
import "../builder-B7WWCOdc.js";
|
|
25
25
|
import "../collection-CcnIw1qY.js";
|
|
26
26
|
import "../keycache-DRxpZ5r9.js";
|
|
27
27
|
import "../negotiation-5NPJL6zp.js";
|
|
28
28
|
import "../retry-D4GJ670a.js";
|
|
29
|
-
import "../send-
|
|
29
|
+
import "../send-CO2ZYT96.js";
|
|
30
30
|
import { assertStrictEquals } from "../std__assert-DWivtrGR.js";
|
|
31
31
|
import { assertFalse, assertRejects } from "../assert_rejects-Ce45JcFg.js";
|
|
32
32
|
import { assertThrows } from "../assert_throws-BNXdRGWP.js";
|
|
@@ -1635,6 +1635,7 @@ test("ContextImpl.sendActivity()", async (t) => {
|
|
|
1635
1635
|
sharedInbox: false
|
|
1636
1636
|
} },
|
|
1637
1637
|
keys: queue.messages[0].type === "fanout" ? queue.messages[0].keys : [],
|
|
1638
|
+
orderingKey: void 0,
|
|
1638
1639
|
traceContext: {}
|
|
1639
1640
|
}]);
|
|
1640
1641
|
});
|
|
@@ -1732,6 +1733,57 @@ test("ContextImpl.sendActivity()", async (t) => {
|
|
|
1732
1733
|
});
|
|
1733
1734
|
assertNotEquals(collectionSyncHeader, null);
|
|
1734
1735
|
});
|
|
1736
|
+
queue.clear();
|
|
1737
|
+
await t.step("orderingKey with fanout: \"force\"", async () => {
|
|
1738
|
+
const activity = new vocab.Create({
|
|
1739
|
+
id: new URL("https://example.com/activity/ordering-1"),
|
|
1740
|
+
actor: new URL("https://example.com/person")
|
|
1741
|
+
});
|
|
1742
|
+
await ctx2.sendActivity({ username: "john" }, {
|
|
1743
|
+
id: new URL("https://example.com/recipient"),
|
|
1744
|
+
inboxId: new URL("https://example.com/inbox")
|
|
1745
|
+
}, activity, {
|
|
1746
|
+
fanout: "force",
|
|
1747
|
+
orderingKey: "https://example.com/note/1"
|
|
1748
|
+
});
|
|
1749
|
+
assertEquals(queue.messages.length, 1);
|
|
1750
|
+
const fanoutMessage = queue.messages[0];
|
|
1751
|
+
assertEquals(fanoutMessage.type, "fanout");
|
|
1752
|
+
if (fanoutMessage.type === "fanout") assertEquals(fanoutMessage.orderingKey, "https://example.com/note/1");
|
|
1753
|
+
});
|
|
1754
|
+
queue.clear();
|
|
1755
|
+
await t.step("orderingKey with fanout: \"skip\"", async () => {
|
|
1756
|
+
const activity = new vocab.Create({
|
|
1757
|
+
id: new URL("https://example.com/activity/ordering-2"),
|
|
1758
|
+
actor: new URL("https://example.com/person")
|
|
1759
|
+
});
|
|
1760
|
+
await ctx2.sendActivity({ username: "john" }, {
|
|
1761
|
+
id: new URL("https://example.com/recipient"),
|
|
1762
|
+
inboxId: new URL("https://example.com/inbox")
|
|
1763
|
+
}, activity, {
|
|
1764
|
+
fanout: "skip",
|
|
1765
|
+
orderingKey: "https://example.com/note/2"
|
|
1766
|
+
});
|
|
1767
|
+
assertEquals(queue.messages.length, 1);
|
|
1768
|
+
const outboxMessage = queue.messages[0];
|
|
1769
|
+
assertEquals(outboxMessage.type, "outbox");
|
|
1770
|
+
if (outboxMessage.type === "outbox") assertEquals(outboxMessage.orderingKey, "https://example.com/note/2\nhttps://example.com");
|
|
1771
|
+
});
|
|
1772
|
+
queue.clear();
|
|
1773
|
+
await t.step("orderingKey not specified", async () => {
|
|
1774
|
+
const activity = new vocab.Create({
|
|
1775
|
+
id: new URL("https://example.com/activity/ordering-3"),
|
|
1776
|
+
actor: new URL("https://example.com/person")
|
|
1777
|
+
});
|
|
1778
|
+
await ctx2.sendActivity({ username: "john" }, {
|
|
1779
|
+
id: new URL("https://example.com/recipient"),
|
|
1780
|
+
inboxId: new URL("https://example.com/inbox")
|
|
1781
|
+
}, activity, { fanout: "force" });
|
|
1782
|
+
assertEquals(queue.messages.length, 1);
|
|
1783
|
+
const fanoutMessage2 = queue.messages[0];
|
|
1784
|
+
assertEquals(fanoutMessage2.type, "fanout");
|
|
1785
|
+
if (fanoutMessage2.type === "fanout") assertEquals(fanoutMessage2.orderingKey, void 0);
|
|
1786
|
+
});
|
|
1735
1787
|
esm_default.hardReset();
|
|
1736
1788
|
});
|
|
1737
1789
|
test({
|