UNPKG

hfs

Version:
94 lines (93 loc) 3 kB
"use strict"; // This file is part of HFS - Copyright 2021-2023, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt Object.defineProperty(exports, "__esModule", { value: true }); exports.ThrottleGroup = exports.ThrottledStream = void 0; const stream_1 = require("stream"); const limiter_1 = require("limiter"); // throttled stream class ThrottledStream extends stream_1.Transform { constructor(group, copyStats) { super(); this.group = group; this.sent = 0; this.lastSpeed = 0; this.lastSpeedTime = Date.now(); this.totalSent = 0; // total sent over connection, since connection can be re-used for multiple requests if (!copyStats) return; this.sent = copyStats.sent; this.totalSent = copyStats.totalSent; this.lastSpeedTime = copyStats.lastSpeedTime; this.lastSpeed = copyStats.lastSpeed; } async _transform(chunk, encoding, done) { let pos = 0; while (1) { let n = this.group.suggestChunkSize(); const slice = chunk.slice(pos, pos + n); n = slice.length; if (!n) // we're done here return done(); try { await this.group.consume(n); this.push(slice); this.sent += n; this.totalSent += n; pos += n; this.emit('sent', n); } catch (e) { done(e); return; } } } // @return kBs getSpeed() { const now = Date.now(); const past = now - this.lastSpeedTime; if (past >= 1000) { // recalculate? this.lastSpeedTime = now; this.lastSpeed = this.sent / past; this.sent = 0; } return this.lastSpeed; } getBytesSent() { return this.totalSent; } } exports.ThrottledStream = ThrottledStream; class ThrottleGroup { constructor(kBs, parent) { this.parent = parent; this.bucket = this.updateLimit(kBs); // assignment is redundant and yet the best way I've found to shut up typescript } // @return kBs getLimit() { return this.bucket.bucketSize / 1000; } updateLimit(kBs) { if (kBs < 0) throw new Error('invalid bytesPerSecond'); kBs *= 1000; return this.bucket = new limiter_1.TokenBucket({ bucketSize: kBs, tokensPerInterval: kBs, interval: 'second', }); } suggestChunkSize() { var _a; let b = this.bucket; b.parentBucket = (_a = this.parent) === null || _a === void 0 ? void 0 : _a.bucket; let min = b.bucketSize; while (b = b.parentBucket) min = Math.min(min, b.bucketSize); return min / 10; } consume(n) { return this.bucket.removeTokens(n); } } exports.ThrottleGroup = ThrottleGroup;