Precache all thumbnails and pinned originals inside open() (closes #48)
check / check (push) Successful in 26s

Precaches aggressively inside open(): every thumbnail (newest first, through the shared thumbnail pool, never evicted; visible/ahead requests preempt the background fill) and the pinned originals — the favorites album plus every file within precacheOriginalsDays (default 7) of the newest takenAt — through the content pool. The pinned set integrates with the #47 eviction hook; when the window moves or a favorite is removed, files become ordinary evictable originals. open() options precacheThumbnails/precacheOriginals/precacheOriginalsDays; progress via onProgress/status().

Model: opus-4-8
This commit was merged in pull request #73.
This commit is contained in:
2026-09-22 21:21:34 +02:00
parent e8575780e4
commit 2e00139d3c
6 changed files with 835 additions and 23 deletions
+38 -9
View File
@@ -328,12 +328,45 @@ export class ContentCache implements PhotoContent, ThumbnailsAPI {
}
async ensureThumbnails(args: EnsureOptions): Promise<EnsureResult[]> {
const priority = poolPriorityOf(args.priority);
return this.ensureMany(
"thumbnail",
poolPriorityOf(args.priority),
args.fileIDs,
args.signal,
args.onProgress,
);
}
// Fill originals through the content pool for the precache (#48), always at
// background priority so an on-demand `original()` preempts the fill. A
// present original is a map lookup and no fetch; a per-file failure is
// returned, not thrown, so one bad file never halts a background sweep.
async ensureOriginals(args: {
fileIDs: number[];
signal?: AbortSignal;
onProgress?: (event: EnsureEvent) => void;
}): Promise<EnsureResult[]> {
return this.ensureMany(
"original",
"background",
args.fileIDs,
args.signal,
args.onProgress,
);
}
private async ensureMany(
kind: Kind,
priority: Priority,
fileIDs: number[],
signal: AbortSignal | undefined,
onProgress: ((event: EnsureEvent) => void) | undefined,
): Promise<EnsureResult[]> {
// Dedup the request list so a repeated fileID is fetched once and
// reported once, in first-requested order.
const seen = new Set<number>();
const unique: number[] = [];
for (const id of args.fileIDs) {
for (const id of fileIDs) {
if (!seen.has(id)) {
seen.add(id);
unique.push(id);
@@ -341,24 +374,20 @@ export class ContentCache implements PhotoContent, ThumbnailsAPI {
}
return Promise.all(
unique.map((fileID) =>
this.ensureOne(fileID, priority, args.signal, args.onProgress),
this.ensureOne(fileID, kind, priority, signal, onProgress),
),
);
}
private async ensureOne(
fileID: number,
kind: Kind,
priority: Priority,
signal: AbortSignal | undefined,
onProgress: ((event: EnsureEvent) => void) | undefined,
): Promise<EnsureResult> {
try {
const result = await this.acquire(
fileID,
"thumbnail",
priority,
signal,
);
const result = await this.acquire(fileID, kind, priority, signal);
const status = result.cached ? "skipped" : "done";
onProgress?.({ fileID, status, path: result.path });
return { fileID, path: result.path };