ethstats-server/models/node.js
2015-06-02 00:04:34 +03:00

286 lines
4.8 KiB
JavaScript

var geoip = require('geoip-lite');
var _ = require('lodash');
var MAX_HISTORY = 40;
var MAX_INACTIVE_TIME = 1000*60*60*4;
var Node = function Node(data)
{
this.id = null;
this.info = {};
this.geo = {}
this.stats = {
active: false,
mining: false,
hashrate: 0,
peers: 0,
pending: 0,
gasPrice: 0,
block: {
difficulty: 0,
number: 0,
gasLimit: 0,
timestamp: 0,
time: 0,
arrival: 0,
propagation: 0,
received: 0,
transactions: [],
uncles: []
},
propagationAvg: 0,
latency: 0,
uptime: 0,
lastUpdate: 0
};
this.history = new Array(MAX_HISTORY);
this.uptime = {
started: null,
history: []
};
this.init(data);
return this;
}
Node.prototype.init = function(data)
{
_.fill(this.history, -1);
if( this.id === null )
{
this.uptime.started = _.now();
this.setState(true);
}
if( !_.isUndefined(data.id) )
this.id = data.id;
this.setInfo(data);
if( !_.isUndefined(data.latency) )
this.stats.latency = data.latency;
return this;
}
Node.prototype.setInfo = function(data)
{
if( !_.isUndefined(data.info) )
{
this.info = data.info;
if( _.isUndefined(data.info.canUpdateHistory) )
data.info.canUpdateHistory = false;
}
if( !_.isUndefined(data.ip) )
{
if(data.ip === '::ffff:127.0.0.1')
data.ip = '84.117.82.122';
this.info.ip = data.ip;
this.setGeo();
}
if( !_.isUndefined(data.spark) )
this.spark = data.spark;
var uptimeCnt = this.uptime.history.length;
if( uptimeCnt > 0 && this.uptime.history[uptimeCnt - 1].status === 'down' )
this.setState(true);
return this;
}
Node.prototype.setGeo = function()
{
this.geo = geoip.lookup(this.info.ip);
return this;
}
Node.prototype.getInfo = function()
{
return {
id: this.id,
info: this.info,
geo: this.geo,
stats: this.stats,
history: this.history
};
}
Node.prototype.setStats = function(stats, history)
{
if( !_.isUndefined(stats) && !_.isUndefined(stats.block) && !_.isUndefined(stats.block.number) )
{
this.history = history;
var positives = _.filter(history, function(p) {
return p >= 0;
});
if(positives.length > 0)
stats.propagationAvg = Math.round( _.sum(positives) / positives.length );
else
stats.propagationAvg = 0;
if( !_.isUndefined(this.stats.latency) )
stats.latency = this.stats.latency;
this.stats = stats;
return this.getStats();
}
return false;
}
Node.prototype.setBlock = function(block, history)
{
if( !_.isUndefined(block) && !_.isUndefined(block.number) )
{
this.history = history;
var propagationAvg = 0;
var positives = _.filter(history, function(p) {
return p >= 0;
});
if(positives.length > 0)
propagationAvg = Math.round( _.sum(positives) / positives.length );
else
propagationAvg = 0;
this.stats.block = block;
this.stats.propagationAvg = propagationAvg;
return this.getBlockStats();
}
return false;
}
Node.prototype.setPending = function(stats)
{
if( !_.isUndefined(stats) && !_.isUndefined(stats.pending) )
{
this.stats.pending = stats.pending;
return {
id: this.id,
pending: this.stats.pending
};
}
return false;
}
Node.prototype.setBasicStats = function(stats)
{
if( !_.isUndefined(stats) )
{
this.stats.active = stats.active;
this.stats.mining = stats.mining;
this.stats.hashrate = stats.hashrate;
this.stats.peers = stats.peers;
this.stats.gasPrice = stats.gasPrice;
this.stats.uptime = stats.uptime;
return this.getBasicStats();
}
return false;
}
Node.prototype.setLatency = function(latency)
{
if( !_.isUndefined(latency) )
{
this.stats.latency = latency;
return {
id: this.id,
latency: latency
};
}
return false;
}
Node.prototype.getStats = function()
{
return {
id: this.id,
stats: this.stats,
history: this.history
};
}
Node.prototype.getBlockStats = function()
{
return {
id: this.id,
block: this.stats.block,
propagationAvg: this.stats.propagationAvg,
history: this.history
};
}
Node.prototype.getBasicStats = function()
{
return {
id: this.id,
stats: {
active: this.stats.active,
mining: this.stats.mining,
hashrate: this.stats.hashrate,
peers: this.stats.peers,
gasPrice: this.stats.gasPrice,
uptime: this.stats.uptime
}
};
}
Node.prototype.setState = function(active)
{
this.stats.active = active;
this.uptime.history.push({
status: (active ? 'up' : 'down'),
time: _.now()
});
}
Node.prototype.getBlockNumber = function()
{
return this.stats.block.number;
}
Node.prototype.canUpdate = function()
{
return this.info.canUpdateHistory || false;
}
Node.prototype.isInactiveAndOld = function()
{
if(this.stats.active)
return false;
var lastState = this.uptime.history[this.uptime.history.length -1];
if( !_.isUndefined(lastState) && !_.isUndefined(lastState.status) && !_.isUndefined(lastState.time) )
{
if( lastState.status === 'down' && (_.now() - lastState.time) > MAX_INACTIVE_TIME )
return true;
}
return false;
}
module.exports = Node;