diff --git a/lib/common/defaults.js b/lib/common/defaults.js index 2853c03..b08abab 100644 --- a/lib/common/defaults.js +++ b/lib/common/defaults.js @@ -77,4 +77,7 @@ Defaults.CONFIRMATIONS_TO_START_CACHING = 6 * 6; // ~ 6hrs // Number of addresses from which tx history is enabled in a wallet Defaults.HISTORY_CACHE_ADDRESS_THRESOLD = 100; +// Cache time for blockchain height (in seconds) +Defaults.BLOCKHEIGHT_CACHE_TIME = 10 * 60; + module.exports = Defaults; diff --git a/lib/server.js b/lib/server.js index 5465335..1c956ad 100644 --- a/lib/server.js +++ b/lib/server.js @@ -108,11 +108,11 @@ WalletService.initialize = function(opts, cb) { }; function initMessageBroker(cb) { - if (opts.messageBroker) { - messageBroker = opts.messageBroker; - } else { - messageBroker = new MessageBroker(opts.messageBrokerOpts); + messageBroker = opts.messageBroker || new MessageBroker(opts.messageBrokerOpts); + if (messageBroker) { + messageBroker.onMessage(WalletService.handleIncomingNotification); } + return cb(); }; @@ -153,6 +153,14 @@ WalletService.initialize = function(opts, cb) { }); }; +WalletService.handleIncomingNotification = function(notification, cb) { + cb = cb || function() {}; + + if (!notification || notification.type != 'NewBlock') return cb(); + WalletService._clearBlockchainHeightCache(); + return cb(); +}; + WalletService.shutDown = function(cb) { if (!initialized) return cb(); @@ -2626,17 +2634,35 @@ WalletService.prototype._normalizeTxHistory = function(txs) { }); }; -var _lastKnownBlockchainHeight; -WalletService.prototype._getLastKnownBlockchainHeight = function(network, cb) { +WalletService._cachedBlockheight; +WalletService._clearBlockchainHeightCache = function() { + WalletService._cachedBlockheight.current = null; +}; + +WalletService.prototype._getBlockchainHeight = function(network, cb) { var self = this; - var bc = self._getBlockchainExplorer(network); - bc.getBlockchainHeight(function(err, height) { - if (!err && height > 0) { - _lastKnownBlockchainHeight = height; - } - return cb(null, _lastKnownBlockchainHeight); - }); + var now = Date.now(); + if (!WalletService._cachedBlockheight) WalletService._cachedBlockheight = {}; + var cache = WalletService._cachedBlockheight; + + function fetchFromBlockchain(cb) { + var bc = self._getBlockchainExplorer(network); + bc.getBlockchainHeight(function(err, height) { + if (!err && height > 0) { + cache.current = height; + cache.last = height; + cache.updatedOn = now; + } + return cb(null, cache.last); + }); + }; + + if (!cache.current || (now - cache.updatedOn) > Defaults.BLOCKHEIGHT_CACHE_TIME * 1000) { + return fetchFromBlockchain(cb); + } + + return cb(null, cache.current); }; /** @@ -2834,7 +2860,7 @@ WalletService.prototype.getTxHistory = function(opts, cb) { if (!txs) return next(); // Fix tx confirmations - self._getLastKnownBlockchainHeight(network, function(err, height) { + self._getBlockchainHeight(network, function(err, height) { if (err || !height) return next(err); _.each(txs, function(tx) { if (tx.blockheight >= 0) { diff --git a/test/integration/server.js b/test/integration/server.js index 845ceb3..f96970d 100644 --- a/test/integration/server.js +++ b/test/integration/server.js @@ -6335,6 +6335,7 @@ describe('Wallet service', function() { it('should get real # of confirmations based on current block height', function(done) { var _confirmations = Defaults.CONFIRMATIONS_TO_START_CACHING; Defaults.CONFIRMATIONS_TO_START_CACHING = 6; + WalletService._cachedBlockheight = null; var h = helpers.historyCacheTest(20); _.each(h, function(x, i) { @@ -6365,17 +6366,26 @@ describe('Wallet service', function() { _.last(txs).confirmations.should.equal(20); blockchainExplorer.getBlockchainHeight = sinon.stub().callsArgWith(0, null, 200); - server.getTxHistory({ - skip: 0, - limit: 30, - }, function(err, txs) { + server._notify('NewBlock', { + hash: 'dummy hash', + }, { + isGlobal: true + }, function(err) { should.not.exist(err); - _.first(txs).confirmations.should.equal(101); - _.last(txs).confirmations.should.equal(120); + setTimeout(function() { + server.getTxHistory({ + skip: 0, + limit: 30, + }, function(err, txs) { + should.not.exist(err); + _.first(txs).confirmations.should.equal(101); + _.last(txs).confirmations.should.equal(120); - server.storage.storeTxHistoryCache.restore(); - Defaults.CONFIRMATIONS_TO_START_CACHING = _confirmations; - done(); + server.storage.storeTxHistoryCache.restore(); + Defaults.CONFIRMATIONS_TO_START_CACHING = _confirmations; + done(); + }); + }, 100); }); }); }); @@ -6384,13 +6394,13 @@ describe('Wallet service', function() { it('should get cached # of confirmations if current height unknown', function(done) { var _confirmations = Defaults.CONFIRMATIONS_TO_START_CACHING; Defaults.CONFIRMATIONS_TO_START_CACHING = 6; + WalletService._cachedBlockheight = null; var h = helpers.historyCacheTest(20); helpers.stubHistory(h); var storeTxHistoryCacheSpy = sinon.spy(server.storage, 'storeTxHistoryCache'); - var _getLastKnownBlockchainHeight = server._getLastKnownBlockchainHeight; - server._getLastKnownBlockchainHeight = sinon.stub().callsArgWith(1, null, null); + blockchainExplorer.getBlockchainHeight = sinon.stub().callsArgWith(0, null, null); // Cache txs server.getTxHistory({ @@ -6414,7 +6424,6 @@ describe('Wallet service', function() { server.storage.storeTxHistoryCache.restore(); Defaults.CONFIRMATIONS_TO_START_CACHING = _confirmations; - server._getLastKnownBlockchainHeight = _getLastKnownBlockchainHeight; done(); }); });