Skip to content

Commit 53d8840

Browse files
committed
Merge tag '2.1.4'
Fedify 2.1.4
2 parents bb22a55 + 3477b13 commit 53d8840

4 files changed

Lines changed: 164 additions & 2 deletions

File tree

CHANGES.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,35 @@ To be released.
4848
[#652]: https://github.com/fedify-dev/fedify/pull/652
4949

5050

51+
Version 2.1.4
52+
-------------
53+
54+
Released on April 7, 2026.
55+
56+
### @fedify/fedify
57+
58+
- Fixed `sendActivity()` not awaiting `fanoutQueue.enqueue()` in the fanout
59+
path, which could cause fanout messages to be silently dropped on runtimes
60+
like Cloudflare Workers that may terminate an isolate as soon as the
61+
response is sent. [[#661]]
62+
63+
[#661]: https://github.com/fedify-dev/fedify/issues/661
64+
65+
### @fedify/cfworkers
66+
67+
- Fixed a TypeScript type mismatch that occurred when passing
68+
`wrangler types`-generated binding types (e.g. `KVNamespace`, `Queue`)
69+
to `WorkersKvStore` and `WorkersMessageQueue` constructors. The package
70+
previously imported these types from
71+
`@cloudflare/workers-types/experimental`, which includes extra members
72+
(such as `KVNamespace.deleteBulk()`) absent from types generated by
73+
`wrangler types`, causing TypeScript assignment errors at the call site.
74+
The import now uses the stable `@cloudflare/workers-types` entrypoint,
75+
whose definitions match what `wrangler types` generates. [[#662]]
76+
77+
[#662]: https://github.com/fedify-dev/fedify/issues/662
78+
79+
5180
Version 2.1.3
5281
-------------
5382

@@ -309,6 +338,31 @@ Released on March 24, 2026.
309338
[#599]: https://github.com/fedify-dev/fedify/pull/599
310339

311340

341+
Version 2.0.11
342+
--------------
343+
344+
Released on April 7, 2026.
345+
346+
### @fedify/fedify
347+
348+
- Fixed `sendActivity()` not awaiting `fanoutQueue.enqueue()` in the fanout
349+
path, which could cause fanout messages to be silently dropped on runtimes
350+
like Cloudflare Workers that may terminate an isolate as soon as the
351+
response is sent. [[#661]]
352+
353+
### @fedify/cfworkers
354+
355+
- Fixed a TypeScript type mismatch that occurred when passing
356+
`wrangler types`-generated binding types (e.g. `KVNamespace`, `Queue`)
357+
to `WorkersKvStore` and `WorkersMessageQueue` constructors. The package
358+
previously imported these types from
359+
`@cloudflare/workers-types/experimental`, which includes extra members
360+
(such as `KVNamespace.deleteBulk()`) absent from types generated by
361+
`wrangler types`, causing TypeScript assignment errors at the call site.
362+
The import now uses the stable `@cloudflare/workers-types` entrypoint,
363+
whose definitions match what `wrangler types` generates. [[#662]]
364+
365+
312366
Version 2.0.10
313367
--------------
314368

@@ -1086,6 +1140,19 @@ Released on February 22, 2026.
10861140
[#351]: https://github.com/fedify-dev/fedify/issues/351
10871141

10881142

1143+
Version 1.10.7
1144+
--------------
1145+
1146+
Released on April 7, 2026.
1147+
1148+
### @fedify/fedify
1149+
1150+
- Fixed `sendActivity()` not awaiting `fanoutQueue.enqueue()` in the fanout
1151+
path, which could cause fanout messages to be silently dropped on runtimes
1152+
like Cloudflare Workers that may terminate an isolate as soon as the
1153+
response is sent. [[#661]]
1154+
1155+
10891156
Version 1.10.6
10901157
--------------
10911158

@@ -1273,6 +1340,19 @@ Released on December 24, 2025.
12731340
- Implemented `list()` method in `WorkersKvStore`. [[#498], [#500]]
12741341

12751342

1343+
Version 1.9.8
1344+
-------------
1345+
1346+
Released on April 7, 2026.
1347+
1348+
### @fedify/fedify
1349+
1350+
- Fixed `sendActivity()` not awaiting `fanoutQueue.enqueue()` in the fanout
1351+
path, which could cause fanout messages to be silently dropped on runtimes
1352+
like Cloudflare Workers that may terminate an isolate as soon as the
1353+
response is sent. [[#661]]
1354+
1355+
12761356
Version 1.9.7
12771357
-------------
12781358

packages/cfworkers/src/mod.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import type {
1212
KVNamespace,
1313
MessageSendRequest,
1414
Queue,
15-
} from "@cloudflare/workers-types/experimental";
15+
} from "@cloudflare/workers-types";
1616
import type {
1717
KvKey,
1818
KvStore,

packages/fedify/src/federation/middleware.test.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3001,6 +3001,88 @@ test("ContextImpl.sendActivity()", async (t) => {
30013001
]);
30023002
});
30033003

3004+
await t.step(
3005+
"fanout: fanoutQueue.enqueue() is awaited before sendActivity() returns",
3006+
async () => {
3007+
// Regression test for <https://github.com/fedify-dev/fedify/issues/661>.
3008+
// The fanout branch of sendActivityInternal() must await
3009+
// fanoutQueue.enqueue() so that the message is guaranteed to be
3010+
// enqueued before sendActivity() returns. On runtimes like Cloudflare
3011+
// Workers that may terminate an isolate as soon as the response is sent,
3012+
// a floating (non-awaited) enqueue() promise can be silently dropped,
3013+
// causing fanout messages to be lost.
3014+
//
3015+
// This test uses a queue whose enqueue() resolves only after a
3016+
// macro-task delay (setTimeout 0). If enqueue() is not awaited,
3017+
// sendActivity() will return before the message is recorded, and the
3018+
// assertion below will fail.
3019+
const asyncEnqueued: Message[] = [];
3020+
const asyncQueue: MessageQueue = {
3021+
enqueue(message: Message): Promise<void> {
3022+
return new Promise<void>((resolve) => {
3023+
setTimeout(() => {
3024+
asyncEnqueued.push(message);
3025+
resolve();
3026+
}, 0);
3027+
});
3028+
},
3029+
async listen(): Promise<void> {},
3030+
};
3031+
const fed = new FederationImpl<void>({
3032+
kv,
3033+
contextLoaderFactory: () => mockDocumentLoader,
3034+
queue: asyncQueue,
3035+
manuallyStartQueue: true,
3036+
});
3037+
fed
3038+
.setActorDispatcher("/{identifier}", async (ctx, identifier) => {
3039+
if (identifier !== "john") return null;
3040+
const keys = await ctx.getActorKeyPairs(identifier);
3041+
return new vocab.Person({
3042+
id: ctx.getActorUri(identifier),
3043+
preferredUsername: "john",
3044+
publicKey: keys[0].cryptographicKey,
3045+
assertionMethods: keys.map((k) => k.multikey),
3046+
});
3047+
})
3048+
.setKeyPairsDispatcher((_ctx, identifier) => {
3049+
if (identifier !== "john") return [];
3050+
return [
3051+
{ privateKey: rsaPrivateKey2, publicKey: rsaPublicKey2.publicKey! },
3052+
{
3053+
privateKey: ed25519PrivateKey,
3054+
publicKey: ed25519PublicKey.publicKey!,
3055+
},
3056+
];
3057+
});
3058+
const ctx3 = new ContextImpl({
3059+
data: undefined,
3060+
federation: fed,
3061+
url: new URL("https://example.com/"),
3062+
documentLoader: mockDocumentLoader,
3063+
contextLoader: mockDocumentLoader,
3064+
});
3065+
const activity = new vocab.Create({
3066+
id: new URL("https://example.com/activity/1"),
3067+
actor: new URL("https://example.com/person"),
3068+
});
3069+
await ctx3.sendActivity(
3070+
{ username: "john" },
3071+
{
3072+
id: new URL("https://example.com/recipient"),
3073+
inboxId: new URL("https://example.com/inbox"),
3074+
},
3075+
activity,
3076+
{ fanout: "force" },
3077+
);
3078+
assertEquals(
3079+
asyncEnqueued.length,
3080+
1,
3081+
"fanoutQueue.enqueue() must be awaited before sendActivity() returns",
3082+
);
3083+
},
3084+
);
3085+
30043086
collectionSyncHeader = null;
30053087

30063088
await t.step("followers collection without syncCollection", async () => {

packages/fedify/src/federation/middleware.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2363,7 +2363,7 @@ export class ContextImpl<TContextData> implements Context<TContextData> {
23632363
if (!this.federation.manuallyStartQueue) {
23642364
this.federation._startQueueInternal(this.data);
23652365
}
2366-
this.federation.fanoutQueue.enqueue(
2366+
await this.federation.fanoutQueue.enqueue(
23672367
message,
23682368
{ orderingKey: options.orderingKey },
23692369
);

0 commit comments

Comments
 (0)