fix: guard AbortError from retry counting; eviction policy removes stale keys
This commit is contained in:
@@ -202,6 +202,11 @@ export class AppliedFontsManager {
|
|||||||
if (results[j].status === 'rejected') {
|
if (results[j].status === 'rejected') {
|
||||||
const [key, config] = chunk[j];
|
const [key, config] = chunk[j];
|
||||||
const reason = (results[j] as PromiseRejectedResult).reason;
|
const reason = (results[j] as PromiseRejectedResult).reason;
|
||||||
|
// Aborted fetches are not retriable failures — skip silently
|
||||||
|
const isAbort = reason instanceof FontFetchError
|
||||||
|
&& reason.cause instanceof Error
|
||||||
|
&& reason.cause.name === 'AbortError';
|
||||||
|
if (isAbort) continue;
|
||||||
if (reason instanceof FontFetchError) {
|
if (reason instanceof FontFetchError) {
|
||||||
console.error(`Font fetch failed: ${config.name}`, reason);
|
console.error(`Font fetch failed: ${config.name}`, reason);
|
||||||
}
|
}
|
||||||
@@ -276,6 +281,7 @@ export class AppliedFontsManager {
|
|||||||
// Clean up remaining state
|
// Clean up remaining state
|
||||||
this.#loadedFonts.delete(key);
|
this.#loadedFonts.delete(key);
|
||||||
this.statuses.delete(key);
|
this.statuses.delete(key);
|
||||||
|
this.#eviction.remove(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,23 @@ describe('FontEvictionPolicy', () => {
|
|||||||
expect(Array.from(policy.keys())).toEqual(expect.arrayContaining(['a@400', 'b@vf']));
|
expect(Array.from(policy.keys())).toEqual(expect.arrayContaining(['a@400', 'b@vf']));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('remove deletes key from tracking so it no longer appears in keys()', () => {
|
||||||
|
policy.touch('a@400', t0);
|
||||||
|
policy.touch('b@vf', t0);
|
||||||
|
policy.remove('a@400');
|
||||||
|
expect(Array.from(policy.keys())).not.toContain('a@400');
|
||||||
|
expect(Array.from(policy.keys())).toContain('b@vf');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('remove unpins the key so a subsequent touch + TTL would evict it', () => {
|
||||||
|
policy.touch('a@400', t0);
|
||||||
|
policy.pin('a@400');
|
||||||
|
policy.remove('a@400');
|
||||||
|
// re-touch and check it can be evicted again
|
||||||
|
policy.touch('a@400', t0);
|
||||||
|
expect(policy.shouldEvict('a@400', t0 + TTL)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
it('clear resets all state', () => {
|
it('clear resets all state', () => {
|
||||||
policy.touch('a@400', t0);
|
policy.touch('a@400', t0);
|
||||||
policy.pin('a@400');
|
policy.pin('a@400');
|
||||||
|
|||||||
@@ -58,6 +58,12 @@ export class FontEvictionPolicy {
|
|||||||
return this.#usageTracker.keys();
|
return this.#usageTracker.keys();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Removes a font key from tracking. Called by the orchestrator after eviction. */
|
||||||
|
remove(key: string): void {
|
||||||
|
this.#usageTracker.delete(key);
|
||||||
|
this.#pinnedFonts.delete(key);
|
||||||
|
}
|
||||||
|
|
||||||
/** Clears all usage timestamps and pinned keys. */
|
/** Clears all usage timestamps and pinned keys. */
|
||||||
clear(): void {
|
clear(): void {
|
||||||
this.#usageTracker.clear();
|
this.#usageTracker.clear();
|
||||||
|
|||||||
Reference in New Issue
Block a user