Commit ee085835 authored by Cédric Moreau's avatar Cédric Moreau
Browse files

Fix: faster /blockchain/blocks method

parent 469807a6
......@@ -2,6 +2,7 @@
var _ = require('underscore');
var Q = require('q');
var co = require('co');
var async = require('async');
var es = require('event-stream');
var moment = require('moment');
......@@ -122,51 +123,17 @@ function BlockchainBinding (server) {
this.blocks = function (req, res) {
res.type('application/json');
async.waterfall([
function (next){
async.parallel({
params: async.apply(ParametersService.getCountAndFrom, req),
current: async.apply(BlockchainService.current)
}, next);
},
function (res, next){
var current = res.current;
var count = parseInt(res.params[0]);
var from = parseInt(res.params[1]);
if (count > 5000) {
next('Count is too high');
return;
}
if (!current || current.number < from) {
next('Starting block #' + from + ' does not exist');
return;
}
count = Math.min(current.number - from + 1, count);
var blocks = [];
var i = from;
async.whilst(
function(){ return i < from + count; },
function (next) {
async.waterfall([
function (next){
BlockchainService.promoted(i, next);
},
function (block, next){
blocks.push(new Block(block).json());
i++;
next();
}
], next);
}, function (err) {
next(err, blocks);
});
}
], function (err, blocks) {
if(err){
res.send(400, err);
return;
co(function *() {
try {
let params = ParametersService.getCountAndFrom(req);
var count = parseInt(params.count);
var from = parseInt(params.from);
let blocks = yield BlockchainService.blocksBetween(from, count);
blocks = blocks.map((b) => (new Block(b).json()));
res.send(200, JSON.stringify(blocks, null, " "));
} catch(e) {
res.send(400, e);
}
res.send(200, JSON.stringify(blocks, null, " "));
});
};
......
......@@ -307,20 +307,7 @@ function FileDAL(profile, home, localDir, myFS, parentFileDAL, dalName, core, lo
return that.blockDAL.lastBlockOfIssuer(issuer);
};
this.getBlocksBetween = function(start, end) {
var s = Math.max(0, start);
return Q.all(_.range(s, end + 1).map(function(number) {
return that.getBlock(number);
}))
.then(function(results){
return results.reduce(function(blocks, block) {
if (block) {
return blocks.concat(block);
}
return blocks;
}, []);
});
};
this.getBlocksBetween = (start, end) => Q(this.blockDAL.getBlocks(Math.max(0, start), end));
this.getCurrentNumber = function() {
return that.blockDAL.getCurrent()
......
......@@ -37,6 +37,15 @@ function BlockDAL(fileDAL, loki) {
return Q(-1);
};
this.getBlocks = (start, end) =>
blocksDB.branchResultset().find({
$and: [{
number: { $gte: start }
}, {
number: { $lte: end }
}]
}).data();
this.lastBlockWithDividend = () => blocksDB.branchResultset().find({ dividend: { $gt: 0 } }).data()[0];
this.lastBlockOfIssuer = (issuer) => {
......
......@@ -1512,6 +1512,19 @@ function BlockchainService (conf, mainDAL, pair) {
return { number: -1 };
});
};
this.blocksBetween = (from, count) => co(function *() {
if (count > 5000) {
throw 'Count is too high';
}
let current = yield that.current();
count = Math.min(current.number - from + 1, count);
if (!current || current.number < from) {
throw 'Starting block #' + from + ' does not exist';
}
let mainFork = yield that.mainFork();
return mainFork.dal.getBlocksBetween(from, from + count - 1);
});
}
/**
......
......@@ -21,26 +21,25 @@ function ParameterNamespace () {
this.getSearchP = (req) => Q.nbind(this.getSearch, this)(req);
this.getCountAndFrom = function (req, callback){
this.getCountAndFrom = function (req){
if(!req.params.from){
callback("From is required");
return;
throw "From is required";
}
if(!req.params.count){
callback("Count is required");
return;
throw "Count is required";
}
var matches = req.params.from.match(/^(\d+)$/);
if(!matches){
callback("From format is incorrect, must be a positive integer");
return;
throw "From format is incorrect, must be a positive integer";
}
var matches2 = req.params.count.match(/^(\d+)$/);
if(!matches){
callback("Count format is incorrect, must be a positive integer");
return;
throw "Count format is incorrect, must be a positive integer";
}
callback(null, matches2[1], matches[1]);
return {
count: matches2[1],
from: matches[1]
};
};
this.getPubkey = function (req, callback){
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment