var EventEmitter = require('events').EventEmitter,
util = require('util');
/**
* An observer that watches one or more circuit breakers. It will
* group their 'interval' event by name, and emit a single 'batch'
* event with their combined data.
*
* @fires CBObserver#batch
*
* @constructor
*/
function CBObserver() {
var EVENT = 'interval',
watched = [],
listeners = [],
intervals = {},
self = this;
/**
* Watch a circuit breaker
*
* @param {CircuitBreaker} cb - The circuit breaker on which we'll listen the 'interval' event.
*/
this.watch = function(cb) {
if (watched.indexOf(cb) > -1) {
return;
}
watched.push(cb);
var name = cb.getName();
if (!(name in intervals)) {
intervals[name] = [];
}
var listener = buildOnInterval(name);
listeners.push(listener);
cb.on(EVENT, listener);
};
/**
* Stop watching this circuit breaker
*
* @param {CircuitBreaker} cb
*/
this.unwatch = function(cb) {
var index = watched.indexOf(cb);
if (index > -1) {
watched.splice(index, 1);
var arr = listeners.splice(index, 1);
cb.removeListener(EVENT, arr[0]);
}
};
function buildOnInterval(cb) {
return function(interval) {
intervals[cb].push(interval);
emitIfNecessary();
};
}
function emitIfNecessary() {
for (var name in intervals) {
var cnt = intervals[name].length;
if (cnt > 1) {
doEmit();
return;
} else if (cnt === 0) {
return false;
}
}
doEmit();
}
function doEmit() {
var data = intervals;
intervals = {};
for (var name in data) {
intervals[name] = [];
}
/**
* Batch event. The keys of the object are the names of the circuit breakers.
* The values of the object are arrays of {@link CircuitBreaker#event:interval}.
*
* @event CBObserver#batch
* @type object
*/
self.emit('batch', data);
}
}
util.inherits(CBObserver, EventEmitter);
module.exports = CBObserver;