UNPKG

ipull

Version:

The only file downloader you'll ever need. For node.js and the browser, CLI and library for fast and reliable file downloads.

89 lines 3.66 kB
import { DownloadStatus } from "./progress-status-file.js"; import sleep from "sleep-promise"; const BASE_AVERAGE_SPEED_TIME = 1000; const AVERAGE_SPEED_TIME = 1000 * 8; const ALLOW_SPEED_DECREASE_PERCENTAGE = 10; const ADD_MORE_PARALLEL_IF_SPEED_INCREASE_PERCENTAGE = 10; export class DownloaderProgramManager { _program; _download; // date, speed _speedHistory = []; _lastResumeDate = 0; _lastAverageSpeed = 0; _increasePaused = false; _removeEvent; constructor(_program, _download) { this._program = _program; this._download = _download; this._initEvents(); } _initEvents() { let lastTransferredBytes = 0; let lastTransferredBytesDate = 0; let watNotActive = true; const progressEvent = (event) => { const now = Date.now(); if (event.retrying || event.downloadStatus != DownloadStatus.Active) { watNotActive = true; } else { if (watNotActive) { this._lastResumeDate = now; watNotActive = false; } const isTimeToCalculate = lastTransferredBytesDate + BASE_AVERAGE_SPEED_TIME < now; if (lastTransferredBytesDate === 0 || isTimeToCalculate) { if (isTimeToCalculate) { const speedPerSec = event.transferredBytes - lastTransferredBytes; this._speedHistory.push([now, speedPerSec]); } lastTransferredBytesDate = now; lastTransferredBytes = event.transferredBytes; } } const deleteAllBefore = now - AVERAGE_SPEED_TIME; this._speedHistory = this._speedHistory.filter(([date]) => date > deleteAllBefore); if (!watNotActive && now - this._lastResumeDate > AVERAGE_SPEED_TIME) { this._checkAction(); } }; this._download.on("progress", progressEvent); this._removeEvent = () => this._download.off("progress", progressEvent); } _calculateAverageSpeed() { const totalSpeed = this._speedHistory.reduce((acc, [, speed]) => acc + speed, 0); return totalSpeed / (this._speedHistory.length || 1); } async _checkAction() { const lastAverageSpeed = this._lastAverageSpeed; const newAverageSpeed = this._calculateAverageSpeed(); const speedDecreasedOK = (lastAverageSpeed - newAverageSpeed) / newAverageSpeed * 100 > ALLOW_SPEED_DECREASE_PERCENTAGE; if (!speedDecreasedOK) { this._lastAverageSpeed = newAverageSpeed; } if (this._increasePaused || newAverageSpeed > lastAverageSpeed || speedDecreasedOK) { return; } this._increasePaused = true; this._program.incParallelStreams(); let sleepTime = AVERAGE_SPEED_TIME; while (sleepTime <= AVERAGE_SPEED_TIME) { await sleep(sleepTime); sleepTime = Date.now() - this._lastResumeDate; } const newSpeed = this._calculateAverageSpeed(); const bestLastSpeed = Math.max(newAverageSpeed, lastAverageSpeed); const speedIncreasedOK = newSpeed > bestLastSpeed && (newSpeed - bestLastSpeed) / bestLastSpeed * 100 > ADD_MORE_PARALLEL_IF_SPEED_INCREASE_PERCENTAGE; if (speedIncreasedOK) { this._increasePaused = false; } else { this._program.decParallelStreams(); } } close() { this._removeEvent?.(); } } //# sourceMappingURL=downloaderProgramManager.js.map