Merge pull request #108 from maraoz/feature/realtime-sync-info

Feature/realtime sync info
This commit is contained in:
Manuel Aráoz 2014-01-21 08:31:42 -08:00
commit 590acff915
5 changed files with 227 additions and 207 deletions

View File

@ -27,5 +27,5 @@ module.exports.broadcast_address_tx = function(address, tx) {
}; };
module.exports.broadcastSyncInfo = function(syncInfo) { module.exports.broadcastSyncInfo = function(syncInfo) {
ios.sockets.emit('sync', syncInfo); ios.sockets.in('sync').emit('status', syncInfo);
}; };

View File

@ -2,7 +2,6 @@
require('classtool'); require('classtool');
function spec() { function spec() {
var util = require('util'); var util = require('util');
var RpcClient = require('bitcore/RpcClient').class(); var RpcClient = require('bitcore/RpcClient').class();
@ -21,7 +20,6 @@ function spec() {
this.genesis = genesisHashReversed.reverse().toString('hex'); this.genesis = genesisHashReversed.reverse().toString('hex');
this.sync = new Sync(opts); this.sync = new Sync(opts);
//available status: new / syncing / finished / aborted //available status: new / syncing / finished / aborted
this.status = 'new'; this.status = 'new';
this.syncInfo = {}; this.syncInfo = {};
@ -31,8 +29,6 @@ function spec() {
var args = []; var args = [];
Array.prototype.push.apply(args, arguments); Array.prototype.push.apply(args, arguments);
args.unshift('[historic_sync]'); args.unshift('[historic_sync]');
/*jshint validthis:true */ /*jshint validthis:true */
console.log.apply(this, args); console.log.apply(this, args);
@ -48,36 +44,40 @@ function spec() {
this.sync.close(); this.sync.close();
}; };
HistoricSync.prototype.showProgress = function() { HistoricSync.prototype.showProgress = function() {
var self = this; var self = this;
var i = self.syncInfo; var i = self.syncInfo;
var per = parseInt(100 * i.syncedBlocks / i.blocksToSync); var per = parseInt(100 * i.syncedBlocks / i.blocksToSync);
p(util.format('status: %d/%d [%d%%]', i.syncedBlocks, i.blocksToSync, per)); p(util.format('status: %d/%d [%d%%]', i.syncedBlocks, i.blocksToSync, per));
if (self.opts.broadcast) { if (self.opts.shouldBroadcast) {
sockets.broadcastSyncInfo(self.syncInfo); sockets.broadcastSyncInfo(self.syncInfo);
} }
}; };
HistoricSync.prototype.getPrevNextBlock = function(blockHash, blockEnd, opts, cb) { HistoricSync.prototype.getPrevNextBlock = function(blockHash, blockEnd, opts, cb) {
var self = this; var self = this;
// recursion end. // recursion end.
if (!blockHash) return cb(); if (!blockHash) return cb();
var existed = 0; var existed = false;
var blockInfo; var blockInfo;
var blockObj; var blockObj;
async.series([ async.series([
// Already got it? // Already got it?
function(c) { function(c) {
Block.findOne({hash:blockHash}, function(err,block){ Block.findOne({
if (err) { p(err); return c(err); } hash: blockHash
},
function(err, block) {
if (err) {
p(err);
return c(err);
}
if (block) { if (block) {
existed =1; existed = true;
blockObj = block; blockObj = block;
} }
return c(); return c();
@ -85,10 +85,15 @@ function spec() {
}, },
//show some (inacurate) status //show some (inacurate) status
function(c) { function(c) {
if (!self.step) {
var step = parseInt(self.syncInfo.blocksToSync / 100); var step = parseInt(self.syncInfo.blocksToSync / 100);
if (step < 10) step = 10; if (self.opts.progressStep) {
step = self.opts.progressStep;
if (self.syncInfo.syncedBlocks % step === 1) { }
if (step < 2) step = 2;
self.step = step;
}
if (self.syncInfo.syncedBlocks % self.step === 1) {
self.showProgress(); self.showProgress();
} }
return c(); return c();
@ -98,7 +103,6 @@ function spec() {
// TODO: if we store prev/next, no need to go to RPC // TODO: if we store prev/next, no need to go to RPC
// if (blockObj && blockObj.nextBlockHash) return c(); // if (blockObj && blockObj.nextBlockHash) return c();
self.rpc.getBlock(blockHash, function(err, ret) { self.rpc.getBlock(blockHash, function(err, ret) {
if (err) return c(err); if (err) return c(err);
@ -127,8 +131,7 @@ function spec() {
return c(); return c();
} }
*/ */
], ], function(err) {
function (err){
if (err) { if (err) {
self.err = util.format('ERROR: @%s: %s [count: syncedBlocks: %d]', blockHash, err, self.syncInfo.syncedBlocks); self.err = util.format('ERROR: @%s: %s [count: syncedBlocks: %d]', blockHash, err, self.syncInfo.syncedBlocks);
@ -162,7 +165,6 @@ function spec() {
return cb(err); return cb(err);
} }
// Continue // Continue
if (blockInfo && blockInfo.result) { if (blockInfo && blockInfo.result) {
if (!existed) self.syncInfo.syncedBlocks++; if (!existed) self.syncInfo.syncedBlocks++;
@ -170,8 +172,7 @@ function spec() {
return self.getPrevNextBlock(blockInfo.result.previousblockhash, blockEnd, opts, cb); return self.getPrevNextBlock(blockInfo.result.previousblockhash, blockEnd, opts, cb);
} }
if (opts.next && blockInfo.result.nextblockhash) if (opts.next && blockInfo.result.nextblockhash) return self.getPrevNextBlock(blockInfo.result.nextblockhash, blockEnd, opts, cb);
return self.getPrevNextBlock(blockInfo.result.nextblockhash, blockEnd, opts, cb);
} }
return cb(err); return cb(err);
}); });
@ -225,7 +226,10 @@ function spec() {
} }
else { else {
// should be isOrphan = true or null to be more accurate. // should be isOrphan = true or null to be more accurate.
Block.count({ isOrphan: null}, function(err, count) { Block.count({
isOrphan: null
},
function(err, count) {
if (err) return cb(err); if (err) return cb(err);
self.syncInfo.blocksToSync = blockChainHeight - count; self.syncInfo.blocksToSync = blockChainHeight - count;
@ -234,9 +238,7 @@ function spec() {
}); });
} }
}, },
], ], function(err) {
function(err) {
var start, end; var start, end;
function sync() { function sync() {
@ -271,15 +273,17 @@ function spec() {
setTimeout(function() { setTimeout(function() {
p('Retrying in %d secs', retry_secs); p('Retrying in %d secs', retry_secs);
sync(); sync();
}, retry_secs * 1000); },
retry_secs * 1000);
} }
else else return next(err);
return next(err);
}); });
} }
if (err) { if (err) {
self.syncInfo = util._extend(self.syncInfo, { error: err.message }); self.syncInfo = util._extend(self.syncInfo, {
error: err.message
});
return next(err, 0); return next(err, 0);
} }
else { else {
@ -292,11 +296,13 @@ function spec() {
HistoricSync.prototype.smart_import = function(next) { HistoricSync.prototype.smart_import = function(next) {
var self = this; var self = this;
Block.findOne({hash:self.genesis}, function(err, b){ Block.findOne({
hash: self.genesis
},
function(err, b) {
if (err) return next(err); if (err) return next(err);
if (!b) { if (!b) {
p('Could not find Genesis block. Running FULL SYNC'); p('Could not find Genesis block. Running FULL SYNC');
} }
@ -305,7 +311,7 @@ function spec() {
} }
var opts = { var opts = {
reverse: 1, reverse: true,
upToExisting: b ? true: false, upToExisting: b ? true: false,
}; };
@ -313,7 +319,6 @@ function spec() {
}); });
}; };
return HistoricSync; return HistoricSync;
} }
module.defineClass(spec); module.defineClass(spec);

View File

@ -1,16 +1,18 @@
'use strict'; 'use strict';
angular.module('insight.status').controller('StatusController', angular.module('insight.status').controller('StatusController',
function ($scope, $routeParams, $location, $rootScope, Global, Status, Sync) { function($scope, $routeParams, $location, $rootScope, Global, Status, Sync, get_socket) {
$scope.global = Global; $scope.global = Global;
$scope.getStatus = function(q) { $scope.getStatus = function(q) {
Status.get({ Status.get({
q: 'get' + q q: 'get' + q
}, function(d) { },
function(d) {
$rootScope.infoError = null; $rootScope.infoError = null;
angular.extend($scope, d); angular.extend($scope, d);
}, function(e) { },
function(e) {
if (e.status === 503) { if (e.status === 503) {
$rootScope.infoError = 'Backend Error. ' + e.data; $rootScope.infoError = 'Backend Error. ' + e.data;
} }
@ -20,24 +22,36 @@ angular.module('insight.status').controller('StatusController',
}); });
}; };
$scope.getSync = function() { var on_sync_update = function(sync) {
Sync.get({}, function(sync) {
$rootScope.syncError = null;
if (sync.blocksToSync > sync.syncedBlocks) { if (sync.blocksToSync > sync.syncedBlocks) {
sync.message = 'Blocks to sync: ' + (sync.blocksToSync - sync.syncedBlocks); var p = parseInt(100*(sync.syncedBlocks) / sync.blocksToSync);
sync.tooltip = 'Skipped blocks:' + sync.skipped_blocks; var delta = sync.blocksToSync - sync.syncedBlocks;
} sync.message = 'Sync ' + p + '% ['+delta+' blocks remaining]';
else { sync.style = 'warn';
} else {
sync.message = 'On sync'; sync.message = 'On sync';
sync.tooltip = ''; sync.style = 'success';
} }
sync.tooltip = 'Synced blocks: '+sync.syncedBlocks;
$scope.sync = sync; $scope.sync = sync;
}, function(e) { };
$scope.getSync = function() {
Sync.get({},
function(sync) {
$rootScope.syncError = null;
on_sync_update(sync);
},
function(e) {
$rootScope.syncError = 'Could not get sync information' + e; $rootScope.syncError = 'Could not get sync information' + e;
}); });
}; };
var socket = get_socket($scope);
socket.emit('subscribe', 'sync');
socket.on('status', function(sync) {
on_sync_update(sync);
});
}); });

View File

@ -26,7 +26,7 @@
<div class="status" data-ng-controller="StatusController"> <div class="status" data-ng-controller="StatusController">
<span data-ng-init="getSync()"> <span data-ng-init="getSync()">
<span class="small" tooltip="{{sync.tooltip}}" tooltip-placement="down"> <span class="small" tooltip="{{sync.tooltip}}" tooltip-placement="down">
<i><strong> {{sync.message}} </strong></i> <i class="{{sync.style}}"><strong> {{sync.message}} </strong></i>
</span> </span>
</span> </span>
<span data-ng-init="getStatus('Info')"> <span data-ng-init="getStatus('Info')">

View File

@ -60,6 +60,7 @@ if (!config.disableHistoricSync) {
historicSync.init({ historicSync.init({
skipDbConnection: true, skipDbConnection: true,
shouldBroadcast: true, shouldBroadcast: true,
progressStep: 2,
networkName: config.network networkName: config.network
}, function() { }, function() {
historicSync.smart_import(function(err){ historicSync.smart_import(function(err){