Files
dees-catalog/ts_web/elements/dees-pdf-shared/PdfManager.ts

108 lines
2.7 KiB
TypeScript
Raw Normal View History

import { domtools } from '@design.estate/dees-element';
interface CachedDocument {
url: string;
document: any;
lastAccessed: number;
refCount: number;
}
export class PdfManager {
private static cache = new Map<string, CachedDocument>();
private static maxCacheSize = 10;
private static pdfjsLib: any;
private static initialized = false;
public static async initialize() {
if (this.initialized) return;
// @ts-ignore
this.pdfjsLib = await import('https://cdn.jsdelivr.net/npm/pdfjs-dist@4.0.379/+esm');
this.pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdn.jsdelivr.net/npm/pdfjs-dist@4.0.379/build/pdf.worker.mjs';
this.initialized = true;
}
public static async loadDocument(url: string): Promise<any> {
await this.initialize();
// Check cache first
const cached = this.cache.get(url);
if (cached) {
cached.lastAccessed = Date.now();
cached.refCount++;
return cached.document;
}
// Load new document
const loadingTask = this.pdfjsLib.getDocument(url);
const document = await loadingTask.promise;
// Add to cache with LRU eviction if needed
if (this.cache.size >= this.maxCacheSize) {
this.evictLeastRecentlyUsed();
}
this.cache.set(url, {
url,
document,
lastAccessed: Date.now(),
refCount: 1,
});
return document;
}
public static releaseDocument(url: string) {
const cached = this.cache.get(url);
if (cached) {
cached.refCount--;
if (cached.refCount <= 0) {
// Don't immediately remove, keep for potential reuse
cached.refCount = 0;
}
}
}
private static evictLeastRecentlyUsed() {
let oldestTime = Infinity;
let oldestKey: string | null = null;
for (const [key, value] of this.cache.entries()) {
// Only evict if not currently in use
if (value.refCount === 0 && value.lastAccessed < oldestTime) {
oldestTime = value.lastAccessed;
oldestKey = key;
}
}
if (oldestKey) {
const cached = this.cache.get(oldestKey);
if (cached?.document) {
cached.document.destroy?.();
}
this.cache.delete(oldestKey);
}
}
public static clearCache() {
for (const cached of this.cache.values()) {
if (cached.document) {
cached.document.destroy?.();
}
}
this.cache.clear();
}
public static getCacheStats() {
return {
size: this.cache.size,
maxSize: this.maxCacheSize,
entries: Array.from(this.cache.entries()).map(([url, data]) => ({
url,
refCount: data.refCount,
lastAccessed: new Date(data.lastAccessed).toISOString(),
})),
};
}
}