mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
perf: use batch fetch for profile refresh
Replaces the sequential loop in `forceRefreshAllProfiles` with `batchFetchProfiles` to reduce network requests. Updates `batchFetchProfilesFromRelays` to support `forceRefresh`, ensuring fresh data is requested while maintaining optimistic UI updates. Adds unit tests for `forceRefresh` behavior. Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
1 parent
c539fef553
commit
aae2ea7d16
3 files changed
+83
-4
No files matched your search
@@ -718,9 +718,7 @@ class Application {
|
||||
const uniqueAuthors = new Set(activeVideos.map((v) => v.pubkey));
|
||||
|
||||
// 3) For each author, fetchAndRenderProfile with forceRefresh = true
|
||||
for (const authorPubkey of uniqueAuthors) {
|
||||
this.authService.fetchAndRenderProfile(authorPubkey, true);
|
||||
}
|
||||
this.batchFetchProfiles(uniqueAuthors, { forceRefresh: true });
|
||||
}
|
||||
|
||||
getCurrentUserNpub() {
|
||||
@@ -2661,9 +2659,10 @@ class Application {
|
||||
return this.authService.fetchAndRenderProfile(pubkey, forceRefresh);
|
||||
}
|
||||
|
||||
async batchFetchProfiles(authorSet) {
|
||||
async batchFetchProfiles(authorSet, { forceRefresh = false } = {}) {
|
||||
return batchFetchProfilesFromRelays({
|
||||
authorSet,
|
||||
forceRefresh,
|
||||
getProfileCacheEntry: (pubkey) => this.getProfileCacheEntry(pubkey),
|
||||
setProfileCacheEntry: (pubkey, profile) =>
|
||||
this.setProfileCacheEntry(pubkey, profile),
|
||||
|
||||
@@ -10,6 +10,7 @@ const DEFAULT_PROFILE_IMAGE = "assets/svg/default-profile.svg";
|
||||
|
||||
export async function batchFetchProfilesFromRelays({
|
||||
authorSet,
|
||||
forceRefresh = false,
|
||||
getProfileCacheEntry,
|
||||
setProfileCacheEntry,
|
||||
updateProfileInDOM,
|
||||
@@ -50,6 +51,9 @@ export async function batchFetchProfilesFromRelays({
|
||||
const cacheEntry = getProfileCacheEntry(normalizedPubkey);
|
||||
if (cacheEntry) {
|
||||
updateProfileInDOM(normalizedPubkey, cacheEntry.profile);
|
||||
if (forceRefresh) {
|
||||
toFetch.push(normalizedPubkey);
|
||||
}
|
||||
} else {
|
||||
toFetch.push(normalizedPubkey);
|
||||
}
|
||||
|
||||
@@ -133,3 +133,79 @@ test("batchFetchProfiles handles fast and failing relays", async () => {
|
||||
{ pubkey: VALID_PUBKEY, profile: { name: "Fast", picture: "fast.png" } },
|
||||
]);
|
||||
});
|
||||
|
||||
test("batchFetchProfiles respects forceRefresh", async () => {
|
||||
const cache = new Map();
|
||||
const updates = [];
|
||||
const setCalls = [];
|
||||
const authorSet = new Set([
|
||||
CACHED_PUBKEY,
|
||||
]);
|
||||
|
||||
const getProfileCacheEntry = (pubkey) => {
|
||||
if (pubkey === CACHED_PUBKEY) {
|
||||
return { profile: { name: "Cached", picture: "cached.png" } };
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const setProfileCacheEntry = (pubkey, profile) => {
|
||||
cache.set(pubkey, { profile });
|
||||
setCalls.push({ pubkey, profile });
|
||||
};
|
||||
|
||||
const updateProfileInDOM = (pubkey, profile) => {
|
||||
updates.push({ pubkey, profile });
|
||||
};
|
||||
|
||||
const originalPool = nostrClient.pool;
|
||||
const poolListCalls = [];
|
||||
|
||||
nostrClient.pool = {
|
||||
list: (relays, filters) => {
|
||||
poolListCalls.push({ relays, filters });
|
||||
return Promise.resolve([
|
||||
createProfileEvent({
|
||||
pubkey: CACHED_PUBKEY,
|
||||
createdAt: 300,
|
||||
content: { name: "Refreshed", picture: "refreshed.png" },
|
||||
}),
|
||||
]);
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
await batchFetchProfilesFromRelays({
|
||||
authorSet,
|
||||
forceRefresh: true,
|
||||
getProfileCacheEntry,
|
||||
setProfileCacheEntry,
|
||||
updateProfileInDOM,
|
||||
});
|
||||
} finally {
|
||||
nostrClient.pool = originalPool;
|
||||
}
|
||||
|
||||
// Should fetch despite cache presence
|
||||
assert.ok(poolListCalls.length > 0, "should query relays when forceRefresh is true");
|
||||
assert.deepEqual(
|
||||
poolListCalls[0].filters[0].authors,
|
||||
[CACHED_PUBKEY],
|
||||
"should include cached pubkey in fetch list"
|
||||
);
|
||||
|
||||
// Should still optimistic update from cache first
|
||||
assert.deepEqual(
|
||||
updates[0],
|
||||
{ pubkey: CACHED_PUBKEY, profile: { name: "Cached", picture: "cached.png" } },
|
||||
"cached profiles should hydrate immediately even with forceRefresh"
|
||||
);
|
||||
|
||||
// Then update with fresh data
|
||||
const lastUpdate = updates[updates.length - 1];
|
||||
assert.deepEqual(
|
||||
lastUpdate,
|
||||
{ pubkey: CACHED_PUBKEY, profile: { name: "Refreshed", picture: "refreshed.png" } },
|
||||
"should update with refreshed data"
|
||||
);
|
||||
});
|
||||
Reference in new issue
Block a user