perf(web): batch dashboard tile hydration

This commit is contained in:
vince 2026-06-20 15:12:18 +02:00
parent 63b008095f
commit de87464ef1
7 changed files with 518 additions and 40 deletions

View file

@ -152,10 +152,12 @@ export async function runDashboardHydrationQueue<TItem>(
}
export interface DashboardViewportHydrationQueueOptions<TItem> {
batchSize?: number;
collectVisibleModelIds: () => Promise<ReadonlySet<string>>;
concurrency: number;
getModelId: (item: TItem) => string;
hydrate: (item: TItem) => Promise<void> | void;
hydrateBatch?: (items: TItem[]) => Promise<void> | void;
items: TItem[];
onAllItemsSettled?: () => void;
onVisibleItemsSettled?: () => void;
@ -175,12 +177,7 @@ export async function runViewportAwareDashboardHydrationQueue<TItem>(
visibleModelIds,
});
await runDashboardHydrationQueue({
concurrency: options.concurrency,
hydrate: options.hydrate,
items: visible,
signal: options.signal,
});
await runDashboardHydrationItems(options, visible);
if (options.signal.aborted) return;
options.onVisibleItemsSettled?.();
@ -192,13 +189,44 @@ export async function runViewportAwareDashboardHydrationQueue<TItem>(
await options.waitForIdle();
if (options.signal.aborted) return;
await runDashboardHydrationQueue({
concurrency: options.concurrency,
hydrate: options.hydrate,
items: deferred,
await runDashboardHydrationItems(options, deferred);
options.onAllItemsSettled?.();
}
async function runDashboardHydrationItems<TItem>(
options: DashboardViewportHydrationQueueOptions<TItem>,
items: TItem[],
): Promise<void> {
if (!options.hydrateBatch) {
await runDashboardHydrationQueue({
concurrency: options.concurrency,
hydrate: options.hydrate,
items,
signal: options.signal,
});
return;
}
await runDashboardHydrationBatchQueue({
batchSize: options.batchSize ?? options.concurrency,
hydrateBatch: options.hydrateBatch,
items,
signal: options.signal,
});
options.onAllItemsSettled?.();
}
export async function runDashboardHydrationBatchQueue<TItem>(options: {
batchSize: number;
hydrateBatch: (items: TItem[]) => Promise<void> | void;
items: TItem[];
signal: AbortSignal;
}): Promise<void> {
const batchSize = Math.max(1, Math.floor(options.batchSize));
for (let index = 0; index < options.items.length; index += batchSize) {
if (options.signal.aborted) return;
await options.hydrateBatch(options.items.slice(index, index + batchSize));
}
}
export function splitDashboardHydrationItemsByVisibility<TItem>(options: {