-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathindex.js
96 lines (80 loc) · 3.04 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
var EndpointPool;
var _ = require('underscore');
var dns = require('dns');
var Events = require('events');
var PoolManager = require('./pool-manager');
var util = require('util');
var DNS_LOOKUP_TIMEOUT = 1000;
/**
* @param {String} discoveryName The name of the service discovery host
* @param {Number} ttl How long the endpoints are valid for. The service discovery endpoint will be checked on
* this interval.
* @param {{maxFailures: Number, failureWindow: Number, resetTimeout: Number}}
* ejectOnErrorConfig How to handle endpoint errors. If specified, the following options must be defined:
* - maxFailures: Number of failures allowed before the endpoint circuit breaker is tripped.
* - failureWindow: Size of the sliding window of time in which the failures are counted.
* - resetTimeout: Amount of time before putting the circuit back into half open state.
* @param {Function=} onReady Callback to execute when endpoints have been primed (updated for the first time)
*/
module.exports = EndpointPool = function (discoveryName, ttl, ejectOnErrorConfig, onReady) {
if (!discoveryName || !ttl) {
throw new Error('Must supply all arguments');
}
if (ejectOnErrorConfig) {
this.poolManager = PoolManager.ejectOnErrorPoolManager(ejectOnErrorConfig);
} else {
this.poolManager = PoolManager.defaultPoolManager();
}
Events.EventEmitter.call(this);
this.discoveryName = discoveryName;
this.ttl = ttl;
this._updateTimeout = null;
this.lastUpdate = Date.now();
this.update(onReady);
};
util.inherits(EndpointPool, Events.EventEmitter);
_.extend(EndpointPool.prototype, {
update: function (onDone) {
this.resolve(function (err, endpoints) {
if (err || !endpoints || !endpoints.length) {
this.emit('updateError', err, Date.now() - this.lastUpdate);
} else {
this.lastUpdate = Date.now();
this.setEndpoints(endpoints);
}
this._updateTimeout = setTimeout(this.update.bind(this), this.ttl);
if (typeof onDone === 'function') {
onDone();
}
}.bind(this));
},
resolve: function (cb) {
var callback = _.once(cb);
setTimeout(callback, DNS_LOOKUP_TIMEOUT, dns.TIMEOUT);
dns.resolveSrv(this.discoveryName, callback);
},
getEndpoint: function () {
var endpoint = this.poolManager.getNextEndpoint();
if (endpoint) {
return endpoint;
} else {
this.emit('noEndpoints');
return null;
}
},
hasEndpoints: function () {
return this.poolManager.hasEndpoints();
},
setEndpoints: function (endpoints) {
this.poolManager.updateEndpoints(endpoints);
},
getStatus: function () {
var poolStatus = this.poolManager.getStatus();
return _.assign({
age: Date.now() - this.lastUpdate
}, poolStatus);
},
stopUpdating: function () {
clearTimeout(this._updateTimeout);
}
});