From 9e281320ac662301e47e2fcb0a9409b74f8768b9 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 26 May 2015 23:38:22 -0300 Subject: [PATCH] returns 503 in /addr/* if sync is not finished --- app/controllers/addresses.js | 69 +++++++++++++---- app/controllers/common.js | 3 + app/models/Address.js | 142 ++++++++++++++++++----------------- config/express.js | 4 +- insight.js | 12 --- 5 files changed, 133 insertions(+), 97 deletions(-) diff --git a/app/controllers/addresses.js b/app/controllers/addresses.js index 30cfca3..f92d768 100644 --- a/app/controllers/addresses.js +++ b/app/controllers/addresses.js @@ -11,6 +11,18 @@ var async = require('async'); var tDb = require('../../lib/TransactionDb').default(); +var checkSync = function(req, res) { + if (req.historicSync) { + var i = req.historicSync.info() + if (i.status !== 'complete') { + common.notReady(req, res, i.syncPercentage); + return false; + } + } + return true; +}; + + var getAddr = function(req, res, next) { var a; try { @@ -47,6 +59,7 @@ var getAddrs = function(req, res, next) { }; exports.show = function(req, res, next) { + if (!checkSync(req, res)) return; var a = getAddr(req, res, next); if (a) { @@ -56,13 +69,18 @@ exports.show = function(req, res, next) { } else { return res.jsonp(a.getObj()); } - }, {txLimit: req.query.noTxList?0:-1, ignoreCache: req.param('noCache')}); + }, { + txLimit: req.query.noTxList ? 0 : -1, + ignoreCache: req.param('noCache') + }); } }; exports.utxo = function(req, res, next) { + if (!checkSync(req, res)) return; + var a = getAddr(req, res, next); if (a) { a.update(function(err) { @@ -71,11 +89,15 @@ exports.utxo = function(req, res, next) { else { return res.jsonp(a.unspent); } - }, {onlyUnspent:1, ignoreCache: req.param('noCache')}); + }, { + onlyUnspent: 1, + ignoreCache: req.param('noCache') + }); } }; exports.multiutxo = function(req, res, next) { + if (!checkSync(req, res)) return; var as = getAddrs(req, res, next); if (as) { var utxos = []; @@ -84,7 +106,10 @@ exports.multiutxo = function(req, res, next) { if (err) callback(err); utxos = utxos.concat(a.unspent); callback(); - }, {onlyUnspent:1, ignoreCache: req.param('noCache')}); + }, { + onlyUnspent: 1, + ignoreCache: req.param('noCache') + }); }, function(err) { // finished callback if (err) return common.handleErrors(err, res); res.jsonp(utxos); @@ -93,6 +118,7 @@ exports.multiutxo = function(req, res, next) { }; exports.multitxs = function(req, res, next) { + if (!checkSync(req, res)) return; function processTxs(txs, from, to, cb) { txs = _.uniq(_.flatten(txs), 'txid'); @@ -109,9 +135,11 @@ exports.multitxs = function(req, res, next) { } var txIndex = {}; - _.each(txs, function (tx) { txIndex[tx.txid] = tx; }); + _.each(txs, function(tx) { + txIndex[tx.txid] = tx; + }); - async.each(txs, function (tx, callback) { + async.each(txs, function(tx, callback) { tDb.fromIdWithInfo(tx.txid, function(err, tx) { if (err) console.log(err); if (tx && tx.info) { @@ -119,9 +147,9 @@ exports.multitxs = function(req, res, next) { } callback(); }); - }, function (err) { + }, function(err) { if (err) return cb(err); - + var transactions = _.pluck(txs, 'info'); if (paginated) { transactions = { @@ -146,10 +174,13 @@ exports.multitxs = function(req, res, next) { if (err) callback(err); txs.push(a.transactions); callback(); - }, {ignoreCache: req.param('noCache'), includeTxInfo: true}); + }, { + ignoreCache: req.param('noCache'), + includeTxInfo: true + }); }, function(err) { // finished callback 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); res.jsonp(transactions); }); @@ -158,6 +189,7 @@ exports.multitxs = function(req, res, next) { }; exports.balance = function(req, res, next) { + if (!checkSync(req, res)) return; var a = getAddr(req, res, next); if (a) a.update(function(err) { @@ -166,10 +198,13 @@ exports.balance = function(req, res, next) { } else { return res.jsonp(a.balanceSat); } - }, {ignoreCache: req.param('noCache')}); + }, { + ignoreCache: req.param('noCache') + }); }; exports.totalReceived = function(req, res, next) { + if (!checkSync(req, res)) return; var a = getAddr(req, res, next); if (a) a.update(function(err) { @@ -178,10 +213,13 @@ exports.totalReceived = function(req, res, next) { } else { return res.jsonp(a.totalReceivedSat); } - }, {ignoreCache: req.param('noCache')}); + }, { + ignoreCache: req.param('noCache') + }); }; exports.totalSent = function(req, res, next) { + if (!checkSync(req, res)) return; var a = getAddr(req, res, next); if (a) a.update(function(err) { @@ -190,10 +228,13 @@ exports.totalSent = function(req, res, next) { } else { return res.jsonp(a.totalSentSat); } - }, {ignoreCache: req.param('noCache')}); + }, { + ignoreCache: req.param('noCache') + }); }; exports.unconfirmedBalance = function(req, res, next) { + if (!checkSync(req, res)) return; var a = getAddr(req, res, next); if (a) a.update(function(err) { @@ -202,5 +243,7 @@ exports.unconfirmedBalance = function(req, res, next) { } else { return res.jsonp(a.unconfirmedBalanceSat); } - }, {ignoreCache: req.param('noCache')}); + }, { + ignoreCache: req.param('noCache') + }); }; diff --git a/app/controllers/common.js b/app/controllers/common.js index b44756b..a13d8e3 100644 --- a/app/controllers/common.js +++ b/app/controllers/common.js @@ -1,5 +1,8 @@ 'use strict'; +exports.notReady = function (err, res, p) { + res.status(503).send('Server not yet ready. Percentage:' + p); +}; exports.handleErrors = function (err, res) { if (err) { diff --git a/app/models/Address.js b/app/models/Address.js index 1cfe7e7..cbdd322 100644 --- a/app/models/Address.js +++ b/app/models/Address.js @@ -1,43 +1,43 @@ 'use strict'; -var imports = require('soop').imports(); -var async = require('async'); -var bitcore = require('bitcore'); -var BitcoreAddress = bitcore.Address; +var imports = require('soop').imports(); +var async = require('async'); +var bitcore = require('bitcore'); +var BitcoreAddress = bitcore.Address; var BitcoreTransaction = bitcore.Transaction; -var BitcoreUtil = bitcore.util; -var Parser = bitcore.BinaryParser; -var Buffer = bitcore.Buffer; -var TransactionDb = imports.TransactionDb || require('../../lib/TransactionDb').default(); -var BlockDb = imports.BlockDb || require('../../lib/BlockDb').default(); -var config = require('../../config/config'); -var CONCURRENCY = 5; +var BitcoreUtil = bitcore.util; +var Parser = bitcore.BinaryParser; +var Buffer = bitcore.Buffer; +var TransactionDb = imports.TransactionDb || require('../../lib/TransactionDb').default(); +var BlockDb = imports.BlockDb || require('../../lib/BlockDb').default(); +var config = require('../../config/config'); +var CONCURRENCY = 5; function Address(addrStr) { - this.balanceSat = 0; - this.totalReceivedSat = 0; - this.totalSentSat = 0; + this.balanceSat = 0; + this.totalReceivedSat = 0; + this.totalSentSat = 0; - this.unconfirmedBalanceSat = 0; + this.unconfirmedBalanceSat = 0; - this.txApperances = 0; - this.unconfirmedTxApperances= 0; - this.seen = {}; + this.txApperances = 0; + this.unconfirmedTxApperances = 0; + this.seen = {}; // TODO store only txids? +index? +all? - this.transactions = []; - this.unspent = []; + this.transactions = []; + this.unspent = []; var a = new BitcoreAddress(addrStr); a.validate(); - this.addrStr = addrStr; - + this.addrStr = addrStr; + Object.defineProperty(this, 'totalSent', { get: function() { return parseFloat(this.totalSentSat) / parseFloat(BitcoreUtil.COIN); }, - set: function(i) { - this.totalSentSat = i * BitcoreUtil.COIN; + set: function(i) { + this.totalSentSat = i * BitcoreUtil.COIN; }, enumerable: 1, }); @@ -46,8 +46,8 @@ function Address(addrStr) { get: function() { return parseFloat(this.balanceSat) / parseFloat(BitcoreUtil.COIN); }, - set: function(i) { - this.balance = i * BitcoreUtil.COIN; + set: function(i) { + this.balance = i * BitcoreUtil.COIN; }, enumerable: 1, }); @@ -56,8 +56,8 @@ function Address(addrStr) { get: function() { return parseFloat(this.totalReceivedSat) / parseFloat(BitcoreUtil.COIN); }, - set: function(i) { - this.totalReceived = i * BitcoreUtil.COIN; + set: function(i) { + this.totalReceived = i * BitcoreUtil.COIN; }, enumerable: 1, }); @@ -67,8 +67,8 @@ function Address(addrStr) { get: function() { return parseFloat(this.unconfirmedBalanceSat) / parseFloat(BitcoreUtil.COIN); }, - set: function(i) { - this.unconfirmedBalanceSat = i * BitcoreUtil.COIN; + set: function(i) { + this.unconfirmedBalanceSat = i * BitcoreUtil.COIN; }, enumerable: 1, }); @@ -78,18 +78,18 @@ function Address(addrStr) { Address.prototype.getObj = function() { // Normalize json address return { - 'addrStr': this.addrStr, - 'balance': this.balance, - 'balanceSat': this.balanceSat, - 'totalReceived': this.totalReceived, - 'totalReceivedSat': this.totalReceivedSat, - 'totalSent': this.totalSent, - 'totalSentSat': this.totalSentSat, - 'unconfirmedBalance': this.unconfirmedBalance, - 'unconfirmedBalanceSat': this.unconfirmedBalanceSat, - 'unconfirmedTxApperances': this.unconfirmedTxApperances, - 'txApperances': this.txApperances, - 'transactions': this.transactions + 'addrStr': this.addrStr, + 'balance': this.balance, + 'balanceSat': this.balanceSat, + 'totalReceived': this.totalReceived, + 'totalReceivedSat': this.totalReceivedSat, + 'totalSent': this.totalSent, + 'totalSentSat': this.totalSentSat, + 'unconfirmedBalance': this.unconfirmedBalance, + 'unconfirmedBalanceSat': this.unconfirmedBalanceSat, + 'unconfirmedTxApperances': this.unconfirmedTxApperances, + 'txApperances': this.txApperances, + 'transactions': this.transactions }; }; @@ -103,7 +103,8 @@ Address.prototype._addTxItem = function(txItem, txList, includeInfo) { } }; - var add=0, addSpend=0; + var add = 0, + addSpend = 0; var v = txItem.value_sat; var seen = this.seen; @@ -112,35 +113,38 @@ Address.prototype._addTxItem = function(txItem, txList, includeInfo) { seen[txItem.txid] = 1; add = 1; - addTx({ txid: txItem.txid, ts: txItem.ts }); + addTx({ + txid: txItem.txid, + ts: txItem.ts + }); } // Spent tx - if (txItem.spentTxId && !seen[txItem.spentTxId] ) { - addTx({ txid: txItem.spentTxId, ts: txItem.spentTs }); - seen[txItem.spentTxId]=1; - addSpend=1; + if (txItem.spentTxId && !seen[txItem.spentTxId]) { + addTx({ + txid: txItem.spentTxId, + ts: txItem.spentTs + }); + seen[txItem.spentTxId] = 1; + addSpend = 1; } if (txItem.isConfirmed) { this.txApperances += add; this.totalReceivedSat += v; - if (! txItem.spentTxId ) { + if (!txItem.spentTxId) { //unspent - this.balanceSat += v; - } - else if(!txItem.spentIsConfirmed) { + this.balanceSat += v; + } else if (!txItem.spentIsConfirmed) { // unspent - this.balanceSat += v; + this.balanceSat += v; this.unconfirmedBalanceSat -= v; this.unconfirmedTxApperances += addSpend; - } - else { + } else { // spent this.totalSentSat += v; this.txApperances += addSpend; } - } - else { + } else { this.unconfirmedBalanceSat += v; this.unconfirmedTxApperances += add; } @@ -156,29 +160,29 @@ Address.prototype.update = function(next, opts) { if (!self.addrStr) return next(); opts = opts || {}; - if (! ('ignoreCache' in opts) ) + if (!('ignoreCache' in opts)) opts.ignoreCache = config.ignoreCache; // should collect txList from address? - var txList = opts.txLimit === 0 ? null: []; + var txList = opts.txLimit === 0 ? null : []; - var tDb = TransactionDb; - var bDb = BlockDb; - tDb.fromAddr(self.addrStr, opts, function(err,txOut){ + var tDb = TransactionDb; + var bDb = BlockDb; + tDb.fromAddr(self.addrStr, opts, function(err, txOut) { if (err) return next(err); bDb.fillConfirmations(txOut, function(err) { if (err) return next(err); tDb.cacheConfirmations(txOut, function(err) { -// console.log('[Address.js.161:txOut:]',txOut); //TODO + // console.log('[Address.js.161:txOut:]',txOut); //TODO if (err) return next(err); if (opts.onlyUnspent) { - txOut = txOut.filter(function(x){ + txOut = txOut.filter(function(x) { return !x.spentTxId; }); tDb.fillScriptPubKey(txOut, function() { - self.unspent = txOut.map(function(x){ + self.unspent = txOut.map(function(x) { return { address: self.addrStr, txid: x.txid, @@ -192,12 +196,11 @@ Address.prototype.update = function(next, opts) { }); return next(); }); - } - else { - txOut.forEach(function(txItem){ + } else { + txOut.forEach(function(txItem) { self._addTxItem(txItem, txList, opts.includeTxInfo); }); - if (txList) + if (txList) self.transactions = txList; return next(); @@ -208,4 +211,3 @@ Address.prototype.update = function(next, opts) { }; module.exports = require('soop')(Address); - diff --git a/config/express.js b/config/express.js index 8de62c8..737958b 100644 --- a/config/express.js +++ b/config/express.js @@ -26,8 +26,8 @@ module.exports = function(app, historicSync, peerSync) { app.set('json spaces', 0); app.enable('jsonp callback'); - app.use(config.apiPrefix + '/sync', setHistoric); - app.use(config.apiPrefix + '/peer', setPeer); + app.use(config.apiPrefix, setHistoric); + app.use(config.apiPrefix, setPeer); app.use(express.logger('dev')); app.use(express.json()); app.use(express.urlencoded()); diff --git a/insight.js b/insight.js index 0e6fba5..52d6739 100755 --- a/insight.js +++ b/insight.js @@ -131,18 +131,6 @@ if (config.enableRatelimiter) { require('./plugins/ratelimiter').init(expressApp, config.ratelimiter); } -if (config.enableMailbox) { - require('./plugins/mailbox').init(ios, config.mailbox); -} - -if (config.enableCleaner) { - require('./plugins/cleaner').init(config.cleaner); -} - -if (config.enableMonitor) { - require('./plugins/monitor').init(config.monitor); -} - if (config.enableEmailstore) { require('./plugins/emailstore').init(config.emailstore); }