mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-15 19:10:47 +02:00
V2 Make FileId type opaque and use consistently throughout project (#4307)
# Description of Changes The `FileId` type in V2 currently is just defined to be a string. This makes it really easy to accidentally pass strings into things accepting file IDs (such as file names). This PR makes the `FileId` type [an opaque type](https://www.geeksforgeeks.org/typescript/opaque-types-in-typescript/), so it is compatible with things accepting strings (arguably not ideal for this...) but strings are not compatible with it without explicit conversion. The PR also includes changes to use `FileId` consistently throughout the project (everywhere I could find uses of `fileId: string`), so that we have the maximum benefit from the type safety. > [!note] > I've marked quite a few things as `FIX ME` where we're passing names in as IDs. If that is intended behaviour, I'm happy to remove the fix me and insert a cast instead, but they probably need comments explaining why we're using a file name as an ID.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useCallback, useRef } from 'react';
|
||||
import { thumbnailGenerationService } from '../services/thumbnailGenerationService';
|
||||
import { FileId } from '../types/file';
|
||||
|
||||
// Request queue to handle concurrent thumbnail requests
|
||||
interface ThumbnailRequest {
|
||||
@@ -35,44 +36,44 @@ async function processRequestQueue() {
|
||||
while (requestQueue.length > 0) {
|
||||
// Sort queue by page number to prioritize visible pages first
|
||||
requestQueue.sort((a, b) => a.pageNumber - b.pageNumber);
|
||||
|
||||
|
||||
// Take a batch of requests (same file only for efficiency)
|
||||
const batchSize = Math.min(BATCH_SIZE, requestQueue.length);
|
||||
const batch = requestQueue.splice(0, batchSize);
|
||||
|
||||
|
||||
// Group by file to process efficiently
|
||||
const fileGroups = new Map<File, ThumbnailRequest[]>();
|
||||
|
||||
|
||||
// First, resolve any cached thumbnails immediately
|
||||
const uncachedRequests: ThumbnailRequest[] = [];
|
||||
|
||||
|
||||
for (const request of batch) {
|
||||
const cached = thumbnailGenerationService.getThumbnailFromCache(request.pageId);
|
||||
if (cached) {
|
||||
request.resolve(cached);
|
||||
} else {
|
||||
uncachedRequests.push(request);
|
||||
|
||||
|
||||
if (!fileGroups.has(request.file)) {
|
||||
fileGroups.set(request.file, []);
|
||||
}
|
||||
fileGroups.get(request.file)!.push(request);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Process each file group with batch thumbnail generation
|
||||
for (const [file, requests] of fileGroups) {
|
||||
if (requests.length === 0) continue;
|
||||
|
||||
|
||||
try {
|
||||
const pageNumbers = requests.map(req => req.pageNumber);
|
||||
const arrayBuffer = await file.arrayBuffer();
|
||||
|
||||
|
||||
console.log(`📸 Batch generating ${requests.length} thumbnails for pages: ${pageNumbers.slice(0, 5).join(', ')}${pageNumbers.length > 5 ? '...' : ''}`);
|
||||
|
||||
|
||||
// Use file name as fileId for PDF document caching
|
||||
const fileId = file.name + '_' + file.size + '_' + file.lastModified;
|
||||
|
||||
const fileId = file.name + '_' + file.size + '_' + file.lastModified as FileId;
|
||||
|
||||
const results = await thumbnailGenerationService.generateThumbnails(
|
||||
fileId,
|
||||
arrayBuffer,
|
||||
@@ -83,11 +84,11 @@ async function processRequestQueue() {
|
||||
console.log(`📸 Batch progress: ${progress.completed}/${progress.total} thumbnails generated`);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
// Match results back to requests and resolve
|
||||
for (const request of requests) {
|
||||
const result = results.find(r => r.pageNumber === request.pageNumber);
|
||||
|
||||
|
||||
if (result && result.success && result.thumbnail) {
|
||||
thumbnailGenerationService.addThumbnailToCache(request.pageId, result.thumbnail);
|
||||
request.resolve(result.thumbnail);
|
||||
@@ -96,7 +97,7 @@ async function processRequestQueue() {
|
||||
request.resolve(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} catch (error) {
|
||||
console.warn(`Batch thumbnail generation failed for ${requests.length} pages:`, error);
|
||||
// Reject all requests in this batch
|
||||
@@ -115,7 +116,7 @@ async function processRequestQueue() {
|
||||
*/
|
||||
export function useThumbnailGeneration() {
|
||||
const generateThumbnails = useCallback(async (
|
||||
fileId: string,
|
||||
fileId: FileId,
|
||||
pdfArrayBuffer: ArrayBuffer,
|
||||
pageNumbers: number[],
|
||||
options: {
|
||||
@@ -157,22 +158,22 @@ export function useThumbnailGeneration() {
|
||||
clearTimeout(batchTimer);
|
||||
batchTimer = null;
|
||||
}
|
||||
|
||||
|
||||
// Clear the queue and active requests
|
||||
requestQueue.length = 0;
|
||||
activeRequests.clear();
|
||||
isProcessingQueue = false;
|
||||
|
||||
|
||||
thumbnailGenerationService.destroy();
|
||||
}, []);
|
||||
|
||||
const clearPDFCacheForFile = useCallback((fileId: string) => {
|
||||
const clearPDFCacheForFile = useCallback((fileId: FileId) => {
|
||||
thumbnailGenerationService.clearPDFCacheForFile(fileId);
|
||||
}, []);
|
||||
|
||||
const requestThumbnail = useCallback(async (
|
||||
pageId: string,
|
||||
file: File,
|
||||
pageId: string,
|
||||
file: File,
|
||||
pageNumber: number
|
||||
): Promise<string | null> => {
|
||||
// Check cache first for immediate return
|
||||
@@ -202,16 +203,16 @@ export function useThumbnailGeneration() {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Schedule batch processing with a small delay to collect more requests
|
||||
if (batchTimer) {
|
||||
clearTimeout(batchTimer);
|
||||
}
|
||||
|
||||
|
||||
// Use shorter delay for the first batch (pages 1-50) to show visible content faster
|
||||
const isFirstBatch = requestQueue.length <= BATCH_SIZE && requestQueue.every(req => req.pageNumber <= BATCH_SIZE);
|
||||
const delay = isFirstBatch ? PRIORITY_BATCH_DELAY : BATCH_DELAY;
|
||||
|
||||
|
||||
batchTimer = window.setTimeout(() => {
|
||||
processRequestQueue().catch(error => {
|
||||
console.error('Error processing thumbnail request queue:', error);
|
||||
@@ -222,7 +223,7 @@ export function useThumbnailGeneration() {
|
||||
|
||||
// Track this request to prevent duplicates
|
||||
activeRequests.set(pageId, requestPromise);
|
||||
|
||||
|
||||
return requestPromise;
|
||||
}, []);
|
||||
|
||||
@@ -236,4 +237,4 @@ export function useThumbnailGeneration() {
|
||||
clearPDFCacheForFile,
|
||||
requestThumbnail
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user