Merge pull request #3 from isocolsky/ref/cache
Cache current blockheight & refresh via notifications
This commit is contained in:
commit
fa98635843
|
@ -77,4 +77,7 @@ Defaults.CONFIRMATIONS_TO_START_CACHING = 6 * 6; // ~ 6hrs
|
||||||
// Number of addresses from which tx history is enabled in a wallet
|
// Number of addresses from which tx history is enabled in a wallet
|
||||||
Defaults.HISTORY_CACHE_ADDRESS_THRESOLD = 100;
|
Defaults.HISTORY_CACHE_ADDRESS_THRESOLD = 100;
|
||||||
|
|
||||||
|
// Cache time for blockchain height (in seconds)
|
||||||
|
Defaults.BLOCKHEIGHT_CACHE_TIME = 10 * 60;
|
||||||
|
|
||||||
module.exports = Defaults;
|
module.exports = Defaults;
|
||||||
|
|
|
@ -108,11 +108,11 @@ WalletService.initialize = function(opts, cb) {
|
||||||
};
|
};
|
||||||
|
|
||||||
function initMessageBroker(cb) {
|
function initMessageBroker(cb) {
|
||||||
if (opts.messageBroker) {
|
messageBroker = opts.messageBroker || new MessageBroker(opts.messageBrokerOpts);
|
||||||
messageBroker = opts.messageBroker;
|
if (messageBroker) {
|
||||||
} else {
|
messageBroker.onMessage(WalletService.handleIncomingNotification);
|
||||||
messageBroker = new MessageBroker(opts.messageBrokerOpts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return cb();
|
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) {
|
WalletService.shutDown = function(cb) {
|
||||||
if (!initialized) return cb();
|
if (!initialized) return cb();
|
||||||
|
@ -2626,17 +2634,35 @@ WalletService.prototype._normalizeTxHistory = function(txs) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var _lastKnownBlockchainHeight;
|
WalletService._cachedBlockheight;
|
||||||
WalletService.prototype._getLastKnownBlockchainHeight = function(network, cb) {
|
WalletService._clearBlockchainHeightCache = function() {
|
||||||
|
WalletService._cachedBlockheight.current = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
WalletService.prototype._getBlockchainHeight = function(network, cb) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var bc = self._getBlockchainExplorer(network);
|
var now = Date.now();
|
||||||
bc.getBlockchainHeight(function(err, height) {
|
if (!WalletService._cachedBlockheight) WalletService._cachedBlockheight = {};
|
||||||
if (!err && height > 0) {
|
var cache = WalletService._cachedBlockheight;
|
||||||
_lastKnownBlockchainHeight = height;
|
|
||||||
}
|
function fetchFromBlockchain(cb) {
|
||||||
return cb(null, _lastKnownBlockchainHeight);
|
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();
|
if (!txs) return next();
|
||||||
|
|
||||||
// Fix tx confirmations
|
// Fix tx confirmations
|
||||||
self._getLastKnownBlockchainHeight(network, function(err, height) {
|
self._getBlockchainHeight(network, function(err, height) {
|
||||||
if (err || !height) return next(err);
|
if (err || !height) return next(err);
|
||||||
_.each(txs, function(tx) {
|
_.each(txs, function(tx) {
|
||||||
if (tx.blockheight >= 0) {
|
if (tx.blockheight >= 0) {
|
||||||
|
|
|
@ -6335,64 +6335,97 @@ describe('Wallet service', function() {
|
||||||
it('should get real # of confirmations based on current block height', function(done) {
|
it('should get real # of confirmations based on current block height', function(done) {
|
||||||
var _confirmations = Defaults.CONFIRMATIONS_TO_START_CACHING;
|
var _confirmations = Defaults.CONFIRMATIONS_TO_START_CACHING;
|
||||||
Defaults.CONFIRMATIONS_TO_START_CACHING = 6;
|
Defaults.CONFIRMATIONS_TO_START_CACHING = 6;
|
||||||
|
WalletService._cachedBlockheight = null;
|
||||||
|
|
||||||
var h = helpers.historyCacheTest(20);
|
var h = helpers.historyCacheTest(20);
|
||||||
|
_.each(h, function(x, i) {
|
||||||
|
x.blockheight = 100 - i;
|
||||||
|
});
|
||||||
helpers.stubHistory(h);
|
helpers.stubHistory(h);
|
||||||
var storeTxHistoryCacheSpy = sinon.spy(server.storage, 'storeTxHistoryCache');
|
var storeTxHistoryCacheSpy = sinon.spy(server.storage, 'storeTxHistoryCache');
|
||||||
var skip = 0;
|
|
||||||
var limit = 20;
|
|
||||||
|
|
||||||
blockchainExplorer.getBlockchainHeight = sinon.stub().callsArgWith(0, null, 100);
|
blockchainExplorer.getBlockchainHeight = sinon.stub().callsArgWith(0, null, 100);
|
||||||
|
|
||||||
|
// Cache txs
|
||||||
server.getTxHistory({
|
server.getTxHistory({
|
||||||
skip: skip,
|
skip: 0,
|
||||||
limit: limit,
|
limit: 30,
|
||||||
}, function(err, txs) {
|
}, function(err, txs) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
should.exist(txs);
|
should.exist(txs);
|
||||||
txs.length.should.equal(limit);
|
|
||||||
var calls = storeTxHistoryCacheSpy.getCalls();
|
var calls = storeTxHistoryCacheSpy.getCalls();
|
||||||
calls.length.should.equal(1);
|
calls.length.should.equal(1);
|
||||||
|
|
||||||
_.first(txs).confirmations.should.equal(82);
|
server.getTxHistory({
|
||||||
_.last(txs).confirmations.should.equal(101);
|
skip: 0,
|
||||||
|
limit: 30,
|
||||||
|
}, function(err, txs) {
|
||||||
|
should.not.exist(err);
|
||||||
|
txs.length.should.equal(20);
|
||||||
|
_.first(txs).confirmations.should.equal(1);
|
||||||
|
_.last(txs).confirmations.should.equal(20);
|
||||||
|
|
||||||
server.storage.storeTxHistoryCache.restore();
|
blockchainExplorer.getBlockchainHeight = sinon.stub().callsArgWith(0, null, 200);
|
||||||
Defaults.CONFIRMATIONS_TO_START_CACHING = _confirmations;
|
server._notify('NewBlock', {
|
||||||
done();
|
hash: 'dummy hash',
|
||||||
|
}, {
|
||||||
|
isGlobal: true
|
||||||
|
}, function(err) {
|
||||||
|
should.not.exist(err);
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should get cached # of confirmations if current height unknown', function(done) {
|
it('should get cached # of confirmations if current height unknown', function(done) {
|
||||||
var _confirmations = Defaults.CONFIRMATIONS_TO_START_CACHING;
|
var _confirmations = Defaults.CONFIRMATIONS_TO_START_CACHING;
|
||||||
Defaults.CONFIRMATIONS_TO_START_CACHING = 6;
|
Defaults.CONFIRMATIONS_TO_START_CACHING = 6;
|
||||||
|
WalletService._cachedBlockheight = null;
|
||||||
|
|
||||||
var h = helpers.historyCacheTest(20);
|
var h = helpers.historyCacheTest(20);
|
||||||
helpers.stubHistory(h);
|
helpers.stubHistory(h);
|
||||||
var storeTxHistoryCacheSpy = sinon.spy(server.storage, 'storeTxHistoryCache');
|
var storeTxHistoryCacheSpy = sinon.spy(server.storage, 'storeTxHistoryCache');
|
||||||
var skip = 0;
|
|
||||||
var limit = 20;
|
|
||||||
|
|
||||||
var _getLastKnownBlockchainHeight = server._getLastKnownBlockchainHeight;
|
blockchainExplorer.getBlockchainHeight = sinon.stub().callsArgWith(0, null, null);
|
||||||
server._getLastKnownBlockchainHeight = sinon.stub().callsArgWith(1, null, null);
|
|
||||||
|
|
||||||
|
// Cache txs
|
||||||
server.getTxHistory({
|
server.getTxHistory({
|
||||||
skip: skip,
|
skip: 0,
|
||||||
limit: limit,
|
limit: 30,
|
||||||
}, function(err, txs) {
|
}, function(err, txs) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
should.exist(txs);
|
should.exist(txs);
|
||||||
txs.length.should.equal(limit);
|
txs.length.should.equal(20);
|
||||||
var calls = storeTxHistoryCacheSpy.getCalls();
|
var calls = storeTxHistoryCacheSpy.getCalls();
|
||||||
calls.length.should.equal(1);
|
calls.length.should.equal(1);
|
||||||
|
|
||||||
_.first(txs).confirmations.should.equal(0);
|
server.getTxHistory({
|
||||||
_.last(txs).confirmations.should.equal(19);
|
skip: 0,
|
||||||
|
limit: 30,
|
||||||
|
}, function(err, txs) {
|
||||||
|
should.not.exist(err);
|
||||||
|
txs.length.should.equal(20);
|
||||||
|
_.first(txs).confirmations.should.equal(0);
|
||||||
|
_.last(txs).confirmations.should.equal(19);
|
||||||
|
|
||||||
server.storage.storeTxHistoryCache.restore();
|
server.storage.storeTxHistoryCache.restore();
|
||||||
Defaults.CONFIRMATIONS_TO_START_CACHING = _confirmations;
|
Defaults.CONFIRMATIONS_TO_START_CACHING = _confirmations;
|
||||||
server._getLastKnownBlockchainHeight = _getLastKnownBlockchainHeight;
|
done();
|
||||||
done();
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue