From ecf5c93cc566565d9e6ef88f3f9c6bee117b9f5f Mon Sep 17 00:00:00 2001 From: Reece Browne Date: Tue, 26 Aug 2025 00:06:14 +0100 Subject: [PATCH] Increase concurrent workers and free up worker when thumbnails loaded --- .../pageEditor/PageEditor.module.css | 2 +- frontend/src/services/pdfWorkerManager.ts | 22 +++---------------- .../services/thumbnailGenerationService.ts | 19 +++++++++++++++- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/frontend/src/components/pageEditor/PageEditor.module.css b/frontend/src/components/pageEditor/PageEditor.module.css index 4cbfc05fb..b172aff23 100644 --- a/frontend/src/components/pageEditor/PageEditor.module.css +++ b/frontend/src/components/pageEditor/PageEditor.module.css @@ -16,7 +16,7 @@ } .pageContainer:hover .pageHoverControls { - opacity: 0.9 !important; + opacity: 0.95 !important; } /* Checkbox container - prevent transform inheritance */ diff --git a/frontend/src/services/pdfWorkerManager.ts b/frontend/src/services/pdfWorkerManager.ts index 012e5086b..c15e2c207 100644 --- a/frontend/src/services/pdfWorkerManager.ts +++ b/frontend/src/services/pdfWorkerManager.ts @@ -12,7 +12,7 @@ class PDFWorkerManager { private static instance: PDFWorkerManager; private activeDocuments = new Set(); private workerCount = 0; - private maxWorkers = 3; // Limit concurrent workers + private maxWorkers = 10; // Limit concurrent workers private isInitialized = false; private constructor() { @@ -33,7 +33,6 @@ class PDFWorkerManager { if (!this.isInitialized) { GlobalWorkerOptions.workerSrc = '/pdf.worker.js'; this.isInitialized = true; - console.log('🏭 PDF.js worker initialized'); } } @@ -52,7 +51,6 @@ class PDFWorkerManager { ): Promise { // Wait if we've hit the worker limit if (this.activeDocuments.size >= this.maxWorkers) { - console.warn(`🏭 PDF Worker limit reached (${this.maxWorkers}), waiting for available worker...`); await this.waitForAvailableWorker(); } @@ -89,8 +87,6 @@ class PDFWorkerManager { this.activeDocuments.add(pdf); this.workerCount++; - console.log(`🏭 PDF document created (active: ${this.activeDocuments.size}/${this.maxWorkers})`); - return pdf; } catch (error) { // If document creation fails, make sure to clean up the loading task @@ -98,7 +94,7 @@ class PDFWorkerManager { try { loadingTask.destroy(); } catch (destroyError) { - console.warn('🏭 Error destroying failed loading task:', destroyError); + // Silent cleanup failure } } throw error; @@ -114,10 +110,7 @@ class PDFWorkerManager { pdf.destroy(); this.activeDocuments.delete(pdf); this.workerCount = Math.max(0, this.workerCount - 1); - - console.log(`🏭 PDF document destroyed (active: ${this.activeDocuments.size}/${this.maxWorkers})`); } catch (error) { - console.warn('🏭 Error destroying PDF document:', error); // Still remove from tracking even if destroy failed this.activeDocuments.delete(pdf); this.workerCount = Math.max(0, this.workerCount - 1); @@ -129,8 +122,6 @@ class PDFWorkerManager { * Destroy all active PDF documents */ destroyAllDocuments(): void { - console.log(`🏭 Destroying all PDF documents (${this.activeDocuments.size} active)`); - const documentsToDestroy = Array.from(this.activeDocuments); documentsToDestroy.forEach(pdf => { this.destroyDocument(pdf); @@ -138,8 +129,6 @@ class PDFWorkerManager { this.activeDocuments.clear(); this.workerCount = 0; - - console.log('🏭 All PDF documents destroyed'); } /** @@ -173,21 +162,17 @@ class PDFWorkerManager { * Force cleanup of all workers (emergency cleanup) */ emergencyCleanup(): void { - console.warn('🏭 Emergency PDF worker cleanup initiated'); - // Force destroy all documents this.activeDocuments.forEach(pdf => { try { pdf.destroy(); } catch (error) { - console.warn('🏭 Emergency cleanup - error destroying document:', error); + // Silent cleanup } }); this.activeDocuments.clear(); this.workerCount = 0; - - console.warn('🏭 Emergency cleanup completed'); } /** @@ -195,7 +180,6 @@ class PDFWorkerManager { */ setMaxWorkers(max: number): void { 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}`); } } diff --git a/frontend/src/services/thumbnailGenerationService.ts b/frontend/src/services/thumbnailGenerationService.ts index a1c221269..be508fd1a 100644 --- a/frontend/src/services/thumbnailGenerationService.ts +++ b/frontend/src/services/thumbnailGenerationService.ts @@ -40,7 +40,7 @@ export class ThumbnailGenerationService { private pdfDocumentCache = new Map(); 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 } @@ -207,6 +207,11 @@ export class ThumbnailGenerationService { // Release reference to PDF document (don't destroy - keep in cache) 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; } @@ -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 { this.clearCache(); this.clearPDFCache();