81 lines
2.1 KiB
TypeScript
81 lines
2.1 KiB
TypeScript
import { UrlCheckResult } from '../types';
|
|
|
|
const CACHE_TTL_MS = 5 * 60 * 1000;
|
|
const API_TIMEOUT_MS = 500;
|
|
const MAX_CACHE_SIZE = 5000;
|
|
|
|
export class UrlCache {
|
|
private cache: Map<string, { result: UrlCheckResult; expiresAt: number }> = new Map();
|
|
|
|
async get(url: string): Promise<UrlCheckResult | null> {
|
|
const normalized = this.normalizeUrl(url);
|
|
const entry = this.cache.get(normalized);
|
|
|
|
if (!entry) return null;
|
|
|
|
if (Date.now() > entry.expiresAt) {
|
|
this.cache.delete(normalized);
|
|
return null;
|
|
}
|
|
|
|
return { ...entry.result, cached: true };
|
|
}
|
|
|
|
async set(url: string, result: UrlCheckResult): Promise<void> {
|
|
const normalized = this.normalizeUrl(url);
|
|
|
|
if (this.cache.size >= MAX_CACHE_SIZE) {
|
|
const firstKey = this.cache.keys().next().value;
|
|
if (firstKey) this.cache.delete(firstKey);
|
|
}
|
|
|
|
this.cache.set(normalized, {
|
|
result,
|
|
expiresAt: Date.now() + CACHE_TTL_MS,
|
|
});
|
|
}
|
|
|
|
async persistToStorage(): Promise<void> {
|
|
const entries: Record<string, { result: UrlCheckResult; expiresAt: number }> = {};
|
|
for (const [key, value] of this.cache.entries()) {
|
|
entries[key] = value;
|
|
}
|
|
await chrome.storage.local.set({ urlCache: entries });
|
|
}
|
|
|
|
async loadFromStorage(): Promise<void> {
|
|
const data = await chrome.storage.local.get('urlCache') as { urlCache: Record<string, { result: UrlCheckResult; expiresAt: number }> };
|
|
if (data.urlCache) {
|
|
const now = Date.now();
|
|
for (const [key, entry] of Object.entries(data.urlCache)) {
|
|
if (now <= entry.expiresAt) {
|
|
this.cache.set(key, entry);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
getStats(): { size: number; max: number } {
|
|
return { size: this.cache.size, max: MAX_CACHE_SIZE };
|
|
}
|
|
|
|
clear(): void {
|
|
this.cache.clear();
|
|
}
|
|
|
|
private normalizeUrl(url: string): string {
|
|
try {
|
|
const u = new URL(url);
|
|
u.hash = '';
|
|
u.search = '';
|
|
return u.toString();
|
|
} catch {
|
|
return url.toLowerCase();
|
|
}
|
|
}
|
|
}
|
|
|
|
export const urlCache = new UrlCache();
|
|
export const CACHE_TTL = CACHE_TTL_MS;
|
|
export const API_TIMEOUT = API_TIMEOUT_MS;
|