⚡ Bolt: [Deduplicate concurrent album fetches] (#50)

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
This commit is contained in:
Ralksta
2026-03-27 10:50:00 +01:00
committed by GitHub
parent f4778d09f6
commit 1704cd87fc
2 changed files with 67 additions and 49 deletions

View File

@@ -2,3 +2,8 @@
**Learning:** `useMemo` can significantly boost the performance of long list or grid components (like `PhotoGrid` component) that otherwise gets re-rendered on simple interactions like navigating the image lightbox. Running standard formatting `pnpm format` applies huge changes across entire directories, so it's generally best to format and clean up ONLY modified files to avoid huge diff pollution in code review.
**Action:** Be extremely cautious of running format/lint commands at the root codebase; specify only modified directories or files, or avoid formatting if it cascades globally. Focus on targeted memoization where state changes dictate expensive array mapping operations.
## 2024-05-28 - [Deduplicate concurrent API requests via Promise caching]
**Learning:** When using `Promise.all` to fetch dependent data in parallel (e.g., getting multiple subpages and standalone albums that internally call a shared `getAlbums` function), the internal cache might not be populated in time. This leads to redundant concurrent network requests to the upstream server.
**Action:** Implement Promise deduplication (request coalescing) by caching the pending Promise itself (e.g., in a `this.pendingPromise` class field) rather than just the final result. Return the pending Promise to subsequent callers until it resolves, ensuring only one network request is made.

View File

@@ -72,6 +72,7 @@ export interface SubpageSummary {
class ImmichClient {
private hasLoggedAlbums = false;
private pendingAlbumsPromise: Promise<ImmichAlbum[]> | null = null;
private get config() {
return getConfig();
@@ -152,6 +153,12 @@ class ImmichClient {
const cached = cache.get<ImmichAlbum[]>(cacheKey);
if (cached) return cached;
if (this.pendingAlbumsPromise) {
return this.pendingAlbumsPromise;
}
this.pendingAlbumsPromise = (async () => {
try {
const all = await this.request<ImmichAlbum[]>('/albums?shared=true');
if (!all) return [];
@@ -203,6 +210,12 @@ class ImmichClient {
cache.set(cacheKey, filtered, this.config.cacheTtl);
return filtered;
} finally {
this.pendingAlbumsPromise = null;
}
})();
return this.pendingAlbumsPromise;
}
/**