briareus
Version:
Briareus assists with Feature Branch deploys to ECS
153 lines (125 loc) • 3.81 kB
JavaScript
'use strict'
const async = require('async');
const _ = require('lodash');
const EventEmitter2 = require('eventemitter2').EventEmitter2;
class Variant extends EventEmitter2 {
constructor(cli, options = {}) {
super();
this.cli = cli;
this.config = _.merge(this.cli.packageBriareusConfig(), this.cli.params);
this.options = _.defaults(options, {
durationBetweenPolls: 3000
});
this.data = {};
this.created = false;
this.eventBuffer = async.queue(this._eventBufferWorker.bind(this));
this.events = [];
this.end = false;
this.on('updated', this._emitNewEvents.bind(this));
this.on('state', this._processStateChanges.bind(this));
this.on('deploy:end', this.destroy.bind(this));
this.pollInterval = setInterval(this.refresh.bind(this, _.noop), this.options.durationBetweenPolls);
}
/**
* Event Buffer Worker
*
* Ensures events are processed synchronously.
*
* @param {object} event The event to process
* @param {function} cb Callback
*/
_eventBufferWorker(event, cb) {
this.cli.log.debug(event, `Variant Event`);
this.emit('event', event);
this.emit(event.name, event);
this.events.push(event);
cb();
}
/**
* _emitNewEvents
*
* Emit new events that have arrived since last time events
* were emited. Called on service 'updated' event.
*/
_emitNewEvents() {
this.cli.log.info('Emitting new variant events');
let index = 0;
if (!this.lastEventId) {
let lastDeployEnd = this._getEvent('deploy:end')
if (lastDeployEnd) this.lastEventId = lastDeployEnd.id;
}
if (this.lastEventId) {
index = _.findIndex(this.data.events, (event) => event.id === this.lastEventId) + 1;
}
let events = this.data.events.slice(index);
if (events.length > 0) this.lastEventId = _.last(events).id;
events.forEach((event) => this.eventBuffer.push(event, _.noop));
}
_getStateEvent(state) {
return _.findLast(this.data.events, (event) => {
return (event.name === 'state' && event.data.state === state)
});
}
_getEvent(name) {
return _.findLast(this.data.events, (event) => event.name === name);
}
/**
* _processStateChanges
*
* Emit state specific events when state changes
*/
_processStateChanges(event) {
this.emit(`state:${event.data.state}`, event);
}
refresh(cb) {
this.cli.api.variant.get({ slug: this.config.slug }, (err, resp) => {
// If 404, Variant hasn't been created yet
if (err && err.code === 404) return cb();
if (err) return cb(err);
this.data = resp.data;
this.created = true;
this.emit('updated');
cb();
});
}
create(cb) {
this.cli.api.variant.create({ data: this.config }, (err, resp) => {
if (err) return cb(err);
this.data = resp.data;
this.emit('updated');
cb()
});
}
init(cb) {
async.series([
(next) => this.refresh(next),
(next) => {
if (this.created && this.data.provisioned === true) return next();
// Wait for Variant to become provisioned before continuing
this.once('state:provisioned', _.ary(next, 0));
if (!this.created) {
this.create((err) => {
if (err) return next(err);
// Do not call next here. We wait for state:provisioned instead
});
}
}
], cb);
}
deploy(cb) {
let params = {
slug: this.data.slug,
data: this.config
}
this.cli.api.variant.deployment.create(params, cb);
}
destroy(event) {
this.cli.log.info('Ending polling of variant');
this.end = true;
clearInterval(this.pollInterval);
if (event.data.error) {
this.emit('error', event.data.error);
}
}
}
module.exports = Variant;