blocks: added lru cache
This commit is contained in:
parent
13efeec84b
commit
3c355c30a9
@ -90,7 +90,7 @@ AddressController.prototype.checkAddrs = function(req, res, next) {
|
||||
}
|
||||
|
||||
this.check(req, res, next, req.addrs);
|
||||
}
|
||||
};
|
||||
|
||||
AddressController.prototype.check = function(req, res, next, addresses) {
|
||||
if(!addresses.length || !addresses[0]) {
|
||||
|
||||
133
lib/blocks.js
133
lib/blocks.js
@ -5,11 +5,16 @@ var async = require('async');
|
||||
var bitcore = require('bitcore-lib');
|
||||
var pools = require('../pools.json');
|
||||
var BN = bitcore.crypto.BN;
|
||||
var LRU = require('lru-cache');
|
||||
|
||||
|
||||
function BlockController(node) {
|
||||
var self = this;
|
||||
this.node = node;
|
||||
|
||||
this.blockSummaryCache = LRU(1000000);
|
||||
this.blockCache = LRU(1000);
|
||||
|
||||
this.poolStrings = {};
|
||||
pools.forEach(function(pool) {
|
||||
pool.searchStrings.forEach(function(s) {
|
||||
@ -29,23 +34,34 @@ var BLOCK_LIMIT = 200;
|
||||
BlockController.prototype.block = function(req, res, next, hash) {
|
||||
var self = this;
|
||||
|
||||
this.node.getBlock(hash, function(err, block) {
|
||||
if(err && err.message === 'Block not found.') {
|
||||
// TODO libbitcoind should pass an instance of errors.Block.NotFound
|
||||
return common.handleErrors(null, res);
|
||||
} else if(err) {
|
||||
return common.handleErrors(err, res);
|
||||
}
|
||||
function finish(blockResult) {
|
||||
blockResult.confirmations = self.node.services.bitcoind.height - blockResult.height + 1;
|
||||
req.block = blockResult;
|
||||
next();
|
||||
}
|
||||
|
||||
self.node.services.bitcoind.getBlockHeader(hash, function(err, info) {
|
||||
if (err) {
|
||||
var block = self.blockCache.get(hash);
|
||||
|
||||
if (block) {
|
||||
finish(block);
|
||||
} else {
|
||||
self.node.getBlock(hash, function(err, block) {
|
||||
if(err && err.message === 'Block not found.') {
|
||||
// TODO libbitcoind should pass an instance of errors.Block.NotFound
|
||||
return common.handleErrors(null, res);
|
||||
} else if(err) {
|
||||
return common.handleErrors(err, res);
|
||||
}
|
||||
req.block = self.transformBlock(block, info);
|
||||
next();
|
||||
self.node.services.bitcoind.getBlockHeader(hash, function(err, info) {
|
||||
if (err) {
|
||||
return common.handleErrors(err, res);
|
||||
}
|
||||
var blockResult = self.transformBlock(block, info);
|
||||
self.blockCache.set(hash, blockResult);
|
||||
finish(blockResult);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
BlockController.prototype.transformBlock = function(block, info) {
|
||||
@ -55,7 +71,6 @@ BlockController.prototype.transformBlock = function(block, info) {
|
||||
});
|
||||
return {
|
||||
hash: block.hash,
|
||||
confirmations: this.node.services.bitcoind.height - info.height + 1,
|
||||
size: block.toBuffer().length,
|
||||
height: info.height,
|
||||
version: blockObj.header.version,
|
||||
@ -94,6 +109,58 @@ BlockController.prototype.blockIndex = function(req, res, next, height) {
|
||||
});
|
||||
};
|
||||
|
||||
BlockController.prototype._getBlockSummary = function(hash, moreTs, next) {
|
||||
var self = this;
|
||||
|
||||
function finish(result) {
|
||||
if (moreTs > result.time) {
|
||||
moreTs = result.time;
|
||||
}
|
||||
return next(null, result);
|
||||
}
|
||||
|
||||
var summaryCache = self.blockSummaryCache.get(hash);
|
||||
|
||||
if (summaryCache) {
|
||||
finish(summaryCache);
|
||||
} else {
|
||||
self.node.services.bitcoind.getRawBlock(hash, function(err, blockBuffer) {
|
||||
if(err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
var br = new bitcore.encoding.BufferReader(blockBuffer);
|
||||
// take a shortcut to get number of transactions and the blocksize.
|
||||
// Also reads the coinbase transaction and only that.
|
||||
// Old code parsed all transactions in every block _and_ then encoded
|
||||
// them all back together to get the binary size of the block.
|
||||
// FIXME: This code might still read the whole block. Fixing that
|
||||
// would require changes in bitcore-node.
|
||||
var header = bitcore.BlockHeader.fromBufferReader(br);
|
||||
var info = {};
|
||||
var txlength = br.readVarintNum();
|
||||
info.transactions = [bitcore.Transaction().fromBufferReader(br)];
|
||||
|
||||
self.node.services.bitcoind.getBlockHeader(hash, function(err, blockHeader) {
|
||||
|
||||
var block = {
|
||||
height: blockHeader.height,
|
||||
size: blockBuffer.length,
|
||||
hash: hash,
|
||||
time: header.time,
|
||||
txlength: txlength,
|
||||
poolInfo: self.getPoolInfo(info)
|
||||
};
|
||||
|
||||
self.blockSummaryCache.set(hash, summary);
|
||||
|
||||
finish(block);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// List blocks by date
|
||||
BlockController.prototype.list = function(req, res) {
|
||||
var self = this;
|
||||
@ -130,6 +197,8 @@ BlockController.prototype.list = function(req, res) {
|
||||
return common.handleErrors(err, res);
|
||||
}
|
||||
|
||||
hashes.reverse();
|
||||
|
||||
if(hashes.length > limit) {
|
||||
more = true;
|
||||
hashes = hashes.slice(0, limit);
|
||||
@ -138,41 +207,7 @@ BlockController.prototype.list = function(req, res) {
|
||||
async.mapSeries(
|
||||
hashes,
|
||||
function(hash, next) {
|
||||
self.node.services.bitcoind.getBlock(hash, function(err, blockBuffer) {
|
||||
if(err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
var br = new bitcore.encoding.BufferReader(blockBuffer);
|
||||
// take a shortcut to get number of transactions and the blocksize.
|
||||
// Also reads the coinbase transaction and only that.
|
||||
// Old code parsed all transactions in every block _and_ then encoded
|
||||
// them all back together to get the binary size of the block.
|
||||
// FIXME: This code might still read the whole block. Fixing that
|
||||
// would require changes in bitcore-node.
|
||||
var header = bitcore.BlockHeader.fromBufferReader(br);
|
||||
var info = {};
|
||||
var txlength = br.readVarintNum();
|
||||
info.transactions = [bitcore.Transaction().fromBufferReader(br)];
|
||||
|
||||
self.node.services.bitcoind.getBlockHeader(hash, function(err, blockHeader) {
|
||||
|
||||
var block = {
|
||||
height: blockHeader.height,
|
||||
size: blockBuffer.length,
|
||||
hash: hash,
|
||||
time: header.time,
|
||||
txlength: txlength,
|
||||
poolInfo: self.getPoolInfo(info)
|
||||
};
|
||||
|
||||
if(moreTs > header.timestamp) {
|
||||
moreTs = header.timestamp;
|
||||
}
|
||||
|
||||
return next(null, block);
|
||||
});
|
||||
});
|
||||
self._getBlockSummary(hash, moreTs, next);
|
||||
},
|
||||
function(err, blocks) {
|
||||
if(err) {
|
||||
|
||||
@ -65,6 +65,7 @@
|
||||
"bitcore-message": "^1.0.1",
|
||||
"body-parser": "^1.13.3",
|
||||
"lodash": "^2.4.1",
|
||||
"lru-cache": "^4.0.1",
|
||||
"request": "^2.64.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user