Fixed progress bar and added tests for getTransaction in
TransactionService.
This commit is contained in:
parent
6d95cd0302
commit
b6f56fb02b
@ -320,7 +320,7 @@ DB.prototype.loadTips = function(callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self[tip] = block;
|
self[tip] = block;
|
||||||
log.info('loaded tip, hash: ' + block.hash + ' height: ' + block.__height);
|
log.info('loaded ' + tip + ', hash: ' + block.hash + ' height: ' + block.__height);
|
||||||
next();
|
next();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -7,7 +7,6 @@ var EventEmitter = require('events').EventEmitter;
|
|||||||
var async = require('async');
|
var async = require('async');
|
||||||
var bitcore = require('bitcore-lib');
|
var bitcore = require('bitcore-lib');
|
||||||
var Block = bitcore.Block;
|
var Block = bitcore.Block;
|
||||||
var ProgressBar = require('progress');
|
|
||||||
var index = require('../../index');
|
var index = require('../../index');
|
||||||
var log = index.log;
|
var log = index.log;
|
||||||
|
|
||||||
@ -66,8 +65,7 @@ function Sync(node, db) {
|
|||||||
this.syncing = false;
|
this.syncing = false;
|
||||||
this.paused = false; //we can't sync while one of our indexes is reading/writing separate from us
|
this.paused = false; //we can't sync while one of our indexes is reading/writing separate from us
|
||||||
this.highWaterMark = 10;
|
this.highWaterMark = 10;
|
||||||
this.progressBar = null;
|
this._lastReportedTime = Date.now();
|
||||||
this.lastReportedBlock = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inherits(Sync, EventEmitter);
|
inherits(Sync, EventEmitter);
|
||||||
@ -98,16 +96,6 @@ Sync.prototype.sync = function() {
|
|||||||
blockStream
|
blockStream
|
||||||
.pipe(processSerial);
|
.pipe(processSerial);
|
||||||
|
|
||||||
self.lastReportedBlock = self.db.tip.__height;
|
|
||||||
|
|
||||||
self.progressBar = new ProgressBar('[:bar] :percent :current blks, :blockspersec blks/sec', {
|
|
||||||
curr: self.lastReportedBlock,
|
|
||||||
total: self.node.services.bitcoind.height,
|
|
||||||
clear: true
|
|
||||||
});
|
|
||||||
|
|
||||||
self.progressBarTimer = setInterval(self.reportStatus.bind(self), 1000);
|
|
||||||
|
|
||||||
processSerial.on('finish', self._onFinish.bind(self));
|
processSerial.on('finish', self._onFinish.bind(self));
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -117,14 +105,6 @@ Sync.prototype._onFinish = function() {
|
|||||||
var self = this;
|
var self = this;
|
||||||
self.syncing = false;
|
self.syncing = false;
|
||||||
|
|
||||||
if (self.progressBar) {
|
|
||||||
self.progressBar.terminate();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.progressBarTimer) {
|
|
||||||
clearInterval(self.progressBarTimer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.forkBlock) {
|
if (self.forkBlock) {
|
||||||
self.db.handleReorg(self.forkBlock, function() {
|
self.db.handleReorg(self.forkBlock, function() {
|
||||||
self.forkBlock = null;
|
self.forkBlock = null;
|
||||||
@ -134,6 +114,7 @@ Sync.prototype._onFinish = function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self._startSubscriptions();
|
self._startSubscriptions();
|
||||||
|
self._reportStatus(true);
|
||||||
self.emit('synced');
|
self.emit('synced');
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -148,6 +129,7 @@ Sync.prototype._startSubscriptions = function() {
|
|||||||
self.bus = self.node.openBus({remoteAddress: 'localhost'});
|
self.bus = self.node.openBus({remoteAddress: 'localhost'});
|
||||||
|
|
||||||
self.bus.on('bitcoind/hashblock', function() {
|
self.bus.on('bitcoind/hashblock', function() {
|
||||||
|
self._reportStatus();
|
||||||
self.sync();
|
self.sync();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -156,12 +138,9 @@ Sync.prototype._startSubscriptions = function() {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Sync.prototype.reportStatus = function() {
|
Sync.prototype._reportStatus = function(override) {
|
||||||
if (process.stderr.isTTY) {
|
if (((Date.now() - this._lastReportedTime) > 1000) || override) {
|
||||||
var tick = this.db.tip.__height - this.lastReportedBlock;
|
this._lastReportedTime = Date.now();
|
||||||
this.progressBar.tick(tick, { blockspersec: tick });
|
|
||||||
this.lastReportedBlock = this.db.tip.__height;
|
|
||||||
} else {
|
|
||||||
log.info('Sync: current height is: ' + this.db.tip.__height);
|
log.info('Sync: current height is: ' + this.db.tip.__height);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -160,6 +160,7 @@ TransactionService.prototype.getTransaction = function(txid, options, callback)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
txid = txid.toString('hex');
|
||||||
var key = self.encoding.encodeTransactionKey(txid);
|
var key = self.encoding.encodeTransactionKey(txid);
|
||||||
|
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
@ -178,22 +179,16 @@ TransactionService.prototype.getTransaction = function(txid, options, callback)
|
|||||||
return next(null, tx);
|
return next(null, tx);
|
||||||
}
|
}
|
||||||
if (!options || !options.queryMempool) {
|
if (!options || !options.queryMempool) {
|
||||||
return next();
|
return next(new Error('Transaction: ' + txid + ' not found in index'));
|
||||||
}
|
}
|
||||||
self.node.services.mempool.getTransaction(txid, function(err, tx) {
|
self.node.services.mempool.getTransaction(txid, function(err, tx) {
|
||||||
if(err) {
|
if (err instanceof levelup.errors.NotFoundError) {
|
||||||
return next(err);
|
return callback(new Error('Transaction: ' + txid + ' not found in index or mempool'));
|
||||||
}
|
} else if (err) {
|
||||||
if (!tx) {
|
return callback(err);
|
||||||
return next();
|
}
|
||||||
}
|
self._getMissingInputValues(tx, next);
|
||||||
self._getMissingInputValues(tx, next);
|
|
||||||
});
|
});
|
||||||
}, function(tx, next) {
|
|
||||||
if (tx) {
|
|
||||||
return next(null, tx);
|
|
||||||
}
|
|
||||||
self.node.services.bitcoind.getTransaction(txid, next);
|
|
||||||
}], callback);
|
}], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -60,7 +60,6 @@
|
|||||||
"mkdirp": "0.5.0",
|
"mkdirp": "0.5.0",
|
||||||
"multer": "^1.2.1",
|
"multer": "^1.2.1",
|
||||||
"path-is-absolute": "^1.0.0",
|
"path-is-absolute": "^1.0.0",
|
||||||
"progress": "kleetus/node-progress#master",
|
|
||||||
"semver": "^5.0.1",
|
"semver": "^5.0.1",
|
||||||
"socket.io": "^1.4.5",
|
"socket.io": "^1.4.5",
|
||||||
"socket.io-client": "^1.4.5",
|
"socket.io-client": "^1.4.5",
|
||||||
|
|||||||
@ -8,7 +8,7 @@ var path = require('path');
|
|||||||
var utils = require('./utils');
|
var utils = require('./utils');
|
||||||
var crypto = require('crypto');
|
var crypto = require('crypto');
|
||||||
|
|
||||||
var debug = false;
|
var debug = true;
|
||||||
var bitcoreDataDir = '/tmp/bitcore';
|
var bitcoreDataDir = '/tmp/bitcore';
|
||||||
var bitcoinDataDir = '/tmp/bitcoin';
|
var bitcoinDataDir = '/tmp/bitcoin';
|
||||||
|
|
||||||
|
|||||||
114
test/services/transaction/index.unit.js
Normal file
114
test/services/transaction/index.unit.js
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var should = require('chai').should();
|
||||||
|
var sinon = require('sinon');
|
||||||
|
var TransactionService = require('../../../lib/services/transaction');
|
||||||
|
var levelup = require('levelup');
|
||||||
|
|
||||||
|
describe('Transaction Index', function() {
|
||||||
|
|
||||||
|
describe('Failures', function() {
|
||||||
|
//if we miss indexing a tx, then this is very bad news. We have no good way of
|
||||||
|
//recursively retrieving inputValues, timestamp of its block, and block's height
|
||||||
|
it('should throw error if a transaction is not in the index', function(done) {
|
||||||
|
var services = {
|
||||||
|
db: {
|
||||||
|
store: {
|
||||||
|
get: sinon.stub().callsArgWith(1, new levelup.errors.NotFoundError())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var node = { node: { services: services }};
|
||||||
|
var service = new TransactionService(node);
|
||||||
|
|
||||||
|
service.encoding = { encodeTransactionKey: function() { return 'key'; }};
|
||||||
|
var tx = service.getTransaction('1234', {}, function(err, res) {
|
||||||
|
err.should.be.an.instanceof(Error);
|
||||||
|
err.message.should.equal('Transaction: 1234 not found in index');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should search the mempool if opted for', function(done) {
|
||||||
|
var getTransaction = sinon.stub().callsArgWith(1, new levelup.errors.NotFoundError());
|
||||||
|
var services = {
|
||||||
|
db: {
|
||||||
|
store: {
|
||||||
|
get: sinon.stub().callsArgWith(1, new levelup.errors.NotFoundError())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mempool: {
|
||||||
|
getTransaction: getTransaction
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var node = { node: { services: services }};
|
||||||
|
var service = new TransactionService(node);
|
||||||
|
|
||||||
|
service.encoding = { encodeTransactionKey: function() { return 'key'; }};
|
||||||
|
var tx = service.getTransaction('1234', { queryMempool: true }, function(err, res) {
|
||||||
|
err.should.be.an.instanceof(Error);
|
||||||
|
err.message.should.equal('Transaction: 1234 not found in index or mempool');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Success', function() {
|
||||||
|
it('should search main index', function(done) {
|
||||||
|
var services = {
|
||||||
|
db: {
|
||||||
|
store: {
|
||||||
|
get: sinon.stub().callsArgWith(1, null, 'tx')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var node = { node: { services: services }};
|
||||||
|
var service = new TransactionService(node);
|
||||||
|
|
||||||
|
service.encoding = {
|
||||||
|
encodeTransactionKey: function() { return 'key'; },
|
||||||
|
decodeTransactionValue: function() { return 'value'; }
|
||||||
|
};
|
||||||
|
var tx = service.getTransaction('1234', {}, function(err, res) {
|
||||||
|
if(err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.should.equal('value');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should search mempool', function(done) {
|
||||||
|
var missingInputs = sinon.stub().callsArgWith(1, null, 'tx');
|
||||||
|
var getTransaction = sinon.stub().callsArgWith(1, null, 'tx');
|
||||||
|
var services = {
|
||||||
|
db: {
|
||||||
|
store: {
|
||||||
|
get: sinon.stub().callsArgWith(1, new levelup.errors.NotFoundError())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mempool: {
|
||||||
|
getTransaction: getTransaction
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var node = { node: { services: services }};
|
||||||
|
var service = new TransactionService(node);
|
||||||
|
|
||||||
|
service.encoding = {
|
||||||
|
encodeTransactionKey: function() { return 'key'; }
|
||||||
|
};
|
||||||
|
service._getMissingInputValues = missingInputs;
|
||||||
|
var tx = service.getTransaction('1234', { queryMempool: true }, function(err, res) {
|
||||||
|
if(err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
missingInputs.callCount.should.equal(1);
|
||||||
|
res.should.equal('tx');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user