fix(federation): hydrate downloads replicated avatars locally + backfill stale URL rows

hydrateReplicatedUserProfile now calls downloadProfileAsset and stores bare local filenames, falling back to absolute URLs only on download failure. It also fills empty fields only — no longer clobbering local files written by processProfileUpdateEvent. Adds an idempotent startup backfill that converts existing http-prefixed avatar/banner rows on replicated users into local files, so federated profile pictures keep rendering when the home instance is offline.
This commit is contained in:
Jannis Braun
2026-05-02 22:45:27 +02:00
parent c0fd7e3a75
commit c0e71b1ded
4 changed files with 136 additions and 30 deletions
@@ -12,6 +12,7 @@ import { connectionManager } from '../ws/handler.js';
import { generateThumbnail } from './thumbnail.js';
import type { FederationRelayRequest, FederationRelayResponse, FederationRelayEvent } from '@backspace/shared';
import { onPeerActivated, startupBootstrapSync, onPeerDeactivated } from './federationPeerActivation.js';
import { backfillReplicatedProfileAssets } from '../routes/federation.js';
import { invokePermanentFailureCallback } from './federationRollback.js';
import fs from 'node:fs';
import path from 'node:path';
@@ -1222,6 +1223,13 @@ export function startFederationWorkers(): void {
startupBootstrapSync().catch((err) => {
console.error('[federation-worker] Startup bootstrap sync error:', err);
});
// Backfill any replicated user avatars/banners still stored as absolute URLs
// (legacy data from before file replication, or rows whose home was offline
// on a previous attempt). Best-effort and idempotent — safe to re-run.
backfillReplicatedProfileAssets().catch((err) => {
console.error('[federation-worker] Replicated profile asset backfill error:', err);
});
}
export function stopFederationWorkers(): void {