bitcoind: _tryAll -> _tryAllClients

Fixes a timing bug with not all clients being tried
This commit is contained in:
Braydon Fuller 2016-06-09 11:12:52 -04:00
parent e87f628e7a
commit 6ac912545b
2 changed files with 68 additions and 46 deletions

View File

@ -428,8 +428,15 @@ Bitcoin.prototype._resetCaches = function() {
this.blockOverviewCache.reset(); this.blockOverviewCache.reset();
}; };
Bitcoin.prototype._tryAll = function(func, callback) { Bitcoin.prototype._tryAllClients = function(func, callback) {
async.retry({times: this.nodes.length, interval: this.tryAllInterval || 1000}, func, callback); var self = this;
var nodesIndex = 0;
var retry = function(done) {
var client = self.nodes[nodesIndex].client;
nodesIndex++;
func(client, done);
};
async.retry({times: this.nodes.length, interval: this.tryAllInterval || 1000}, retry, callback);
}; };
Bitcoin.prototype._wrapRPCError = function(errObj) { Bitcoin.prototype._wrapRPCError = function(errObj) {
@ -1537,8 +1544,8 @@ Bitcoin.prototype.getAddressSummary = function(addressArg, options, callback) {
Bitcoin.prototype._maybeGetBlockHash = function(blockArg, callback) { Bitcoin.prototype._maybeGetBlockHash = function(blockArg, callback) {
var self = this; var self = this;
if (_.isNumber(blockArg) || (blockArg.length < 40 && /^[0-9]+$/.test(blockArg))) { if (_.isNumber(blockArg) || (blockArg.length < 40 && /^[0-9]+$/.test(blockArg))) {
self._tryAll(function(done) { self._tryAllClients(function(client, done) {
self.client.getBlockHash(blockArg, function(err, response) { client.getBlockHash(blockArg, function(err, response) {
if (err) { if (err) {
return done(self._wrapRPCError(err)); return done(self._wrapRPCError(err));
} }
@ -1563,7 +1570,7 @@ Bitcoin.prototype.getRawBlock = function(blockArg, callback) {
if (err) { if (err) {
return callback(err); return callback(err);
} }
self._tryAll(function(done) { self._tryAllClients(function(client, done) {
self.client.getBlock(blockhash, false, function(err, response) { self.client.getBlock(blockhash, false, function(err, response) {
if (err) { if (err) {
return done(self._wrapRPCError(err)); return done(self._wrapRPCError(err));
@ -1603,8 +1610,8 @@ Bitcoin.prototype.getBlockOverview = function(blockArg, callback) {
callback(null, cachedBlock); callback(null, cachedBlock);
}); });
} else { } else {
self._tryAll(function(done) { self._tryAllClients(function(client, done) {
self.client.getBlock(blockhash, true, function(err, response) { client.getBlock(blockhash, true, function(err, response) {
if (err) { if (err) {
return done(self._wrapRPCError(err)); return done(self._wrapRPCError(err));
} }
@ -1654,8 +1661,8 @@ Bitcoin.prototype.getBlock = function(blockArg, callback) {
callback(null, cachedBlock); callback(null, cachedBlock);
}); });
} else { } else {
self._tryAll(function(done) { self._tryAllClients(function(client, done) {
self.client.getBlock(blockhash, false, function(err, response) { client.getBlock(blockhash, false, function(err, response) {
if (err) { if (err) {
return done(self._wrapRPCError(err)); return done(self._wrapRPCError(err));
} }
@ -1713,8 +1720,8 @@ Bitcoin.prototype.getBlockHeader = function(blockArg, callback) {
if (err) { if (err) {
return callback(err); return callback(err);
} }
self._tryAll(function(done) { self._tryAllClients(function(client, done) {
self.client.getBlockHeader(blockhash, function(err, response) { client.getBlockHeader(blockhash, function(err, response) {
if (err) { if (err) {
return done(self._wrapRPCError(err)); return done(self._wrapRPCError(err));
} }
@ -1795,8 +1802,8 @@ Bitcoin.prototype.getRawTransaction = function(txid, callback) {
callback(null, tx); callback(null, tx);
}); });
} else { } else {
self._tryAll(function(done) { self._tryAllClients(function(client, done) {
self.client.getRawTransaction(txid, function(err, response) { client.getRawTransaction(txid, function(err, response) {
if (err) { if (err) {
return done(self._wrapRPCError(err)); return done(self._wrapRPCError(err));
} }
@ -1822,8 +1829,8 @@ Bitcoin.prototype.getTransaction = function(txid, callback) {
callback(null, tx); callback(null, tx);
}); });
} else { } else {
self._tryAll(function(done) { self._tryAllClients(function(client, done) {
self.client.getRawTransaction(txid, function(err, response) { client.getRawTransaction(txid, function(err, response) {
if (err) { if (err) {
return done(self._wrapRPCError(err)); return done(self._wrapRPCError(err));
} }
@ -1937,8 +1944,8 @@ Bitcoin.prototype.getDetailedTransaction = function(txid, callback) {
callback(null, tx); callback(null, tx);
}); });
} else { } else {
self._tryAll(function(done) { self._tryAllClients(function(client, done) {
self.client.getRawTransaction(txid, 1, function(err, response) { client.getRawTransaction(txid, 1, function(err, response) {
if (err) { if (err) {
return done(self._wrapRPCError(err)); return done(self._wrapRPCError(err));
} }

View File

@ -525,46 +525,61 @@ describe('Bitcoin Service', function() {
}); });
}); });
describe('#_tryAll', function() { describe('#_tryAllClients', function() {
it('will retry the number of bitcoind nodes', function(done) { it('will retry for each node client', function(done) {
var bitcoind = new BitcoinService(baseConfig); var bitcoind = new BitcoinService(baseConfig);
bitcoind.tryAllInterval = 1; bitcoind.tryAllInterval = 1;
bitcoind.nodes.push({}); bitcoind.nodes.push({
bitcoind.nodes.push({}); client: {
bitcoind.nodes.push({}); getInfo: sinon.stub().callsArgWith(0, new Error('test'))
var count = 0;
var func = function(callback) {
count++;
if (count <= 2) {
callback(new Error('test'));
} else {
callback();
} }
}; });
bitcoind._tryAll(function(next) { bitcoind.nodes.push({
func(next); client: {
}, function() { getInfo: sinon.stub().callsArgWith(0, new Error('test'))
count.should.equal(3); }
});
bitcoind.nodes.push({
client: {
getInfo: sinon.stub().callsArg(0)
}
});
bitcoind._tryAllClients(function(client, next) {
client.getInfo(next);
}, function(err) {
if (err) {
return done(err);
}
bitcoind.nodes[0].client.getInfo.callCount.should.equal(1);
bitcoind.nodes[1].client.getInfo.callCount.should.equal(1);
bitcoind.nodes[2].client.getInfo.callCount.should.equal(1);
done(); done();
}); });
}); });
it('will get error if all fail', function(done) { it('will get error if all clients fail', function(done) {
var bitcoind = new BitcoinService(baseConfig); var bitcoind = new BitcoinService(baseConfig);
bitcoind.tryAllInterval = 1; bitcoind.tryAllInterval = 1;
bitcoind.nodes.push({}); bitcoind.nodes.push({
bitcoind.nodes.push({}); client: {
bitcoind.nodes.push({}); getInfo: sinon.stub().callsArgWith(0, new Error('test'))
var count = 0; }
var func = function(callback) { });
count++; bitcoind.nodes.push({
callback(new Error('test')); client: {
}; getInfo: sinon.stub().callsArgWith(0, new Error('test'))
bitcoind._tryAll(function(next) { }
func(next); });
bitcoind.nodes.push({
client: {
getInfo: sinon.stub().callsArgWith(0, new Error('test'))
}
});
bitcoind._tryAllClients(function(client, next) {
client.getInfo(next);
}, function(err) { }, function(err) {
should.exist(err); should.exist(err);
err.should.be.instanceOf(Error);
err.message.should.equal('test'); err.message.should.equal('test');
count.should.equal(3);
done(); done();
}); });
}); });