feat(federation): add participant-aware fan-out routing for group DMs

This commit is contained in:
Jannis Braun
2026-03-26 20:10:51 +01:00
parent 0742c37ca1
commit 514d46c82e
+43 -2
View File
@@ -121,6 +121,7 @@ export function queueOutboxEvent(
dmChannelId: string,
eventType: string,
payload: string,
targetPeerOrigins?: string[],
): void {
try {
if (!isFederationRelayEnabled()) {
@@ -139,11 +140,20 @@ export function queueOutboxEvent(
return;
}
// If targetPeerOrigins specified, only queue to those peers
const peers = targetPeerOrigins
? activePeers.filter(p => targetPeerOrigins.includes(p.origin))
: activePeers;
if (peers.length === 0) {
return;
}
const ttlDays = getRelayTtlDays();
const now = Date.now();
const expiresAt = now + (ttlDays * 86_400_000);
for (const peer of activePeers) {
for (const peer of peers) {
db.transaction((tx) => {
const existing = tx
.select()
@@ -245,6 +255,35 @@ export function getDmParticipants(dmChannelId: string): FederationRelayParticipa
}));
}
/**
* Compute which peer origins need to receive events for a group DM.
* Returns undefined for 1-on-1 DMs (broadcast to all).
* Returns a list of origins for group DMs (participant-aware routing).
*/
export function getGroupDmTargetOrigins(dmChannelId: string): string[] | undefined {
const db = getDb();
const channel = db
.select({ ownerId: schema.dmChannels.ownerId })
.from(schema.dmChannels)
.where(eq(schema.dmChannels.id, dmChannelId))
.get();
// Not a group DM (no owner) — broadcast to all
if (!channel?.ownerId) return undefined;
const participants = getDmParticipants(dmChannelId);
const ourOrigin = getOurOrigin();
const origins = new Set<string>();
for (const p of participants) {
if (p.homeInstance !== ourOrigin) {
origins.add(p.homeInstance);
}
}
return Array.from(origins);
}
/**
* Queue a DM message for federation relay to all active peers.
* Builds the complete relay payload including attachments with sourceUrl
@@ -277,6 +316,8 @@ export function queueDmRelay(
const participants = getDmParticipants(dmChannelId);
const targetOrigins = getGroupDmTargetOrigins(dmChannelId);
appendMutationLog(message.id, dmChannelId, eventType);
queueOutboxEvent(message.id, dmChannelId, eventType, JSON.stringify({
message: {
@@ -284,7 +325,7 @@ export function queueDmRelay(
attachments: attachments.length > 0 ? attachments : undefined,
},
participants,
}));
}), targetOrigins);
}
/**