improved queue system

This commit is contained in:
Pierre
2025-11-01 23:00:14 +01:00
parent af278633c4
commit c6983be96b
+17 -15
View File
@@ -7,7 +7,7 @@ import {FileProcessorInterface} from "./FileProcessorInterface.js";
export class FolderWatcher { export class FolderWatcher {
initialized = false; initialized = false;
queue: PQueue; queue: PQueue; // Queue for basic concurrency control during file discovery
fileProcessor: FileProcessorInterface; fileProcessor: FileProcessorInterface;
queueSize = 0; queueSize = 0;
current = 0; current = 0;
@@ -21,8 +21,11 @@ export class FolderWatcher {
outputFolderUpdateIntervalMs?: number, outputFolderUpdateIntervalMs?: number,
concurrency?: number concurrency?: number
}) { }) {
// Initialize queue with configurable concurrency (default 4 to match typical CPU count) // Initialize queue for basic concurrency control
this.queue = new PQueue({concurrency: config.concurrency || 4, autoStart: true}); // Prevents overwhelming the system with too many concurrent file discoveries
const concurrency = config.concurrency || 4;
this.queue = new PQueue({concurrency, autoStart: true});
console.log(`FolderWatcher initialized with ${concurrency} workers for file processing`);
this.fileProcessor = fileProcessor; this.fileProcessor = fileProcessor;
if (this.fileProcessor.finalize) { if (this.fileProcessor.finalize) {
const debouncedImmediate = debounce(() => this.fileProcessor.finalize(), this.config.outputFolderUpdateIntervalMs || 10000, {immediate: true}); const debouncedImmediate = debounce(() => this.fileProcessor.finalize(), this.config.outputFolderUpdateIntervalMs || 10000, {immediate: true});
@@ -69,10 +72,10 @@ export class FolderWatcher {
// Push the promise without waiting for it here // Push the promise without waiting for it here
countPromises.push(this.countFile(fullPath)); countPromises.push(this.countFile(fullPath));
} else { } else {
// Use an IIFE (Immediately Invoked Function Expression) to handle asynchronous condition // Check if file can be processed (no queue needed for counting)
countPromises.push(this.queue.add( countPromises.push(
async () => (await this.fileProcessor.canProcessFile(fullPath)) ? 1 : 0 (async () => (await this.fileProcessor.canProcessFile(fullPath)) ? 1 : 0)()
)); );
} }
} }
@@ -87,21 +90,20 @@ export class FolderWatcher {
if (await this.fileProcessor.canProcessFile(filePath)) { if (await this.fileProcessor.canProcessFile(filePath)) {
const current = ++this.current; const current = ++this.current;
// Notify implementation that file is pending (optional callback) // Add to queue for concurrency control
// Allows tracking of files before they enter the processing queue // The FileProcessor implementation handles its own internal queue logic
await this.queue.add(async () => {
// Mark as pending (optional callback)
if (this.fileProcessor.markPending) { if (this.fileProcessor.markPending) {
this.fileProcessor.markPending(filePath); this.fileProcessor.markPending(filePath);
} }
// Add file to processing queue (respects concurrency limit) // Light processing (quick metadata extraction)
// Both queueFile() and processFile() are executed within the queue
// to ensure controlled concurrency across the entire processing pipeline
await this.queue.add(async () => {
// Optional: Quick/light pre-processing phase
if (this.fileProcessor.queueFile) { if (this.fileProcessor.queueFile) {
await this.fileProcessor.queueFile(filePath); await this.fileProcessor.queueFile(filePath);
} }
// Main processing phase
// Heavy processing (hash computation)
await this.fileProcessor.processFile(current, this.queueSize, filePath); await this.fileProcessor.processFile(current, this.queueSize, filePath);
}); });
} }