perf: Batch NIP-71 metadata fetches in NostrClient

Currently, when the NostrClient processes a burst of video events (e.g., initial
feed load), it triggers an individual NIP-71 metadata fetch for every video that
updates the `activeMap`. This results in a stampede of network requests (N videos
* M relays).

This change optimizes `flushEventBuffer` to collect all videos requiring metadata
updates and executes a single batched `populateNip71MetadataForVideos` call at
the end of the flush cycle.

This reduces the metadata fetch overhead from O(N) to O(1) per batch.

Verified with a local benchmark script (reduced fetch calls from 50 to 1 for 50 events)
and existing unit tests.

Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
google-labs-jules[bot]andPR0M3TH3AN committed 2026-01-31 19:36:08 +00:00
1 parent 20f2cba238
commit 5a5772de3a
1 file changed
+19 -11
+19 -11
View File
@@ -7650,6 +7650,7 @@ export class NostrClient {
const toProcess = eventBuffer;
eventBuffer = [];
const videosNeedingMetadata = [];
for (const evt of toProcess) {
try {
@@ -7706,23 +7707,30 @@ export class NostrClient {
this.activeMap.set(activeKey, video);
onVideo(video); // Trigger the callback that re-renders
// Fetch NIP-71 metadata (categorization tags) in the background
this.populateNip71MetadataForVideos([video])
.then(() => {
this.applyRootCreatedAt(video);
})
.catch((error) => {
devLogger.warn(
"[nostr] Failed to hydrate NIP-71 metadata for live video:",
error
);
});
// Defer NIP-71 fetch for batching
videosNeedingMetadata.push(video);
}
} catch (err) {
devLogger.error("[subscribeVideos] Error processing event:", err);
}
}
if (videosNeedingMetadata.length > 0) {
// Fetch NIP-71 metadata (categorization tags) in the background
this.populateNip71MetadataForVideos(videosNeedingMetadata)
.then(() => {
for (const video of videosNeedingMetadata) {
this.applyRootCreatedAt(video);
}
})
.catch((error) => {
devLogger.warn(
"[nostr] Failed to hydrate NIP-71 metadata for live video batch:",
error,
);
});
}
// Persist processed events after each flush so reloads warm quickly.
this.saveLocalData("subscribeVideos:flush");
};