perf: Optimize nostrService video subscription updates

Optimizes the `subscribeVideos` callback in `js/services/nostrService.js` to handle video updates incrementally, avoiding O(N*M) complexity during high-volume updates (e.g., initial load).

Changes:
- Modified `js/nostr/videoEventBuffer.js` to include deleted videos in the flushed batch, allowing consumers to handle deletions incrementally.
- Updated `js/services/nostrService.js` to process `updatedVideos` incrementally:
  - Separates updates into active and deleted.
  - Updates `this.videosMap` directly (removing deleted, adding/updating active).
  - Filters and caches only the active updates (O(M)).
  - Emits `videos:updated` with the full sorted list (derived from the updated map) to maintain API contract with consumers.
  - Persists the full sorted list to localStorage.

This reduces the per-batch overhead significantly by avoiding O(N) filtering and map reconstruction for every batch of updates.

Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
google-labs-jules[bot]andPR0M3TH3AN committed 2026-02-26 17:48:37 +00:00
1 parent 9913e484ab
commit 6e42d2c97c
2 files changed
+54 -3

No files matched your search

+1
View File
@@ -130,6 +130,7 @@ export class VideoEventBuffer {
}
}
}
updatedVideos.push(video);
continue;
}
+53 -3
View File
@@ -1743,9 +1743,59 @@ export class NostrService {
limit: this.nostrClient.clampVideoRequestLimit(200),
};
const subscription = this.nostrClient.subscribeVideos(
() => {
const updated = this.nostrClient.getActiveVideos();
applyAndNotify(updated, "subscription");
(updatedVideos) => {
if (!Array.isArray(updatedVideos) || !updatedVideos.length) {
return;
}
const activeUpdates = [];
const deletedUpdates = [];
for (const v of updatedVideos) {
if (v.deleted) {
deletedUpdates.push(v);
} else {
activeUpdates.push(v);
}
}
if (deletedUpdates.length > 0) {
const map = this.ensureVideosMap();
for (const v of deletedUpdates) {
if (v.id) {
map.delete(v.id);
}
}
this.markAuthorIndexDirty();
}
const filtered = this.filterVideos(activeUpdates, {
blacklistedEventIds,
isAuthorBlocked,
});
if (filtered.length > 0) {
this.cacheVideos(filtered);
}
if (filtered.length > 0 || deletedUpdates.length > 0) {
// Persist the full list (latest N) from the now-updated cache
const map = this.ensureVideosMap();
const fullList = Array.from(map.values());
fullList.sort((a, b) => {
const aCreated = Number(a?.created_at) || 0;
const bCreated = Number(b?.created_at) || 0;
return bCreated - aCreated;
});
this.emit("videos:updated", {
videos: fullList,
deleted: deletedUpdates,
reason: "subscription",
});
persistFilteredVideos(fullList);
}
},
subscriptionOptions,
);