UNPKG

briareus

Version:

Briareus assists with Feature Branch deploys to ECS

153 lines (125 loc) 3.81 kB
'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;