This repository has been archived on 2025-10-29. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
gekko/core/gekkoStream.js
T
2021-06-06 20:25:14 +02:00

121 lines
3.0 KiB
JavaScript

// Small writable stream wrapper that
// passes data to all `candleConsumers`.
const Writable = require('stream').Writable;
const _ = require('lodash');
const async = require('async');
const moment = require('moment');
const util = require('./util');
const env = util.gekkoEnv();
const mode = util.gekkoMode();
const config = util.getConfig();
const log = require(util.dirs().core + 'log');
var Gekko = function(plugins) {
this.plugins = plugins;
this.candleConsumers = plugins
.filter(plugin => plugin.processCandle);
Writable.call(this, {objectMode: true});
this.producers = this.plugins
.filter(p => p.meta.emits);
this.finalize = _.bind(this.finalize, this);
}
Gekko.prototype = Object.create(Writable.prototype, {
constructor: { value: Gekko }
});
if(config.debug && mode !== 'importer') {
// decorate with more debug information
Gekko.prototype._write = function(chunk, encoding, _done) {
if(chunk.isFinished) {
return this.finalize();
}
const start = moment();
var relayed = false;
var at = null;
const timer = setTimeout(() => {
if(!relayed)
log.error([
`The plugin "${at}" has not processed a candle for 1 second.`,
`This will cause Gekko to slow down or stop working completely.`
].join(' '));
}, 1000);
const flushEvents = _.after(this.candleConsumers.length, () => {
relayed = true;
clearInterval(timer);
this.flushDefferedEvents();
_done();
});
_.each(this.candleConsumers, function(c) {
at = c.meta.name;
c.processCandle(chunk, flushEvents);
}, this);
}
} else {
// skip decoration
Gekko.prototype._write = function(chunk, encoding, _done) {
if(chunk.isFinished) {
return this.finalize();
}
const flushEvents = _.after(this.candleConsumers.length, () => {
this.flushDefferedEvents();
_done();
});
_.each(this.candleConsumers, function(c) {
c.processCandle(chunk, flushEvents);
}, this);
}
}
Gekko.prototype.flushDefferedEvents = function() {
const broadcasted = _.find(
this.producers,
producer => producer.broadcastDeferredEmit()
);
// If we braodcasted anything we might have
// triggered more events, recurse until we
// have fully broadcasted everything.
if(broadcasted)
this.flushDefferedEvents();
}
Gekko.prototype.finalize = function() {
var tradingMethod = _.find(
this.candleConsumers,
c => c.meta.name === 'Trading Advisor'
);
if(!tradingMethod)
return this.shutdown();
tradingMethod.finish(this.shutdown.bind(this));
}
Gekko.prototype.shutdown = function() {
this.end();
async.eachSeries(
this.plugins,
function(c, callback) {
if (c.finalize) c.finalize(callback);
else callback();
},
() => {
// If we are a child process, we signal to the parent to kill the child once it is done
// so that is has time to process all remaining events (and send report data)
if (env === 'child-process') process.send('done');
else process.exit(0);
}
);
};
module.exports = Gekko;