Skip to content

Commit d9f8fd8

Browse files
committed
fix: don't silence fatal or unknown (non-warning) errors
1 parent 1737d79 commit d9f8fd8

2 files changed

Lines changed: 81 additions & 13 deletions

File tree

lib/services/dashd.js

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@ var utils = require('../utils');
2121
var Service = require('../service');
2222
var rawtxTopicBuffer = new Buffer('7261777478', 'hex');
2323
var rawtxlockTopicBuffer = new Buffer('72617774786c6f636b', 'hex');
24+
25+
function isNonFatalError(err) {
26+
if (err.code === Dash.E_RPC_IN_WARMUP) {
27+
log.warn(err.message);
28+
return true;
29+
}
30+
31+
// will throw instead of retrying
32+
return false;
33+
}
34+
2435
/**
2536
* Provides a friendly event driven API to dashd in Node.js. Manages starting and
2637
* stopping dashd as a child process for application support, as well as connecting
@@ -77,6 +88,7 @@ Dash.DEFAULT_SPAWN_RESTART_TIME = 5000;
7788
Dash.DEFAULT_SPAWN_STOP_TIME = 10000;
7889
Dash.DEFAULT_TRY_ALL_INTERVAL = 1000;
7990
Dash.DEFAULT_REINDEX_INTERVAL = 10000;
91+
Dash.DEFAULT_START_RETRY_TIMES = 60;
8092
Dash.DEFAULT_START_RETRY_INTERVAL = 5000;
8193
Dash.DEFAULT_TIP_UPDATE_INTERVAL = 15000;
8294
Dash.DEFAULT_TRANSACTION_CONCURRENCY = 5;
@@ -96,6 +108,7 @@ Dash.DEFAULT_CONFIG_SETTINGS = {
96108
rpcpassword: 'local321',
97109
uacomment: 'dashcore'
98110
};
111+
Dash.E_RPC_IN_WARMUP = -28;
99112

100113
Dash.prototype._initDefaults = function(options) {
101114
/* jshint maxcomplexity: 15 */
@@ -113,6 +126,7 @@ Dash.prototype._initDefaults = function(options) {
113126

114127
// try all interval
115128
this.tryAllInterval = options.tryAllInterval || Dash.DEFAULT_TRY_ALL_INTERVAL;
129+
this.startRetryTimes = options.startRetryTimes || Dash.DEFAULT_START_RETRY_TIMES;
116130
this.startRetryInterval = options.startRetryInterval || Dash.DEFAULT_START_RETRY_INTERVAL;
117131

118132
// rpc limits
@@ -856,10 +870,7 @@ Dash.prototype._checkReindex = function(node, callback) {
856870
Dash.prototype._loadTipFromNode = function(node, callback) {
857871
var self = this;
858872
node.client.getBestBlockHash(function(err, response) {
859-
if (err && err.code === -28) {
860-
log.warn(err.message);
861-
return callback(self._wrapRPCError(err));
862-
} else if (err) {
873+
if (err) {
863874
return callback(self._wrapRPCError(err));
864875
}
865876
node.client.getBlock(response.result, function(err, response) {
@@ -963,7 +974,12 @@ Dash.prototype._spawnChildProcess = function(callback) {
963974

964975
var exitShutdown = false;
965976

966-
async.retry({times: 60, interval: self.startRetryInterval}, function(done) {
977+
var retryOpts = {
978+
times: self.startRetryTimes,
979+
interval: self.startRetryInterval,
980+
errorFilter: isNonFatalError,
981+
};
982+
async.retry(retryOpts, function (done) {
967983
if (self.node.stopping) {
968984
exitShutdown = true;
969985
return done();
@@ -1008,7 +1024,12 @@ Dash.prototype._connectProcess = function(config, callback) {
10081024
var node = {};
10091025
var exitShutdown = false;
10101026

1011-
async.retry({times: 60, interval: self.startRetryInterval}, function(done) {
1027+
var retryOpts = {
1028+
times: self.startRetryTimes,
1029+
interval: self.startRetryInterval,
1030+
errorFilter: isNonFatalError,
1031+
};
1032+
async.retry(retryOpts, function(done) {
10121033
if (self.node.stopping) {
10131034
exitShutdown = true;
10141035
return done();

test/services/dashd.unit.js

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ describe('Dash Service', function() {
3838
}
3939
};
4040

41+
var RPC_IN_WARMUP_ERROR = new Error('Verifying blocks...');
42+
Object.assign(RPC_IN_WARMUP_ERROR, {
43+
code: DashService.E_RPC_IN_WARMUP
44+
})
45+
4146
describe('@constructor', function() {
4247
it('will create an instance', function() {
4348
var dashd = new DashService(baseConfig);
@@ -1592,17 +1597,17 @@ describe('Dash Service', function() {
15921597
done();
15931598
});
15941599
});
1595-
it('will log when error is RPC_IN_WARMUP', function(done) {
1600+
it('will throw when error is RPC_IN_WARMUP outside of retry', function(done) {
15961601
var dashd = new DashService(baseConfig);
1597-
var getBestBlockHash = sinon.stub().callsArgWith(0, {code: -28, message: 'Verifying blocks...'});
1602+
var getBestBlockHash = sinon.stub().callsArgWith(0, RPC_IN_WARMUP_ERROR);
15981603
var node = {
15991604
client: {
16001605
getBestBlockHash: getBestBlockHash
16011606
}
16021607
};
16031608
dashd._loadTipFromNode(node, function(err) {
16041609
err.should.be.instanceof(Error);
1605-
log.warn.callCount.should.equal(1);
1610+
log.warn.callCount.should.equal(0);
16061611
done();
16071612
});
16081613
});
@@ -1968,7 +1973,7 @@ describe('Dash Service', function() {
19681973
process.emit('exit', 1);
19691974
});
19701975
});
1971-
it('will give error after 60 retries', function(done) {
1976+
it('will give error after 60 retries of RPC_IN_WARMUP warning', function(done) {
19721977
var process = new EventEmitter();
19731978
var spawn = sinon.stub().returns(process);
19741979
var TestDashService = proxyquire('../../lib/services/dashd', {
@@ -1992,13 +1997,44 @@ describe('Dash Service', function() {
19921997
dashd.spawn.config.rpcpassword = 'password';
19931998
dashd.spawn.config.zmqpubrawtx = 'tcp://127.0.0.1:30001';
19941999
dashd.spawn.config.zmqpubrawtxlock = 'tcp://127.0.0.1:30001';
1995-
dashd._loadTipFromNode = sinon.stub().callsArgWith(1, new Error('test'));
2000+
dashd._loadTipFromNode = sinon.stub().callsArgWith(1, RPC_IN_WARMUP_ERROR);
19962001
dashd._spawnChildProcess(function(err) {
19972002
dashd._loadTipFromNode.callCount.should.equal(60);
19982003
err.should.be.instanceof(Error);
19992004
done();
20002005
});
20012006
});
2007+
it('will give error WITHOUT retrying for fatal and unknown errors', function(done) {
2008+
var process = new EventEmitter();
2009+
var spawn = sinon.stub().returns(process);
2010+
var TestDashService = proxyquire('../../lib/services/dashd', {
2011+
fs: {
2012+
readFileSync: readFileSync
2013+
},
2014+
child_process: {
2015+
spawn: spawn
2016+
}
2017+
});
2018+
var dashd = new TestDashService(baseConfig);
2019+
dashd.startRetryInterval = 1;
2020+
dashd._loadSpawnConfiguration = sinon.stub();
2021+
dashd.spawn = {};
2022+
dashd.spawn.exec = 'testexec';
2023+
dashd.spawn.configPath = 'testdir/dash.conf';
2024+
dashd.spawn.datadir = 'testdir';
2025+
dashd.spawn.config = {};
2026+
dashd.spawn.config.rpcport = 20001;
2027+
dashd.spawn.config.rpcuser = 'dash';
2028+
dashd.spawn.config.rpcpassword = 'password';
2029+
dashd.spawn.config.zmqpubrawtx = 'tcp://127.0.0.1:30001';
2030+
dashd.spawn.config.zmqpubrawtxlock = 'tcp://127.0.0.1:30001';
2031+
dashd._loadTipFromNode = sinon.stub().callsArgWith(1, new Error('test'));
2032+
dashd._spawnChildProcess(function(err) {
2033+
dashd._loadTipFromNode.callCount.should.equal(1);
2034+
err.should.be.instanceof(Error);
2035+
done();
2036+
});
2037+
});
20022038
it('will give error from check reindex', function(done) {
20032039
var process = new EventEmitter();
20042040
var spawn = sinon.stub().returns(process);
@@ -2058,9 +2094,9 @@ describe('Dash Service', function() {
20582094
done();
20592095
});
20602096
});
2061-
it('will give error from loadTipFromNode after 60 retries', function(done) {
2097+
it('will give error for warnings from loadTipFromNode after 60 retries', function(done) {
20622098
var dashd = new DashService(baseConfig);
2063-
dashd._loadTipFromNode = sinon.stub().callsArgWith(1, new Error('test'));
2099+
dashd._loadTipFromNode = sinon.stub().callsArgWith(1, RPC_IN_WARMUP_ERROR);
20642100
dashd.startRetryInterval = 1;
20652101
var config = {};
20662102
dashd._connectProcess(config, function(err) {
@@ -2069,6 +2105,17 @@ describe('Dash Service', function() {
20692105
done();
20702106
});
20712107
});
2108+
it('will immediately fail from loadTipFromNode for fatal and unknown errors', function(done) {
2109+
var dashd = new DashService(baseConfig);
2110+
dashd._loadTipFromNode = sinon.stub().callsArgWith(1, new Error('test'));
2111+
dashd.startRetryInterval = 1;
2112+
var config = {};
2113+
dashd._connectProcess(config, function(err) {
2114+
err.should.be.instanceof(Error);
2115+
dashd._loadTipFromNode.callCount.should.equal(1);
2116+
done();
2117+
});
2118+
});
20722119
it('will init zmq/rpc on node', function(done) {
20732120
var dashd = new DashService(baseConfig);
20742121
dashd._initZmqSubSocket = sinon.stub();

0 commit comments

Comments
 (0)