import { Worker } from 'worker_threads'; import cliProgress from 'cli-progress'; const MAX_THREADS = 10; export async function saveToc(epub, uploadPath, book_id, author_id) { const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic); progressBar.start(epub.toc.length, 0); let activeWorkers = 0; let currentIndex = 0; const promises = []; function startNextWorker() { if (currentIndex >= epub.toc.length) { return; } const elm = epub.toc[currentIndex]; currentIndex++; activeWorkers++; const promise = new Promise((resolve, reject) => { const worker = new Worker(new URL('./worker.mjs', import.meta.url), { workerData: { elm, book_id, author_id } }); worker.on('message', (message) => { progressBar.increment(); activeWorkers--; resolve(message); startNextWorker(); }); worker.on('error', (err) => { activeWorkers--; reject(err); startNextWorker(); }); worker.on('exit', (code) => { if (code !== 0) { reject(new Error(`Worker stopped with exit code ${code}`)); } }); }); promises.push(promise); } for (let i = 0; i < Math.min(MAX_THREADS, epub.toc.length); i++) { startNextWorker(); } await Promise.all(promises); progressBar.stop(); }