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