tribune
Version:
Holy advocate to the Roman Senate, your Tribune will ensure the Consuls have your interests in mind.
90 lines (74 loc) • 2.35 kB
JavaScript
const httpMethods = require('http').METHODS;
const Endpoint = require('./endpoint');
class Service {
constructor(tribune, name) {
this._tribune = tribune;
this._name = name;
this._endpoint = null;
this._endpointTags = null;
this._endpointUrl = null;
this._connectTimeoutId = null;
this._requests = [];
}
request(url, opts, cb = () => {}) {
if (url && typeof url === 'object') {
cb = opts;
opts = url;
url = undefined;
}
if (typeof opts === 'function') {
cb = opts;
opts = {};
}
let attempts = 0;
const makeRequest = () => {
this.endpoint((err, endpoint) => {
if (err) { return cb(err); }
opts.baseUrl = endpoint.url;
this._tribune._consul._request(url, opts, (err, res) => {
if (!err || err && err.code !== 'ENOTFOUND') {
return cb(err, res);
}
attempts += 1;
if (attempts > 10) { return cb(err, res); }
return makeRequest();
});
});
};
makeRequest();
}
endpoint(cb = () => {}) {
if (this._endpoint) { return cb(null, this._endpoint); }
const timeout = this._tribune._serviceTimeout;
if (timeout > 0) {
clearTimeout(this._connectTimeoutId);
this._connectTimeoutId = setTimeout(() => {
throw new Error(`Could not aquire connection to ${this._name} service`);
}, timeout);
}
this._tribune._getConsulServiceEndpoint(this._name, (err, serviceEndpoint) => {
if (err || serviceEndpoint) { clearTimeout(this._connectTimeoutId); }
if (err) { return cb(err); }
if (!serviceEndpoint) { return setTimeout(() => this.endpoint(cb), 300); }
this._endpoint = new Endpoint(serviceEndpoint);
setTimeout(() => { this._endpoint = null; }, this._tribune._serviceTtl).unref();
cb(null, this._endpoint);
});
}
}
httpMethods.forEach((method) => {
Service.prototype[method.toLowerCase()] = function(url, opts, cb) {
if (url && typeof url === 'object') {
cb = opts;
opts = url;
url = undefined;
}
if (typeof opts === 'function') {
cb = opts;
opts = {};
}
opts.method = method;
return this.request(url, opts, cb);
};
});
module.exports = Service;