feat(journal): async federation inbox via Fedify message queue
Mastodon gives inbox deliveries a 10s read timeout; without a queue, Fedify runs inbox listeners AND outbound deliveries (the Accept we push back after a Follow) inside the inbound request. A slow or unreachable remote then blows the budget, the sender times out and its circuit breaker (Stoplight on Mastodon) cuts us off — observed live during the staging soak. InProcessMessageQueue + manuallyStartQueue: the queue consumer starts explicitly on first federation use (skipped under vitest so tests don't leak timers). In-process queueing is acceptable for the single-process journal: queued work lost on restart is recoverable (remotes retry Follows; activity push delivery is owned by our own pg-boss jobs). Revisit with a Postgres-backed MessageQueue if that changes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
74e50b2d6a
commit
7bcfa4cc76
1 changed files with 19 additions and 1 deletions
|
|
@ -26,7 +26,7 @@
|
|||
// exactly the "acknowledge and drop" the spec wants; the same applies
|
||||
// to wrapped types we inspect and ignore (e.g. Undo(Like)).
|
||||
import { configure, getConsoleSink } from "@logtape/logtape";
|
||||
import { createFederation, type Federation } from "@fedify/fedify";
|
||||
import { createFederation, InProcessMessageQueue, type Federation } from "@fedify/fedify";
|
||||
import { Accept, Follow, Person, PropertyValue, Reject, Undo } from "@fedify/fedify/vocab";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { users } from "@trails-cool/db/schema/journal";
|
||||
|
|
@ -129,10 +129,28 @@ function buildFederation(): Federation<void> {
|
|||
configureFederationLogging();
|
||||
const federation = createFederation<void>({
|
||||
kv: new PostgresKvStore(),
|
||||
// Message queue so inbox listener execution and outbound deliveries
|
||||
// (e.g. the Accept we push back after a Follow) happen asynchronously
|
||||
// with Fedify's own retry policy, instead of inside the inbound HTTP
|
||||
// request — Mastodon gives deliveries a 10s read timeout, and a slow
|
||||
// remote must never make us blow it. In-process is acceptable for
|
||||
// the single-process journal: queued work is lost on restart, but
|
||||
// every message type we enqueue is recoverable (remotes retry
|
||||
// Follows; our own pg-boss jobs own activity delivery). Revisit with
|
||||
// a Postgres-backed MessageQueue if that stops being true.
|
||||
queue: new InProcessMessageQueue(),
|
||||
// Started explicitly below — keeps vitest runs (which build this
|
||||
// instance via handleFederationRequest) free of dangling timers.
|
||||
manuallyStartQueue: true,
|
||||
// Canonical origin so generated IRIs are correct behind the Caddy
|
||||
// proxy (the Node server itself only sees plain HTTP).
|
||||
origin: getOrigin(),
|
||||
});
|
||||
if (!process.env.VITEST) {
|
||||
// Fire-and-forget: runs the queue consumer loop for the process
|
||||
// lifetime. Dev and prod both reach this on first federation use.
|
||||
void federation.startQueue(undefined);
|
||||
}
|
||||
|
||||
federation
|
||||
.setActorDispatcher("/users/{identifier}", async (ctx, identifier) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue