hfs
Version:
HTTP File Server
94 lines (93 loc) • 3 kB
JavaScript
"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;