UNPKG

pull-drain-gently

Version:

Like pull.drain, but respects CPU load

92 lines (86 loc) 2.36 kB
var Pausable = require('pull-pause'); var usage = require('cpu-percentage'); // We need our own drain, should not import from pull-stream function drain(op, done) { var read, abort; function sink(_read) { read = _read; if (abort) return sink.abort(); (function next() { var loop = true; var cbed = false; while (loop) { cbed = false; read(null, (end, data) => { cbed = true; if ((end = end || abort)) { loop = false; if (done) done(end === true ? null : end); else if (end && end !== true) throw end; } else if ((op && false === op(data)) || abort) { loop = false; read(abort || true, done || (() => {})); } else if (!loop) { next(); } }); if (!cbed) { loop = false; return; } } })(); } sink.abort = (err, cb) => { if (typeof err === 'function') (cb = err), (err = true); abort = err || true; if (read) return read(abort, cb || (() => {})); }; return sink; } module.exports = function drainGently(a, b, c) { var opFirst = !a || typeof a === 'function'; var opts = opFirst ? {ceiling: 88, wait: 144, maxPause: Infinity} : a; var op = opFirst ? a : b; var opDone = opFirst ? b : c; var ceiling = opts.ceiling; var wait = opts.wait; var maxPause = opts.maxPause; var pausable = Pausable(); var start = (stats = usage()); var lastResume = Date.now() var step = 2, i = 0; function checkpoint() { stats = usage(start); if ( stats.percent < ceiling || // "CPU is cold enough" stats.time < 20 || // "we just now began draining" Date.now() - lastResume > maxPause // "remained paused for too long" ) { step = step << 1 || 1; lastResume = Date.now() pausable.resume(); } else { step = step >> 1 || 1; pausable.pause(); setTimeout(checkpoint, wait); } } function opWrapper(x) { var res; if (op) res = op(x); if (++i >= step) { i = 0; checkpoint(); } return res; } // The below does `return pull(pausable, drain(opWrapper, opDone))`: var _sink = drain(opWrapper, opDone); function sink(read) { _sink(pausable(read)); } sink.abort = _sink.abort; return sink; };