Increase concurrent workers and free up worker when thumbnails loaded

This commit is contained in:
Reece Browne 2025-08-26 00:06:14 +01:00
parent 9a55437aad
commit ecf5c93cc5
3 changed files with 22 additions and 21 deletions

View File

@ -16,7 +16,7 @@
} }
.pageContainer:hover .pageHoverControls { .pageContainer:hover .pageHoverControls {
opacity: 0.9 !important; opacity: 0.95 !important;
} }
/* Checkbox container - prevent transform inheritance */ /* Checkbox container - prevent transform inheritance */

View File

@ -12,7 +12,7 @@ class PDFWorkerManager {
private static instance: PDFWorkerManager; private static instance: PDFWorkerManager;
private activeDocuments = new Set<any>(); private activeDocuments = new Set<any>();
private workerCount = 0; private workerCount = 0;
private maxWorkers = 3; // Limit concurrent workers private maxWorkers = 10; // Limit concurrent workers
private isInitialized = false; private isInitialized = false;
private constructor() { private constructor() {
@ -33,7 +33,6 @@ class PDFWorkerManager {
if (!this.isInitialized) { if (!this.isInitialized) {
GlobalWorkerOptions.workerSrc = '/pdf.worker.js'; GlobalWorkerOptions.workerSrc = '/pdf.worker.js';
this.isInitialized = true; this.isInitialized = true;
console.log('🏭 PDF.js worker initialized');
} }
} }
@ -52,7 +51,6 @@ class PDFWorkerManager {
): Promise<any> { ): Promise<any> {
// Wait if we've hit the worker limit // Wait if we've hit the worker limit
if (this.activeDocuments.size >= this.maxWorkers) { if (this.activeDocuments.size >= this.maxWorkers) {
console.warn(`🏭 PDF Worker limit reached (${this.maxWorkers}), waiting for available worker...`);
await this.waitForAvailableWorker(); await this.waitForAvailableWorker();
} }
@ -89,8 +87,6 @@ class PDFWorkerManager {
this.activeDocuments.add(pdf); this.activeDocuments.add(pdf);
this.workerCount++; this.workerCount++;
console.log(`🏭 PDF document created (active: ${this.activeDocuments.size}/${this.maxWorkers})`);
return pdf; return pdf;
} catch (error) { } catch (error) {
// If document creation fails, make sure to clean up the loading task // If document creation fails, make sure to clean up the loading task
@ -98,7 +94,7 @@ class PDFWorkerManager {
try { try {
loadingTask.destroy(); loadingTask.destroy();
} catch (destroyError) { } catch (destroyError) {
console.warn('🏭 Error destroying failed loading task:', destroyError); // Silent cleanup failure
} }
} }
throw error; throw error;
@ -114,10 +110,7 @@ class PDFWorkerManager {
pdf.destroy(); pdf.destroy();
this.activeDocuments.delete(pdf); this.activeDocuments.delete(pdf);
this.workerCount = Math.max(0, this.workerCount - 1); this.workerCount = Math.max(0, this.workerCount - 1);
console.log(`🏭 PDF document destroyed (active: ${this.activeDocuments.size}/${this.maxWorkers})`);
} catch (error) { } catch (error) {
console.warn('🏭 Error destroying PDF document:', error);
// Still remove from tracking even if destroy failed // Still remove from tracking even if destroy failed
this.activeDocuments.delete(pdf); this.activeDocuments.delete(pdf);
this.workerCount = Math.max(0, this.workerCount - 1); this.workerCount = Math.max(0, this.workerCount - 1);
@ -129,8 +122,6 @@ class PDFWorkerManager {
* Destroy all active PDF documents * Destroy all active PDF documents
*/ */
destroyAllDocuments(): void { destroyAllDocuments(): void {
console.log(`🏭 Destroying all PDF documents (${this.activeDocuments.size} active)`);
const documentsToDestroy = Array.from(this.activeDocuments); const documentsToDestroy = Array.from(this.activeDocuments);
documentsToDestroy.forEach(pdf => { documentsToDestroy.forEach(pdf => {
this.destroyDocument(pdf); this.destroyDocument(pdf);
@ -138,8 +129,6 @@ class PDFWorkerManager {
this.activeDocuments.clear(); this.activeDocuments.clear();
this.workerCount = 0; this.workerCount = 0;
console.log('🏭 All PDF documents destroyed');
} }
/** /**
@ -173,21 +162,17 @@ class PDFWorkerManager {
* Force cleanup of all workers (emergency cleanup) * Force cleanup of all workers (emergency cleanup)
*/ */
emergencyCleanup(): void { emergencyCleanup(): void {
console.warn('🏭 Emergency PDF worker cleanup initiated');
// Force destroy all documents // Force destroy all documents
this.activeDocuments.forEach(pdf => { this.activeDocuments.forEach(pdf => {
try { try {
pdf.destroy(); pdf.destroy();
} catch (error) { } catch (error) {
console.warn('🏭 Emergency cleanup - error destroying document:', error); // Silent cleanup
} }
}); });
this.activeDocuments.clear(); this.activeDocuments.clear();
this.workerCount = 0; this.workerCount = 0;
console.warn('🏭 Emergency cleanup completed');
} }
/** /**
@ -195,7 +180,6 @@ class PDFWorkerManager {
*/ */
setMaxWorkers(max: number): void { setMaxWorkers(max: number): void {
this.maxWorkers = Math.max(1, Math.min(max, 15)); // Between 1-15 workers for multi-file support this.maxWorkers = Math.max(1, Math.min(max, 15)); // Between 1-15 workers for multi-file support
console.log(`🏭 Max workers set to ${this.maxWorkers}`);
} }
} }

View File

@ -40,7 +40,7 @@ export class ThumbnailGenerationService {
private pdfDocumentCache = new Map<string, CachedPDFDocument>(); private pdfDocumentCache = new Map<string, CachedPDFDocument>();
private maxPdfCacheSize = 10; // Keep up to 10 PDF documents cached private maxPdfCacheSize = 10; // Keep up to 10 PDF documents cached
constructor(private maxWorkers: number = 3) { constructor(private maxWorkers: number = 10) {
// PDF rendering requires DOM access, so we use optimized main thread processing // PDF rendering requires DOM access, so we use optimized main thread processing
} }
@ -207,6 +207,11 @@ export class ThumbnailGenerationService {
// Release reference to PDF document (don't destroy - keep in cache) // Release reference to PDF document (don't destroy - keep in cache)
this.releasePDFDocument(fileId); this.releasePDFDocument(fileId);
// Optionally clean up PDF document from cache to free workers faster
// This can be called after thumbnail generation is complete for a file
this.cleanupCompletedDocument(fileId);
return allResults; return allResults;
} }
@ -289,6 +294,18 @@ export class ThumbnailGenerationService {
} }
} }
/**
* Clean up a PDF document from cache when thumbnail generation is complete
* This frees up workers faster for better performance
*/
cleanupCompletedDocument(fileId: string): void {
const cached = this.pdfDocumentCache.get(fileId);
if (cached && cached.refCount <= 0) {
pdfWorkerManager.destroyDocument(cached.pdf);
this.pdfDocumentCache.delete(fileId);
}
}
destroy(): void { destroy(): void {
this.clearCache(); this.clearCache();
this.clearPDFCache(); this.clearPDFCache();