'use strict'; // Queue tuần tự hoá thao tác Puppeteer — tránh race condition trong 1 browser slot class AsyncQueue { constructor(name = 'default') { this._name = name; this._running = false; this._queue = []; } add(fn, label = 'task') { return new Promise((resolve, reject) => { this._queue.push({ fn, resolve, reject, label }); this._next(); }); } async _next() { if (this._running || this._queue.length === 0) return; this._running = true; const { fn, resolve, reject, label } = this._queue.shift(); try { console.log(`[queue:${this._name}] → ${label}`); resolve(await fn()); } catch (err) { console.error(`[queue:${this._name}] ✗ ${label}:`, err.message); reject(err); } finally { this._running = false; this._next(); } } get size() { return this._queue.length; } get busy() { return this._running; } } module.exports = new AsyncQueue('global'); module.exports.AsyncQueue = AsyncQueue;