From 0631083baeefc1d092011a67738056d3ed847c5a Mon Sep 17 00:00:00 2001 From: Ivan Socolsky Date: Tue, 7 Apr 2015 17:02:08 -0300 Subject: [PATCH] common interface for locks --- lib/locallock.js | 34 +++++++++++++++++++++++++++++ lib/lock.js | 40 +++++++++++----------------------- lib/server.js | 21 ++++++++++-------- lib/utils.js | 16 -------------- test/{lock.js => locallock.js} | 4 ++-- 5 files changed, 61 insertions(+), 54 deletions(-) create mode 100644 lib/locallock.js rename test/{lock.js => locallock.js} (93%) diff --git a/lib/locallock.js b/lib/locallock.js new file mode 100644 index 0000000..6ca71a4 --- /dev/null +++ b/lib/locallock.js @@ -0,0 +1,34 @@ +var _ = require('lodash'); +var $ = require('preconditions').singleton(); + +var locks = {}; + +var Lock = function() { + this.taken = false; + this.queue = []; +}; + +Lock.prototype.free = function() { + if (this.queue.length > 0) { + var f = this.queue.shift(); + f(this); + } else { + this.taken = false; + } +}; + +Lock.get = function(key, callback) { + if (_.isUndefined(locks[key])) { + locks[key] = new Lock(); + } + var lock = locks[key]; + + if (lock.taken) { + lock.queue.push(callback); + } else { + lock.taken = true; + callback(lock); + } +}; + +module.exports = Lock; diff --git a/lib/lock.js b/lib/lock.js index 6ca71a4..65e7259 100644 --- a/lib/lock.js +++ b/lib/lock.js @@ -1,34 +1,20 @@ -var _ = require('lodash'); var $ = require('preconditions').singleton(); +var _ = require('lodash'); +var LocalLock = require('./locallock'); +var RemoteLock = require('locker'); -var locks = {}; - -var Lock = function() { - this.taken = false; - this.queue = []; -}; - -Lock.prototype.free = function() { - if (this.queue.length > 0) { - var f = this.queue.shift(); - f(this); - } else { - this.taken = false; - } -}; +function Lock(opts) {}; -Lock.get = function(key, callback) { - if (_.isUndefined(locks[key])) { - locks[key] = new Lock(); - } - var lock = locks[key]; +Lock.prototype.runLocked = function(token, cb, task) { + $.shouldBeDefined(token); - if (lock.taken) { - lock.queue.push(callback); - } else { - lock.taken = true; - callback(lock); - } + LocalLock.get(token, function(lock) { + var _cb = function() { + cb.apply(null, arguments); + lock.free(); + }; + task(_cb); + }); }; module.exports = Lock; diff --git a/lib/server.js b/lib/server.js index 9f804b8..abf662a 100644 --- a/lib/server.js +++ b/lib/server.js @@ -13,6 +13,7 @@ var Address = Bitcore.Address; var ClientError = require('./clienterror'); var Utils = require('./utils'); +var Lock = require('./lock'); var Storage = require('./storage'); var NotificationBroadcaster = require('./notificationbroadcaster'); var BlockchainExplorer = require('./blockchainexplorer'); @@ -24,7 +25,7 @@ var TxProposal = require('./model/txproposal'); var Notification = require('./model/notification'); var initialized = false; -var storage, blockchainExplorer; +var lock, storage, blockchainExplorer; /** @@ -35,6 +36,7 @@ function WalletService() { if (!initialized) throw new Error('Server not initialized'); + this.lock = lock; this.storage = storage; this.blockchainExplorer = blockchainExplorer; this.notifyTicker = 0; @@ -52,7 +54,8 @@ WalletService.onNotification = function(func) { */ WalletService.initialize = function(opts) { opts = opts || {}; - storage = opts.storage ||  new Storage(opts.storageOpts); + lock = opts.lock || new Lock(opts.lockOpts); + storage = opts.storage || new Storage(opts.storageOpts); blockchainExplorer = opts.blockchainExplorer; initialized = true; }; @@ -190,7 +193,7 @@ WalletService.prototype.replaceTemporaryRequestKey = function(opts, cb) { if (opts.isTemporaryRequestKey) return cb(new ClientError('Bad arguments')); - Utils.runLocked(self.walletId, cb, function(cb) { + self.lock.runLocked(self.walletId, cb, function(cb) { self.storage.fetchWallet(self.walletId, function(err, wallet) { if (err) return cb(err); @@ -298,7 +301,7 @@ WalletService.prototype.joinWallet = function(opts, cb) { if (_.isEmpty(opts.name)) return cb(new ClientError('Invalid copayer name')); - Utils.runLocked(opts.walletId, cb, function(cb) { + self.lock.runLocked(opts.walletId, cb, function(cb) { self.storage.fetchWallet(opts.walletId, function(err, wallet) { if (err) return cb(err); @@ -357,7 +360,7 @@ WalletService.prototype.joinWallet = function(opts, cb) { WalletService.prototype.createAddress = function(opts, cb) { var self = this; - Utils.runLocked(self.walletId, cb, function(cb) { + self.lock.runLocked(self.walletId, cb, function(cb) { self.getWallet({}, function(err, wallet) { if (err) return cb(err); if (!wallet.isComplete()) @@ -612,7 +615,7 @@ WalletService.prototype.createTx = function(opts, cb) { if (!Utils.checkRequired(opts, ['toAddress', 'amount', 'proposalSignature'])) return cb(new ClientError('Required argument missing')); - Utils.runLocked(self.walletId, cb, function(cb) { + self.lock.runLocked(self.walletId, cb, function(cb) { self.getWallet({}, function(err, wallet) { if (err) return cb(err); if (!wallet.isComplete()) return cb(new ClientError('Wallet is not complete')); @@ -702,7 +705,7 @@ WalletService.prototype.getTx = function(opts, cb) { WalletService.prototype.removeWallet = function(opts, cb) { var self = this; - Utils.runLocked(self.walletId, cb, function(cb) { + self.lock.runLocked(self.walletId, cb, function(cb) { self.storage.removeWallet(self.walletId, cb); }); }; @@ -720,7 +723,7 @@ WalletService.prototype.removePendingTx = function(opts, cb) { if (!Utils.checkRequired(opts, ['txProposalId'])) return cb(new ClientError('Required argument missing')); - Utils.runLocked(self.walletId, cb, function(cb) { + self.lock.runLocked(self.walletId, cb, function(cb) { self.getTx({ txProposalId: opts.txProposalId, @@ -1178,7 +1181,7 @@ WalletService.prototype.scan = function(opts, cb) { }; - Utils.runLocked(self.walletId, cb, function(cb) { + self.lock.runLocked(self.walletId, cb, function(cb) { self.getWallet({}, function(err, wallet) { if (err) return cb(err); if (!wallet.isComplete()) return cb(new ClientError('Wallet is not complete')); diff --git a/lib/utils.js b/lib/utils.js index b39fb7a..aadc018 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,24 +1,8 @@ var $ = require('preconditions').singleton(); var _ = require('lodash'); -var Lock = require('./lock'); var Utils = {}; -Utils.runLocked = function(token, cb, task) { - var self = this; - - $.shouldBeDefined(token); - - Lock.get(token, function(lock) { - var _cb = function() { - cb.apply(null, arguments); - lock.free(); - }; - task(_cb); - }); -}; - - Utils.checkRequired = function(obj, args) { args = [].concat(args); if (!_.isObject(obj)) return false; diff --git a/test/lock.js b/test/locallock.js similarity index 93% rename from test/lock.js rename to test/locallock.js index 95ae2fe..ea98ecf 100644 --- a/test/lock.js +++ b/test/locallock.js @@ -4,9 +4,9 @@ var _ = require('lodash'); var chai = require('chai'); var sinon = require('sinon'); var should = chai.should(); -var Lock = require('../lib/lock'); +var Lock = require('../lib/locallock'); -describe('Lock', function() { +describe('Local lock', function() { it('should lock tasks using the same token', function(done) { var a = false, b = false;