Database indexing: Full Address history, fix balances, add db file locks
This commit is contained in:
+198
-115
@@ -9,6 +9,7 @@ var mongoose = require('mongoose')
|
||||
, Heavy = require('../models/heavy')
|
||||
, lib = require('./explorer')
|
||||
, settings = require('./settings')
|
||||
, fs = require('fs')
|
||||
, poloniex = require('./markets/poloniex')
|
||||
, bittrex = require('./markets/bittrex')
|
||||
, bleutrade = require('./markets/bleutrade')
|
||||
@@ -39,6 +40,16 @@ function find_address(hash, caseSensitive, cb) {
|
||||
}
|
||||
}
|
||||
|
||||
function find_address_tx(address, hash, cb) {
|
||||
AddressTx.findOne({a_id: address, txid: hash}, function(err, address_tx) {
|
||||
if(address_tx) {
|
||||
return cb(address_tx);
|
||||
} else {
|
||||
return cb();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function find_richlist(coin, cb) {
|
||||
Richlist.findOne({coin: coin}, function(err, richlist) {
|
||||
if(richlist) {
|
||||
@@ -62,41 +73,38 @@ function update_address(hash, txid, amount, type, cb) {
|
||||
return cb();
|
||||
});
|
||||
} else {
|
||||
//Considering no duplicate
|
||||
var tx_array = [];
|
||||
var received = address.received;
|
||||
var sent = address.sent;
|
||||
if (type == 'vin') {
|
||||
sent = sent + amount;
|
||||
} else {
|
||||
received = received + amount;
|
||||
var received = address.received;
|
||||
var sent = address.sent;
|
||||
if (type == 'vin') {
|
||||
sent = sent + amount;
|
||||
} else {
|
||||
received = received + amount;
|
||||
}
|
||||
Address.updateOne({a_id:hash}, {
|
||||
received: received,
|
||||
sent: sent,
|
||||
balance: received - sent
|
||||
}, function() {
|
||||
// ensure tx doesnt already exist in address.txs
|
||||
find_address_tx(hash, txid, function(address_tx) {
|
||||
if (typeof address_tx == "undefined") {
|
||||
var newAddressTx = new AddressTx({
|
||||
a_id: hash,
|
||||
txid: txid
|
||||
});
|
||||
newAddressTx.save(function(err) {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
} else {
|
||||
return cb();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return cb(); //duplicate
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
tx_array.push({addresses: txid, type: type});
|
||||
|
||||
Address.updateOne({a_id:hash}, {
|
||||
received: received,
|
||||
sent: sent,
|
||||
balance: received - sent
|
||||
}, function() {
|
||||
|
||||
var newAddressTx = new AddressTx({
|
||||
a_id: hash,
|
||||
addresses: txid,
|
||||
type: type
|
||||
});
|
||||
newAddressTx.save(function(err) {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
} else {
|
||||
//console.log('address saved: %s', hash);
|
||||
//console.log(newAddress);
|
||||
return cb();
|
||||
}
|
||||
});
|
||||
return cb();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
//new address
|
||||
if (type == 'vin') {
|
||||
@@ -117,24 +125,17 @@ function update_address(hash, txid, amount, type, cb) {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
} else {
|
||||
//console.log('address saved: %s', hash);
|
||||
//console.log(newAddress);
|
||||
|
||||
var newAddressTx = new AddressTx({
|
||||
a_id: hash,
|
||||
addresses: txid,
|
||||
type: type
|
||||
txid: txid
|
||||
});
|
||||
newAddressTx.save(function(err) {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
} else {
|
||||
//console.log('address saved: %s', hash);
|
||||
//console.log(newAddress);
|
||||
return cb();
|
||||
}
|
||||
});
|
||||
return cb();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -255,6 +256,53 @@ function get_market_data(market, cb) {
|
||||
}
|
||||
}
|
||||
|
||||
function create_lock(lockfile, cb) {
|
||||
if (settings.lock_during_index == true) {
|
||||
var fname = './tmp/' + lockfile + '.pid';
|
||||
fs.appendFile(fname, process.pid, function (err) {
|
||||
if (err) {
|
||||
console.log("Error: unable to create %s", fname);
|
||||
process.exit(1);
|
||||
} else {
|
||||
return cb();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return cb();
|
||||
}
|
||||
}
|
||||
|
||||
function remove_lock(lockfile, cb) {
|
||||
if (settings.lock_during_index == true) {
|
||||
var fname = './tmp/' + lockfile + '.pid';
|
||||
fs.unlink(fname, function (err){
|
||||
if(err) {
|
||||
console.log("unable to remove lock: %s", fname);
|
||||
process.exit(1);
|
||||
} else {
|
||||
return cb();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return cb();
|
||||
}
|
||||
}
|
||||
|
||||
function is_locked(lockfile, cb) {
|
||||
if (settings.lock_during_index == true) {
|
||||
var fname = './tmp/' + lockfile + '.pid';
|
||||
fs.exists(fname, function (exists){
|
||||
if(exists) {
|
||||
return cb(true);
|
||||
} else {
|
||||
return cb(false);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return cb(false);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
// initialize DB
|
||||
connect: function(database, cb) {
|
||||
@@ -270,6 +318,16 @@ module.exports = {
|
||||
});
|
||||
},
|
||||
|
||||
is_locked: function(cb) {
|
||||
is_locked("db_index", function (exists) {
|
||||
if (exists) {
|
||||
return cb(true);
|
||||
} else {
|
||||
return cb(false);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
check_stats: function(coin, cb) {
|
||||
Stats.findOne({coin: coin}, function(err, stats) {
|
||||
if(stats) {
|
||||
@@ -380,29 +438,43 @@ module.exports = {
|
||||
},
|
||||
|
||||
create_tx: function(txid, cb) {
|
||||
save_tx(txid, function(err){
|
||||
if (err) {
|
||||
return cb(err);
|
||||
} else {
|
||||
//console.log('tx stored: %s', txid);
|
||||
is_locked("db_index", function (exists) {
|
||||
if (exists) {
|
||||
console.log("db_index lock file exists...");
|
||||
return cb();
|
||||
} else {
|
||||
save_tx(txid, function(err){
|
||||
if (err) {
|
||||
return cb(err);
|
||||
} else {
|
||||
//console.log('tx stored: %s', txid);
|
||||
return cb();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
create_txs: function(block, cb) {
|
||||
lib.syncLoop(block.tx.length, function (loop) {
|
||||
var i = loop.iteration();
|
||||
save_tx(block.tx[i], function(err){
|
||||
if (err) {
|
||||
loop.next();
|
||||
} else {
|
||||
//console.log('tx stored: %s', block.tx[i]);
|
||||
loop.next();
|
||||
}
|
||||
});
|
||||
}, function(){
|
||||
return cb();
|
||||
is_locked("db_index", function (exists) {
|
||||
if (exists) {
|
||||
console.log("db_index lock file exists...");
|
||||
return cb();
|
||||
} else {
|
||||
lib.syncLoop(block.tx.length, function (loop) {
|
||||
var i = loop.iteration();
|
||||
save_tx(block.tx[i], function(err){
|
||||
if (err) {
|
||||
loop.next();
|
||||
} else {
|
||||
//console.log('tx stored: %s', block.tx[i]);
|
||||
loop.next();
|
||||
}
|
||||
});
|
||||
}, function(){
|
||||
return cb();
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@@ -432,7 +504,6 @@ module.exports = {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
} else {
|
||||
//console.log(address);
|
||||
var txs = [];
|
||||
var count = address.length;
|
||||
var hashes = address;
|
||||
@@ -441,13 +512,15 @@ module.exports = {
|
||||
|
||||
lib.syncLoop(count, function (loop) {
|
||||
var i = loop.iteration();
|
||||
find_tx(hashes[i].addresses, function (tx) {
|
||||
if (tx) {
|
||||
find_tx(hashes[i].txid, function (tx) {
|
||||
if (tx && !txs.includes(tx)) {
|
||||
txs.push(tx);
|
||||
loop.next();
|
||||
} else {
|
||||
} else if (!txs.includes(tx)) {
|
||||
txs.push("1. Not found");
|
||||
loop.next();
|
||||
} else {
|
||||
loop.next();
|
||||
}
|
||||
})
|
||||
}, function () {
|
||||
@@ -738,65 +811,75 @@ module.exports = {
|
||||
|
||||
// updates tx, address & richlist db's; called by sync.js
|
||||
update_tx_db: function(coin, start, end, timeout, cb) {
|
||||
var complete = false;
|
||||
if (start < 1) start = 1; // fix for invalid block height (skip genesis block as it should not have valid txs)
|
||||
lib.syncLoop((end - start) + 1, function (loop) {
|
||||
var x = loop.iteration();
|
||||
if (x % 5000 === 0) {
|
||||
Tx.find({}).where('blockindex').lt(start + x).sort({timestamp: 'desc'}).limit(settings.index.last_txs).exec(function(err, txs){
|
||||
Stats.updateOne({coin: coin}, {
|
||||
last: start + x - 1,
|
||||
last_txs: '' //not used anymore left to clear out existing objects
|
||||
}, function() {});
|
||||
});
|
||||
}
|
||||
lib.get_blockhash(start + x, function(blockhash){
|
||||
if (blockhash) {
|
||||
lib.get_block(blockhash, function(block) {
|
||||
if (block) {
|
||||
lib.syncLoop(block.tx.length, function (subloop) {
|
||||
var i = subloop.iteration();
|
||||
Tx.findOne({txid: block.tx[i]}, function(err, tx) {
|
||||
if(tx) {
|
||||
tx = null;
|
||||
subloop.next();
|
||||
} else {
|
||||
save_tx(block.tx[i], function(err){
|
||||
if (err) {
|
||||
console.log(err);
|
||||
} else {
|
||||
console.log('%s: %s', block.height, block.tx[i]);
|
||||
}
|
||||
setTimeout( function(){
|
||||
tx = null;
|
||||
subloop.next();
|
||||
}, timeout);
|
||||
is_locked("db_index", function (exists) {
|
||||
if (exists) {
|
||||
console.log("db_index lock file exists...");
|
||||
return cb();
|
||||
} else {
|
||||
create_lock("db_index", function (){
|
||||
var complete = false;
|
||||
lib.syncLoop((end - start) + 1, function (loop) {
|
||||
var x = loop.iteration();
|
||||
if (x % 5000 === 0) {
|
||||
Tx.find({}).where('blockindex').lt(start + x).sort({timestamp: 'desc'}).limit(settings.index.last_txs).exec(function(err, txs){
|
||||
Stats.updateOne({coin: coin}, {
|
||||
last: start + x - 1,
|
||||
last_txs: '' //not used anymore left to clear out existing objects
|
||||
}, function() {});
|
||||
});
|
||||
}
|
||||
lib.get_blockhash(start + x, function(blockhash){
|
||||
if (blockhash) {
|
||||
lib.get_block(blockhash, function(block) {
|
||||
if (block) {
|
||||
lib.syncLoop(block.tx.length, function (subloop) {
|
||||
var i = subloop.iteration();
|
||||
Tx.findOne({txid: block.tx[i]}, function(err, tx) {
|
||||
if(tx) {
|
||||
tx = null;
|
||||
subloop.next();
|
||||
} else {
|
||||
save_tx(block.tx[i], function(err){
|
||||
if (err) {
|
||||
console.log(err);
|
||||
} else {
|
||||
console.log('%s: %s', block.height, block.tx[i]);
|
||||
}
|
||||
setTimeout( function(){
|
||||
tx = null;
|
||||
subloop.next();
|
||||
}, timeout);
|
||||
});
|
||||
}
|
||||
});
|
||||
}, function(){
|
||||
blockhash = null;
|
||||
block = null;
|
||||
loop.next();
|
||||
});
|
||||
} else {
|
||||
console.log('block not found: %s', blockhash);
|
||||
loop.next();
|
||||
}
|
||||
});
|
||||
}, function(){
|
||||
blockhash = null;
|
||||
block = null;
|
||||
} else {
|
||||
loop.next();
|
||||
}
|
||||
});
|
||||
}, function(){
|
||||
Tx.find({}).sort({timestamp: 'desc'}).limit(settings.index.last_txs).exec(function(err, txs){
|
||||
Stats.update({coin: coin}, {
|
||||
last: end,
|
||||
last_txs: '' //not used anymore left to clear out existing objects
|
||||
}, function() {
|
||||
remove_lock("db_index", function(){
|
||||
return cb();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
console.log('block not found: %s', blockhash);
|
||||
loop.next();
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
loop.next();
|
||||
}
|
||||
});
|
||||
}, function(){
|
||||
Tx.find({}).sort({timestamp: 'desc'}).limit(settings.index.last_txs).exec(function(err, txs){
|
||||
Stats.updateOne({coin: coin}, {
|
||||
last: end,
|
||||
last_txs: '' //not used anymore left to clear out existing objects
|
||||
}, function() {
|
||||
return cb();
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user