Skip to content

Commit

Permalink
working version
Browse files Browse the repository at this point in the history
  • Loading branch information
asyncanup committed Jan 20, 2018
1 parent 1bf4a99 commit 42b7481
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 3 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
npm-debug.log
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ Service Discoverer node module

## Use

VASCO_HOST=localhost VASCO_PORT=6379 VASCO_PASS=redispassword \
node app.js
VASCO_URL=127.0.0.1:6379 node app.js

If not supplied, `VASCO_URL` gets the default value `127.0.0.1:6379`.

Inside `app.js`,

Expand All @@ -22,7 +23,7 @@ Inside `app.js`,
return;
}
// deps is a hash of dependency names (as defined in package.json)
// with active urls ensure to be active
// with active urls
console.log(deps);
});

26 changes: 26 additions & 0 deletions examples/service/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
var pick = require('object-pick');
var vasco = require('../..');
var ip = require('ip').address();
var log = require('debug')('example:service');
var app = require('express')();

app.get('/', function (req, res) {
res.json({ ping: 'PONG' });
});

app.listen(function() {
var port = this.address().port;
var address = ip + ':' + port;
var pkg = require('./package');
log('address', address);

vasco.register(address, pkg, function (err, depUrls) {
if (err) {
console.error('Could not register self as service');
throw err;
}
log('depUrls', depUrls);
app.set('depUrls', depUrls);
log('started!');
});
});
18 changes: 18 additions & 0 deletions examples/service/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "service",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "DEBUG=* node index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"dependencies": {
"debug": "^2.2.0",
"express": "^4.13.4",
"ip": "^1.1.0",
"object-pick": "^0.1.2"
}
}
39 changes: 39 additions & 0 deletions examples/user/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
var vasco = require('../..');
var request = require('request');
var log = require('debug')('example:user');
var ip = require('ip').address();
var app = require('express')();

app.get('/', function (req, res) {
var depUrls = app.get('depUrls');
if (!depUrls || !depUrls.service) {
return res.status(500).send('Service dependencies not available yet');
}
log('deps.service', depUrls.service);
var url = 'http://' + depUrls.service;
request.get({ url: url, json: true }, function (err, response, body) {
if (err) { return res.status(500).send(err.message); }
if (response.statusCode !== 200) {
return res.status(response.statusCode).send(body);
}
log('body', body);
if (body.ping !== 'PONG') {
return res.status(404).send('Incorrect response from service: ' + body);
}
res.send('success!');
});
});

app.listen(process.env.SERVICE_PORT, function () {
var address = ip + ':' + this.address().port;
var pkg = require('./package');
log('address', address);
vasco.register(address, pkg, function (err, depUrls) {
if (err) {
console.error('Could not register with vasco');
throw err;
}
log('depUrls', depUrls);
app.set('depUrls', depUrls);
});
});
26 changes: 26 additions & 0 deletions examples/user/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "user",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "DEBUG=* node index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"dependencies": {
"debug": "^2.2.0",
"express": "^4.13.4",
"ip": "^1.1.0",
"request": "^2.69.0"
},
"vasco": {
"dependencies": {
"service": "1.0.0",
"auth": "1.0.0"
},
"mocks": {
"auth": "localhost:3000"
}
}
}
93 changes: 93 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
const redis = global.redis || require('redis');
const log = require('debug')('vasco');

let db;
function connectDB() {
db = redis.createClient(process.env.VASCO_URL);
db.on('error', err => { throw err; });
}

function findDependencies(dependencies, mockDeps, done) {
const depUrls = {};
const depNames = Object.keys(dependencies);
const depKeys = depNames.map(depName => depName + '@' + dependencies[depName]);
log('depKeys', depKeys);

let total = depKeys.length;
if (!total) { return done(null, {}); }

depNames.forEach((depName, index) => {
if (mockDeps[depName]) { return gotMockDepUrl(depName, mockDeps[depName]); }
const key = depKeys[index];
const dbKey = 'endpoints.' + key;
db.srandmember(dbKey, gotDepUrl(depName, key, dbKey));
});

function gotDepUrl(depName, key, dbKey) {
return (err, url) => {
if (err) { return done(err); }
if (!url) { return done(new Error('No service found for ' + key)); }
log('url for dep', key, url);

db.get('alive.' + url, (err, alive) => {
if (err) { return done(err); }
log('url alive:', url, alive);
if (!alive) {
return db.srem(dbKey, url, err => {
if (err) { return done(err); }
db.srandmember(dbKey, gotDepUrl(key, dbKey));
});
}
log('url for alive dep', key, url);
depUrls[depName] = url;
total -= 1;
if (!total) { return done(null, depUrls); }
});
};
}
function gotMockDepUrl(depName, url) {
if (!url) { return done(new Error('No mock service found for', depName)); }
depUrls[depName] = url;
total -= 1;
if (!total) { return done(null, depUrls); }
}
}

function register(url, pkg, done) {
if (!url) { return done(new Error('Need url of service')); }
if (!pkg || !pkg.name || !pkg.version) { return done(new Error('Invalid package')); }
const opts = pkg.vasco || {};
const aliveDuration = opts.aliveDuration || 10; // seconds

connectDB();
findDependencies(opts.dependencies || {}, opts.mocks || {}, (err, depUrls) => {
if (err) { return done(err); }
const name = pkg.name + '@' + pkg.version;
db.sadd('endpoints.' + name, url, err => {
if (err) { return done(err); }
db.end(true);
pingHealth(url, err => {
if (err) { return done(err); }
setInterval(pingHealth, aliveDuration * 1000, url);
done(null, depUrls);
});
});
});

function pingHealth(url, callback) {
const key = 'alive.' + url;
callback = callback || (err => { if (err) throw err; });

connectDB();
db.set(key, true, err => {
if (err) { return callback(err); }
db.expire(key, aliveDuration, err => {
callback(err);
db.end(true);
});
});
}
}

module.exports = { findDependencies, register };

14 changes: 14 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "vasco",
"version": "1.0.0",
"description": "The Great Service Discoverer",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Anup Bishnoi <[email protected]>",
"dependencies": {
"debug": "^2.2.0",
"redis": "^2.4.2"
}
}

0 comments on commit 42b7481

Please sign in to comment.