enforce limit at POST /txs requests

This commit is contained in:
Matias Alejo Garcia 2015-07-13 16:39:05 -03:00
parent 1615925ae5
commit 71e3c1ba9c
2 changed files with 40 additions and 22 deletions

View File

@ -9,6 +9,9 @@ var Address = require('../models/Address');
var common = require('./common'); var common = require('./common');
var async = require('async'); var async = require('async');
var MAX_BATCH_SIZE = 100;
var RPC_CONCURRENCY = 5;
var tDb = require('../../lib/TransactionDb').default(); var tDb = require('../../lib/TransactionDb').default();
var checkSync = function(req, res) { var checkSync = function(req, res) {
@ -50,7 +53,7 @@ var getAddrs = function(req, res, next) {
} }
} catch (e) { } catch (e) {
common.handleErrors({ common.handleErrors({
message: 'Invalid address:' + e.message, message: 'Invalid addrs param:' + e.message,
code: 1 code: 1
}, res, next); }, res, next);
return null; return null;
@ -101,7 +104,7 @@ exports.multiutxo = function(req, res, next) {
var as = getAddrs(req, res, next); var as = getAddrs(req, res, next);
if (as) { if (as) {
var utxos = []; var utxos = [];
async.each(as, function(a, callback) { async.eachLimit(as, RPC_CONCURRENCY, function(a, callback) {
a.update(function(err) { a.update(function(err) {
if (err) callback(err); if (err) callback(err);
utxos = utxos.concat(a.unspent); utxos = utxos.concat(a.unspent);
@ -123,23 +126,31 @@ exports.multitxs = function(req, res, next) {
function processTxs(txs, from, to, cb) { function processTxs(txs, from, to, cb) {
txs = _.uniq(_.flatten(txs), 'txid'); txs = _.uniq(_.flatten(txs), 'txid');
var nbTxs = txs.length; var nbTxs = txs.length;
var paginated = !_.isUndefined(from) || !_.isUndefined(to);
if (paginated) { if ( _.isUndefined(from) && _.isUndefined(to)) {
txs.sort(function(a, b) { from = 0;
return (b.ts || b.ts) - (a.ts || a.ts); to = MAX_BATCH_SIZE;
});
var start = Math.max(from || 0, 0);
var end = Math.min(to || txs.length, txs.length);
txs = txs.slice(start, end);
} }
if ( ! _.isUndefined(from) && _.isUndefined(to))
to = from + MAX_BATCH_SIZE;
if ( ! _.isUndefined(from) && ! _.isUndefined(to) && to - from > MAX_BATCH_SIZE)
to = from + MAX_BATCH_SIZE;
txs.sort(function(a, b) {
return (b.ts || b.ts) - (a.ts || a.ts);
});
var start = Math.max(from || 0, 0);
var end = Math.min(to || nbTxs, nbTxs);
txs = txs.slice(start, end);
var txIndex = {}; var txIndex = {};
_.each(txs, function(tx) { _.each(txs, function(tx) {
txIndex[tx.txid] = tx; txIndex[tx.txid] = tx;
}); });
async.eachLimit(txs, 5, function(tx, callback) { async.eachLimit(txs, RPC_CONCURRENCY, function(tx, callback) {
tDb.fromIdWithInfo(tx.txid, function(err, tx) { tDb.fromIdWithInfo(tx.txid, function(err, tx) {
if (err) { if (err) {
console.log(err); console.log(err);
@ -154,14 +165,12 @@ exports.multitxs = function(req, res, next) {
if (err) return cb(err); if (err) return cb(err);
var transactions = _.pluck(txs, 'info'); var transactions = _.pluck(txs, 'info');
if (paginated) { transactions = {
transactions = { totalItems: nbTxs,
totalItems: nbTxs, from: +from,
from: +from, to: +to,
to: +to, items: transactions,
items: transactions, };
};
}
return cb(null, transactions); return cb(null, transactions);
}); });
}; };
@ -172,17 +181,19 @@ exports.multitxs = function(req, res, next) {
var as = getAddrs(req, res, next); var as = getAddrs(req, res, next);
if (as) { if (as) {
var txs = []; var txs = [];
async.eachLimit(as, 10, function(a, callback) { async.eachLimit(as, RPC_CONCURRENCY, function(a, callback) {
a.update(function(err) { a.update(function(err) {
if (err) callback(err); if (err) callback(err);
txs.push(a.transactions); txs.push(a.transactions);
callback(); callback();
}, { }, {
ignoreCache: req.param('noCache'), ignoreCache: req.param('noCache'),
includeTxInfo: true includeTxInfo: true,
dontFillSpent: true,
}); });
}, function(err) { // finished callback }, function(err) { // finished callback
if (err) return common.handleErrors(err, res); if (err) return common.handleErrors(err, res);
processTxs(txs, from, to, function(err, transactions) { processTxs(txs, from, to, function(err, transactions) {
if (err) return common.handleErrors(err, res); if (err) return common.handleErrors(err, res);
res.jsonp(transactions); res.jsonp(transactions);

View File

@ -17,7 +17,7 @@ var ADDR_PREFIX = 'txa2-'; //txa-<addr>-<tsr>-<txid>-<n>
// TODO: use bitcore networks module // TODO: use bitcore networks module
var genesisTXID = '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b'; var genesisTXID = '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b';
var CONCURRENCY = 10; var CONCURRENCY = 5;
var DEFAULT_SAFE_CONFIRMATIONS = 6; var DEFAULT_SAFE_CONFIRMATIONS = 6;
var MAX_OPEN_FILES = 500; var MAX_OPEN_FILES = 500;
@ -448,6 +448,9 @@ TransactionDb.prototype._parseAddrData = function(k, data, ignoreCache) {
return item; return item;
}; };
// opts.dontFillSpent
TransactionDb.prototype.fromAddr = function(addr, opts, cb) { TransactionDb.prototype.fromAddr = function(addr, opts, cb) {
opts = opts || {}; opts = opts || {};
var self = this; var self = this;
@ -470,6 +473,10 @@ TransactionDb.prototype.fromAddr = function(addr, opts, cb) {
}) })
.on('error', cb) .on('error', cb)
.on('end', function() { .on('end', function() {
if (opts.dontFillSpent) {
return cb(null, ret)
}
async.eachLimit(ret.filter(function(x) { async.eachLimit(ret.filter(function(x) {
return !x.spentIsConfirmed; return !x.spentIsConfirmed;
}), CONCURRENCY, function(o, e_c) { }), CONCURRENCY, function(o, e_c) {