Skip to content

Commit 3a10347

Browse files
authored
Merge pull request #453 from braydonf/try-all
bitcoind: fix timing issue with tryAll
2 parents 14f21f9 + a2a30b8 commit 3a10347

File tree

2 files changed

+99
-46
lines changed

2 files changed

+99
-46
lines changed

lib/services/bitcoind.js

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -434,8 +434,15 @@ Bitcoin.prototype._resetCaches = function() {
434434
this.blockOverviewCache.reset();
435435
};
436436

437-
Bitcoin.prototype._tryAll = function(func, callback) {
438-
async.retry({times: this.nodes.length, interval: this.tryAllInterval || 1000}, func, callback);
437+
Bitcoin.prototype._tryAllClients = function(func, callback) {
438+
var self = this;
439+
var nodesIndex = this.nodesIndex;
440+
var retry = function(done) {
441+
var client = self.nodes[nodesIndex].client;
442+
nodesIndex = (nodesIndex + 1) % self.nodes.length;
443+
func(client, done);
444+
};
445+
async.retry({times: this.nodes.length, interval: this.tryAllInterval || 1000}, retry, callback);
439446
};
440447

441448
Bitcoin.prototype._wrapRPCError = function(errObj) {
@@ -1544,8 +1551,8 @@ Bitcoin.prototype.getAddressSummary = function(addressArg, options, callback) {
15441551
Bitcoin.prototype._maybeGetBlockHash = function(blockArg, callback) {
15451552
var self = this;
15461553
if (_.isNumber(blockArg) || (blockArg.length < 40 && /^[0-9]+$/.test(blockArg))) {
1547-
self._tryAll(function(done) {
1548-
self.client.getBlockHash(blockArg, function(err, response) {
1554+
self._tryAllClients(function(client, done) {
1555+
client.getBlockHash(blockArg, function(err, response) {
15491556
if (err) {
15501557
return done(self._wrapRPCError(err));
15511558
}
@@ -1570,7 +1577,7 @@ Bitcoin.prototype.getRawBlock = function(blockArg, callback) {
15701577
if (err) {
15711578
return callback(err);
15721579
}
1573-
self._tryAll(function(done) {
1580+
self._tryAllClients(function(client, done) {
15741581
self.client.getBlock(blockhash, false, function(err, response) {
15751582
if (err) {
15761583
return done(self._wrapRPCError(err));
@@ -1610,8 +1617,8 @@ Bitcoin.prototype.getBlockOverview = function(blockArg, callback) {
16101617
callback(null, cachedBlock);
16111618
});
16121619
} else {
1613-
self._tryAll(function(done) {
1614-
self.client.getBlock(blockhash, true, function(err, response) {
1620+
self._tryAllClients(function(client, done) {
1621+
client.getBlock(blockhash, true, function(err, response) {
16151622
if (err) {
16161623
return done(self._wrapRPCError(err));
16171624
}
@@ -1661,8 +1668,8 @@ Bitcoin.prototype.getBlock = function(blockArg, callback) {
16611668
callback(null, cachedBlock);
16621669
});
16631670
} else {
1664-
self._tryAll(function(done) {
1665-
self.client.getBlock(blockhash, false, function(err, response) {
1671+
self._tryAllClients(function(client, done) {
1672+
client.getBlock(blockhash, false, function(err, response) {
16661673
if (err) {
16671674
return done(self._wrapRPCError(err));
16681675
}
@@ -1720,8 +1727,8 @@ Bitcoin.prototype.getBlockHeader = function(blockArg, callback) {
17201727
if (err) {
17211728
return callback(err);
17221729
}
1723-
self._tryAll(function(done) {
1724-
self.client.getBlockHeader(blockhash, function(err, response) {
1730+
self._tryAllClients(function(client, done) {
1731+
client.getBlockHeader(blockhash, function(err, response) {
17251732
if (err) {
17261733
return done(self._wrapRPCError(err));
17271734
}
@@ -1802,8 +1809,8 @@ Bitcoin.prototype.getRawTransaction = function(txid, callback) {
18021809
callback(null, tx);
18031810
});
18041811
} else {
1805-
self._tryAll(function(done) {
1806-
self.client.getRawTransaction(txid, function(err, response) {
1812+
self._tryAllClients(function(client, done) {
1813+
client.getRawTransaction(txid, function(err, response) {
18071814
if (err) {
18081815
return done(self._wrapRPCError(err));
18091816
}
@@ -1829,8 +1836,8 @@ Bitcoin.prototype.getTransaction = function(txid, callback) {
18291836
callback(null, tx);
18301837
});
18311838
} else {
1832-
self._tryAll(function(done) {
1833-
self.client.getRawTransaction(txid, function(err, response) {
1839+
self._tryAllClients(function(client, done) {
1840+
client.getRawTransaction(txid, function(err, response) {
18341841
if (err) {
18351842
return done(self._wrapRPCError(err));
18361843
}
@@ -1944,8 +1951,8 @@ Bitcoin.prototype.getDetailedTransaction = function(txid, callback) {
19441951
callback(null, tx);
19451952
});
19461953
} else {
1947-
self._tryAll(function(done) {
1948-
self.client.getRawTransaction(txid, 1, function(err, response) {
1954+
self._tryAllClients(function(client, done) {
1955+
client.getRawTransaction(txid, 1, function(err, response) {
19491956
if (err) {
19501957
return done(self._wrapRPCError(err));
19511958
}

test/services/bitcoind.unit.js

Lines changed: 75 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -535,46 +535,92 @@ describe('Bitcoin Service', function() {
535535
});
536536
});
537537

538-
describe('#_tryAll', function() {
539-
it('will retry the number of bitcoind nodes', function(done) {
538+
describe('#_tryAllClients', function() {
539+
it('will retry for each node client', function(done) {
540540
var bitcoind = new BitcoinService(baseConfig);
541541
bitcoind.tryAllInterval = 1;
542-
bitcoind.nodes.push({});
543-
bitcoind.nodes.push({});
544-
bitcoind.nodes.push({});
545-
var count = 0;
546-
var func = function(callback) {
547-
count++;
548-
if (count <= 2) {
549-
callback(new Error('test'));
550-
} else {
551-
callback();
542+
bitcoind.nodes.push({
543+
client: {
544+
getInfo: sinon.stub().callsArgWith(0, new Error('test'))
552545
}
553-
};
554-
bitcoind._tryAll(function(next) {
555-
func(next);
556-
}, function() {
557-
count.should.equal(3);
546+
});
547+
bitcoind.nodes.push({
548+
client: {
549+
getInfo: sinon.stub().callsArgWith(0, new Error('test'))
550+
}
551+
});
552+
bitcoind.nodes.push({
553+
client: {
554+
getInfo: sinon.stub().callsArg(0)
555+
}
556+
});
557+
bitcoind._tryAllClients(function(client, next) {
558+
client.getInfo(next);
559+
}, function(err) {
560+
if (err) {
561+
return done(err);
562+
}
563+
bitcoind.nodes[0].client.getInfo.callCount.should.equal(1);
564+
bitcoind.nodes[1].client.getInfo.callCount.should.equal(1);
565+
bitcoind.nodes[2].client.getInfo.callCount.should.equal(1);
558566
done();
559567
});
560568
});
561-
it('will get error if all fail', function(done) {
569+
it('will start using the current node index (round-robin)', function(done) {
562570
var bitcoind = new BitcoinService(baseConfig);
563571
bitcoind.tryAllInterval = 1;
564-
bitcoind.nodes.push({});
565-
bitcoind.nodes.push({});
566-
bitcoind.nodes.push({});
567-
var count = 0;
568-
var func = function(callback) {
569-
count++;
570-
callback(new Error('test'));
571-
};
572-
bitcoind._tryAll(function(next) {
573-
func(next);
572+
bitcoind.nodes.push({
573+
client: {
574+
getInfo: sinon.stub().callsArgWith(0, new Error('2'))
575+
}
576+
});
577+
bitcoind.nodes.push({
578+
client: {
579+
getInfo: sinon.stub().callsArgWith(0, new Error('3'))
580+
}
581+
});
582+
bitcoind.nodes.push({
583+
client: {
584+
getInfo: sinon.stub().callsArgWith(0, new Error('1'))
585+
}
586+
});
587+
bitcoind.nodesIndex = 2;
588+
bitcoind._tryAllClients(function(client, next) {
589+
client.getInfo(next);
590+
}, function(err) {
591+
err.should.be.instanceOf(Error);
592+
err.message.should.equal('3');
593+
bitcoind.nodes[0].client.getInfo.callCount.should.equal(1);
594+
bitcoind.nodes[1].client.getInfo.callCount.should.equal(1);
595+
bitcoind.nodes[2].client.getInfo.callCount.should.equal(1);
596+
bitcoind.nodesIndex.should.equal(2);
597+
done();
598+
});
599+
});
600+
it('will get error if all clients fail', function(done) {
601+
var bitcoind = new BitcoinService(baseConfig);
602+
bitcoind.tryAllInterval = 1;
603+
bitcoind.nodes.push({
604+
client: {
605+
getInfo: sinon.stub().callsArgWith(0, new Error('test'))
606+
}
607+
});
608+
bitcoind.nodes.push({
609+
client: {
610+
getInfo: sinon.stub().callsArgWith(0, new Error('test'))
611+
}
612+
});
613+
bitcoind.nodes.push({
614+
client: {
615+
getInfo: sinon.stub().callsArgWith(0, new Error('test'))
616+
}
617+
});
618+
bitcoind._tryAllClients(function(client, next) {
619+
client.getInfo(next);
574620
}, function(err) {
575621
should.exist(err);
622+
err.should.be.instanceOf(Error);
576623
err.message.should.equal('test');
577-
count.should.equal(3);
578624
done();
579625
});
580626
});

0 commit comments

Comments
 (0)