UNPKG

stream-flow-control

Version:
111 lines (97 loc) 3.5 kB
const {Readable} = require('stream'); const {Manager} = require('../manager/manager.js'); const uuid = require('uuid'); const {DataWrapper} = require('../wrapper/data_wrapper.js') /** * Hold flow from multiple source streams until a condition is met. If no method is overwitten, then holds flow until end is signaled on all sources. * * @extends Readable */ class FlowHold extends Readable { /** * Create a FlowHold stream * @param {object} options Global options. * @param {string} [options.name] Name for this stream. * @param {Process} [options.hold] How messages are stored. * @param {function} [options.check] Checks a certain condition is met and call _options.release_. * @param {function} [options.release] Controls how messages are released. */ constructor(options) { options = {...options, objectMode: true}; super(options); this.options = options; /** @property Source streams */ this._sources = {}; /** @property Stored messages. There is an array for each source */ this._payloads = {}; this._parents = []; this._readableState.sync = false; this.type = 'FlowHold'; if(this.options.name) Manager.set(this.type, this); if(this.options.hold && typeof this.options.hold == 'function') this._hold = this.options.hold; if(this.options.release && typeof this.options.release == 'function') this._release = this.options.release; if(this.options.check && typeof this.options.check == 'function') this._check = this.options.check; this.on('pipe', (src)=>{ const id = this.goal || (src.options && src.options.name)?src.options.name:uuid.v4(); if(src.options && src.options.port) { id += '/'+src.options.port; } this._sources[id] = {src, ended: false}; src.on('data', (data)=>{ //console.log('hay data'); if(this.goal) { // Is goal player this._parents.push(data); } this._hold({ id, data }); }); src.on('end', () => { this._sources[id].ended = true; this._check(); }); this.on('pause', ()=>{ src.pause(); }); this.on('resume', ()=>{ src.resume(); }); }); } _hold(payload) { if(!this._payloads[payload.id]) this._payloads[payload.id] = []; if(this.goal) { // Is goal player // means payload.data is a DataWrapper payload.data = payload.data.data; } this._payloads[payload.id].push(payload.data); } _check() { for(let i in this._sources) { if(!this._sources[i].ended) return; } this._release(); } _release() { let payload = this._payloads; if(Object.keys(payload).length === 1) { for(let i in payload) { payload = payload[i]; } } if(this.goal) { // Is goal player payload = new DataWrapper(null, this).setParents(this._parents, payload); } this.push(payload); this.push(null); } write(payload) { } end() {} _read() {} } module.exports.FlowHold = FlowHold;