Browse Source

store cached data in db

activeAddress
Ivan Socolsky 9 years ago
parent
commit
94a376ca33
  1. 22
      lib/server.js
  2. 36
      lib/storage.js
  3. 39
      test/integration/helpers.js
  4. 108
      test/integration/server.js

22
lib/server.js

@ -992,8 +992,6 @@ WalletService.prototype._getBalanceFromAddresses = function(addresses, cb) {
}); });
}; };
var prioritaryAddresses;
/** /**
* Get wallet balance. * Get wallet balance.
* @param {Object} opts * @param {Object} opts
@ -1009,13 +1007,17 @@ WalletService.prototype.getBalance = function(opts, cb) {
// Update cache // Update cache
var addressIndex = _.indexBy(addresses, 'address'); var addressIndex = _.indexBy(addresses, 'address');
prioritaryAddresses = _.map(_.pluck(balance.byAddress, 'address'), function(addrStr) { var freshAddresses = _.map(_.pluck(balance.byAddress, 'address'), function(addrStr) {
return addressIndex[addrStr]; return addressIndex[addrStr];
}); });
self.storage.storeCacheData(self.walletId, 'freshAddresses', freshAddresses, function(err) {
if (err) {
log.warn('Could not update wallet cache', err);
}
return cb(null, balance); return cb(null, balance);
}); });
}); });
});
}; };
@ -1027,21 +1029,25 @@ WalletService.prototype.getBalance = function(opts, cb) {
WalletService.prototype.getBalance2Steps = function(opts, cb) { WalletService.prototype.getBalance2Steps = function(opts, cb) {
var self = this; var self = this;
if (!prioritaryAddresses) return self.getBalance(opts, cb); self.storage.fetchCacheData(self.walletId, 'freshAddresses', function(err, freshAddresses) {
if (err || _.isEmpty(freshAddresses)) {
self._getBalanceFromAddresses(prioritaryAddresses, function(err, partialBalance) { return self.getBalance(opts, cb);
} else {
self._getBalanceFromAddresses(freshAddresses, function(err, partialBalance) {
if (err) return cb(err); if (err) return cb(err);
cb(null, partialBalance); cb(null, partialBalance);
setTimeout(function() { setTimeout(function() {
self.getBalance(opts, function(err, fullBalance) { self.getBalance(opts, function(err, fullBalance) {
if (err) return; if (err) return;
if (!_.isEqual(partialBalance, fullBalance)) { if (!_.isEqual(partialBalance, fullBalance)) {
console.log('*** [server.js ln1015] ACTUALIZAR BALANCE!!!!, partialBalance, fullBalance:', partialBalance, fullBalance); // TODO self._notify('BalanceUpdated', fullBalance);
} }
}); });
}, 1); }, 1);
return; return;
}); });
}
});
}; };

36
lib/storage.js

@ -20,6 +20,7 @@ var collections = {
COPAYERS_LOOKUP: 'copayers_lookup', COPAYERS_LOOKUP: 'copayers_lookup',
PREFERENCES: 'preferences', PREFERENCES: 'preferences',
EMAIL_QUEUE: 'email_queue', EMAIL_QUEUE: 'email_queue',
CACHE: 'cache',
}; };
var Storage = function(opts) { var Storage = function(opts) {
@ -56,6 +57,10 @@ Storage.prototype._createIndexes = function() {
this.db.collection(collections.EMAIL_QUEUE).createIndex({ this.db.collection(collections.EMAIL_QUEUE).createIndex({
notificationId: 1, notificationId: 1,
}); });
this.db.collection(collections.CACHE).createIndex({
walletId: 1,
key: 1,
});
}; };
Storage.prototype.connect = function(opts, cb) { Storage.prototype.connect = function(opts, cb) {
@ -501,6 +506,37 @@ Storage.prototype.fetchEmailByNotification = function(notificationId, cb) {
}); });
}; };
Storage.prototype.storeCacheData = function(walletId, key, value, cb) {
var self = this;
var record = {
walletId: walletId,
key: key,
data: value
};
self.db.collection(collections.CACHE).update({
walletId: walletId,
key: key,
}, record, {
w: 1,
upsert: true,
}, cb);
};
Storage.prototype.fetchCacheData = function(walletId, key, cb) {
var self = this;
self.db.collection(collections.CACHE).findOne({
walletId: walletId,
key: key,
}, function(err, result) {
if (err) return cb(err);
if (!result) return cb();
return cb(null, result.data);
});
};
Storage.prototype._dump = function(cb, fn) { Storage.prototype._dump = function(cb, fn) {
fn = fn || console.log; fn = fn || console.log;
cb = cb || function() {}; cb = cb || function() {};

39
test/integration/helpers.js

@ -211,12 +211,26 @@ helpers.toSatoshi = function(btc) {
} }
}; };
helpers.stubUtxos = function(server, wallet, amounts, cb) { helpers.stubUtxos = function(server, wallet, amounts, opts, cb) {
if (_.isFunction(opts)) {
cb = opts;
opts = {};
}
opts = opts || {};
if (!helpers._utxos) helpers._utxos = {};
async.waterfall([
function(next) {
if (opts.addresses) return next(null, [].concat(opts.addresses));
async.mapSeries(_.range(0, amounts.length > 2 ? 2 : 1), function(i, next) { async.mapSeries(_.range(0, amounts.length > 2 ? 2 : 1), function(i, next) {
server.createAddress({}, next); server.createAddress({}, next);
}, function(err, addresses) { }, next);
should.not.exist(err); },
function(addresses, next) {
addresses.should.not.be.empty; addresses.should.not.be.empty;
var utxos = _.compact(_.map([].concat(amounts), function(amount, i) { var utxos = _.compact(_.map([].concat(amounts), function(amount, i) {
var confirmations; var confirmations;
if (_.isString(amount) && _.startsWith(amount, 'u')) { if (_.isString(amount) && _.startsWith(amount, 'u')) {
@ -249,14 +263,25 @@ helpers.stubUtxos = function(server, wallet, amounts, cb) {
confirmations: confirmations confirmations: confirmations
}; };
})); }));
if (opts.keepUtxos) {
helpers._utxos = helpers._utxos.concat(utxos);
} else {
helpers._utxos = utxos;
}
blockchainExplorer.getUnspentUtxos = function(addresses, cb) { blockchainExplorer.getUnspentUtxos = function(addresses, cb) {
var selected = _.filter(utxos, function(utxo) { var selected = _.filter(helpers._utxos, function(utxo) {
return _.contains(addresses, utxo.address); return _.contains(addresses, utxo.address);
}); });
return cb(null, selected); return cb(null, selected);
}; };
return cb(utxos); return next();
},
], function(err) {
should.not.exist(err);
return cb(helpers._utxos);
}); });
}; };
@ -451,14 +476,14 @@ helpers.createProposalOpts = function(type, outputs, signingKey, moreOpts, input
}; };
helpers.createAddresses = function(server, wallet, main, change, cb) { helpers.createAddresses = function(server, wallet, main, change, cb) {
var clock = sinon.useFakeTimers(Date.now(), 'Date'); var clock = sinon.useFakeTimers(Date.now(), 'Date');
async.map(_.range(main + change), function(i, next) { async.mapSeries(_.range(main + change), function(i, next) {
clock.tick(1000); clock.tick(1000);
var address = wallet.createAddress(i >= main); var address = wallet.createAddress(i >= main);
server.storage.storeAddressAndWallet(wallet, address, function(err) { server.storage.storeAddressAndWallet(wallet, address, function(err) {
next(err, address); next(err, address);
}); });
}, function(err, addresses) { }, function(err, addresses) {
if (err) throw new Error('Could not generate addresses'); should.not.exist(err);
clock.restore(); clock.restore();
return cb(_.take(addresses, main), _.takeRight(addresses, change)); return cb(_.take(addresses, main), _.takeRight(addresses, change));
}); });

108
test/integration/server.js

@ -1504,7 +1504,7 @@ describe('Wallet service', function() {
}); });
}); });
describe('#getBalance 2 steps', function() { describe.only('#getBalance 2 steps', function() {
var server, wallet; var server, wallet;
beforeEach(function(done) { beforeEach(function(done) {
helpers.createAndJoinWallet(1, 1, function(s, w) { helpers.createAndJoinWallet(1, 1, function(s, w) {
@ -1536,22 +1536,118 @@ describe('Wallet service', function() {
}); });
}); });
}); });
it.only('should trigger notification when balance of non-prioritary addresses is updated', function(done) {
helpers.stubUtxos(server, wallet, [1, 2], function() { it('should trigger notification when balance of non-prioritary addresses is updated', function(done) {
var addresses;
async.series([
function(next) {
helpers.createAddresses(server, wallet, 4, 0, function(addrs) {
addresses = addrs;
helpers.stubUtxos(server, wallet, [1, 2], {
addresses: _.take(addresses, 2),
}, function() {
next();
});
});
},
function(next) {
server.getBalance2Steps({}, function(err, balance) { server.getBalance2Steps({}, function(err, balance) {
should.not.exist(err); should.not.exist(err);
should.exist(balance); should.exist(balance);
balance.totalAmount.should.equal(helpers.toSatoshi(3)); balance.totalAmount.should.equal(helpers.toSatoshi(3));
next();
});
},
function(next) {
helpers.stubUtxos(server, wallet, 0.5, {
addresses: addresses[2],
keepUtxos: true,
}, function() {
next();
});
},
function(next) {
server.getBalance2Steps({}, function(err, balance) {
should.not.exist(err);
should.exist(balance);
balance.totalAmount.should.equal(helpers.toSatoshi(3));
next();
});
},
function(next) {
setTimeout(next, 100);
},
function(next) {
server.getNotifications({}, function(err, notifications) {
should.not.exist(err);
var last = _.last(notifications);
last.type.should.equal('BalanceUpdated');
var balance = last.data;
balance.totalAmount.should.equal(helpers.toSatoshi(3.5));
next();
});
},
], function(err) {
should.not.exist(err);
done();
});
});
helpers.stubUtxos(server, wallet, [0.5, 0.6], function() { it('should not trigger notification when only balance of prioritary addresses is updated', function(done) {
var addresses;
async.series([
function(next) {
helpers.createAddresses(server, wallet, 4, 0, function(addrs) {
addresses = addrs;
helpers.stubUtxos(server, wallet, [1, 2], {
addresses: _.take(addresses, 2),
}, function() {
next();
});
});
},
function(next) {
server.getBalance2Steps({}, function(err, balance) { server.getBalance2Steps({}, function(err, balance) {
should.not.exist(err); should.not.exist(err);
should.exist(balance); should.exist(balance);
//balance.totalAmount.should.equal(helpers.toSatoshi(1.1)); balance.totalAmount.should.equal(helpers.toSatoshi(3));
//done(); next();
});
},
function(next) {
helpers.stubUtxos(server, wallet, 0.5, {
addresses: addresses[0],
keepUtxos: true,
}, function() {
next();
}); });
},
function(next) {
server.getBalance2Steps({}, function(err, balance) {
should.not.exist(err);
should.exist(balance);
balance.totalAmount.should.equal(helpers.toSatoshi(3.5));
next();
}); });
},
function(next) {
setTimeout(next, 100);
},
function(next) {
server.getNotifications({}, function(err, notifications) {
should.not.exist(err);
var last = _.last(notifications);
last.type.should.not.equal('BalanceUpdated');
next();
}); });
},
], function(err) {
should.not.exist(err);
done();
}); });
}); });
}); });

Loading…
Cancel
Save