// Pause-Schranke für Übertragungen: Arbeitsschritte rufen vor jedem Schritt wait() auf und bleiben // dort stehen, solange pausiert ist. Ein Abbruch (AbortSignal) löst wartende Schritte sofort mit // dem Abbruchfehler (code UPLOAD_CANCELLED) aus. // // Pausiert wird zwischen den Schritten, nicht mittendrin: Ein laufender Clone, Push oder // Paket-Upload wird erst fertig, danach hält die Übertragung an. function cancelledError() { const err = new Error('Upload abgebrochen'); err.code = 'UPLOAD_CANCELLED'; return err; } function createPauseGate({ onChange } = {}) { let paused = false; let waiters = []; function setPaused(value) { if (paused === value) return false; paused = value; if (!value) { const release = waiters; waiters = []; for (const w of release) w.resolve(); } if (onChange) { try { onChange(paused); } catch (_) {} } return true; } function wait(signal) { if (signal && signal.aborted) return Promise.reject(cancelledError()); if (!paused) return Promise.resolve(); return new Promise((resolve, reject) => { const waiter = { resolve: null }; const onAbort = () => { waiters = waiters.filter((w) => w !== waiter); reject(cancelledError()); }; waiter.resolve = () => { if (signal) signal.removeEventListener('abort', onAbort); resolve(); }; waiters.push(waiter); if (signal) signal.addEventListener('abort', onAbort, { once: true }); }); } return { pause: () => setPaused(true), resume: () => setPaused(false), isPaused: () => paused, waitingCount: () => waiters.length, wait }; } module.exports = { createPauseGate };