Merge pull request #2070 from PR0M3TH3AN/ai/perf-subscribeVideos-batching-9436508141846921918

⚡ Batch subscribeVideos updates to optimize initial load
This commit is contained in:
thePR0M3TH3AN authored and GitHub committed 2026-02-02 12:14:45 -05:00
commit 793a8ab8d3
3 files changed
+34 -19

No files matched your search

+21 -13
View File
@@ -7750,6 +7750,7 @@ export class NostrClient {
const toProcess = eventBuffer;
eventBuffer = [];
const updatedVideos = [];
for (const evt of toProcess) {
try {
@@ -7805,25 +7806,32 @@ export class NostrClient {
const prevActive = this.activeMap.get(activeKey);
if (!prevActive || video.created_at > prevActive.created_at) {
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
);
});
updatedVideos.push(video);
}
} catch (err) {
devLogger.error("[subscribeVideos] Error processing event:", err);
}
}
if (updatedVideos.length > 0) {
// Trigger the callback once per batch to avoid UI thrashing
onVideo(updatedVideos);
// Fetch NIP-71 metadata (categorization tags) in the background for the whole batch
this.populateNip71MetadataForVideos(updatedVideos)
.then(() => {
for (const video of updatedVideos) {
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");
};
+8 -4
View File
@@ -196,8 +196,10 @@ await (async function testDeleteFlowPublishesDeletionFlag() {
},
};
client.subscribeVideos((videoUpdate) => {
seenUpdates.push(videoUpdate);
client.subscribeVideos((videos) => {
if (Array.isArray(videos)) {
seenUpdates.push(...videos);
}
});
const deleteEvent = {
@@ -300,8 +302,10 @@ await (async function testSubscribeVideosSkipsOlderThanTombstone() {
},
};
client.subscribeVideos((videoUpdate) => {
seenUpdates.push(videoUpdate);
client.subscribeVideos((videos) => {
if (Array.isArray(videos)) {
seenUpdates.push(...videos);
}
});
const pubkey = "PUBKEY789";
+5 -2
View File
@@ -148,8 +148,11 @@ describe("NostrClient", () => {
client.pool.sub.mock.mockImplementation(() => subMock);
let capturedVideo = null;
const sub = client.subscribeVideos((video) => {
capturedVideo = video;
const sub = client.subscribeVideos((videos) => {
// Callback receives an array of updates
if (Array.isArray(videos) && videos.length > 0) {
capturedVideo = videos[0];
}
});
assert.ok(sub);