Database indexing: Full Address history, fix balances, add db file locks

This commit is contained in:
joeuhren
2020-11-20 16:28:28 -07:00
parent a7f29d5d81
commit 42e1964ab3
18 changed files with 305 additions and 200 deletions
+198 -115
View File
@@ -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();
});
});
}
});
},