Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

redlock

Package Overview
Dependencies
Maintainers
1
Versions
27
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

redlock - npm Package Compare versions

Comparing version 1.0.1 to 2.0.0

2

package.json
{
"name": "redlock",
"version": "1.0.1",
"version": "2.0.0",
"description": "A node.js redlock implementation for distributed redis locks",

@@ -5,0 +5,0 @@ "main": "redlock.js",

@@ -93,3 +93,8 @@ [![npm version](https://badge.fury.io/js/redlock.svg)](https://www.npmjs.com/package/redlock)

// unlock your resource when you are done
return lock.unlock();
return lock.unlock()
.catch(function(err) {
// we weren't able to reach redis; your lock will eventually
// expire, but you probably want to log this error
console.error(err);
});
});

@@ -114,3 +119,8 @@

// unlock your resource when you are done
return lock.unlock();
return lock.unlock()
.catch(function(err) {
// we weren't able to reach redis; your lock will eventually
// expire, but you probably want to log this error
console.error(err);
});
});

@@ -139,4 +149,12 @@ });

using(redlock.disposer(resource, ttl), function(lock) {
// if we weren't able to reach redis, your lock will eventually
// expire, but you probably want to do something like log that
// an error occurred; if you don't pass a handler, this error
// will be ignored
function unlockErrorHandler(err) {
console.error(err);
}
using(redlock.disposer(resource, ttl, unlockErrorHandler), function(lock) {
// ...do something here...

@@ -152,3 +170,3 @@

```js
using(redlock.disposer('locks:account:322456', 1000), function(lock) {
using(redlock.disposer('locks:account:322456', 1000, unlockErrorHandler), function(lock) {

@@ -204,3 +222,7 @@ // ...do something here...

// unlock your resource when you are done
lock.unlock();
lock.unlock(function(err) {
// we weren't able to reach redis; your lock will eventually
// expire, but you probably want to log this error
console.error(err);
});
}

@@ -253,3 +275,3 @@ });

###`Redlock.lock(resource, ttl, callback)`
###`Redlock.lock(resource, ttl, ?callback)`
- `resource (string)` resource to be locked

@@ -262,8 +284,9 @@ - `ttl (number)` time in ms until the lock expires

###`Redlock.unlock(lock, callback)`
###`Redlock.unlock(lock, ?callback)`
- `lock (Lock)` lock to be released
- `callback (function)` callback with no returning arguments
- `callback (function)` callback returning:
- `err (Error)`
###`Redlock.extend(lock, ttl, callback)`
###`Redlock.extend(lock, ttl, ?callback)`
- `lock (Lock)` lock to be extended

@@ -276,7 +299,15 @@ - `ttl (number)` time in ms to extend the lock's expiration

###`Lock.unlock(callback)`
- `callback (function)` callback with no returning arguments
###`Redlock.disposer(resource, ttl, ?unlockErrorHandler)`
- `resource (string)` resource to be locked
- `ttl (number)` time in ms to extend the lock's expiration
- `callback (function)` error handler called with:
- `err (Error)`
###`Lock.extend(ttl, callback)`
###`Lock.unlock(?callback)`
- `callback (function)` callback returning:
- `err (Error)`
###`Lock.extend(ttl, ?callback)`
- `ttl (number)` time in ms to extend the lock's expiration

@@ -283,0 +314,0 @@ - `callback (function)` callback returning:

@@ -130,4 +130,7 @@ 'use strict';

// ```
Redlock.prototype.disposer = function disposer(resource, ttl) {
return this._lock(resource, null, ttl).disposer(function(lock){ return lock.unlock(); });
Redlock.prototype.disposer = function disposer(resource, ttl, errorHandler) {
errorHandler = errorHandler || function(err) {};
return this._lock(resource, null, ttl).disposer(function(lock){
return lock.unlock().catch(errorHandler);
});
};

@@ -138,4 +141,6 @@

// ------
// This method unlocks the provided lock from all servers still persisting it. This is a
// best-effort attempt and as such fails silently.
// This method unlocks the provided lock from all servers still persisting it. It will fail
// with an error if it is unable to release the lock on a quorum of nodes, but will make no
// attempt to restore the lock on nodes that failed to release. It is safe to re-attempt an
// unlock or to ignore the error, as the lock will automatically expire after its timeout.
Redlock.prototype.release =

@@ -146,10 +151,11 @@ Redlock.prototype.unlock = function unlock(lock, callback) {

// the lock has expired
if(lock.expiration < Date.now()) {
return resolve();
}
// invalidate the lock
lock.expiration = 0;
// the number of servers which have agreed to release this lock
var votes = 0;
// the number of votes needed for consensus
var quorum = Math.floor(self.servers.length / 2) + 1;
// the number of async redis calls still waiting to finish

@@ -165,4 +171,19 @@ var waiting = self.servers.length;

if(err) self.emit('clientError', err);
// - if the lock was released by this call, it will return 1
// - if the lock has already been released, it will return 0
// - it may have been re-acquired by another process
// - it may hava already been manually released
// - it may have expired
if(typeof response === 'number' && (response === 0 || response === 1))
votes++;
if(waiting-- > 1) return;
return resolve();
// SUCCESS: there is concensus and the lock is released
if(votes >= quorum)
return resolve();
// FAILURE: the lock could not be released
return reject(new LockError('Unable to fully release the lock on resource "' + lock.resource + '".'));
}

@@ -169,0 +190,0 @@ })

@@ -40,8 +40,13 @@ 'use strict';

it('emits a clientError event when a client error occurs', function(done){
redlock.once('clientError', function(err) {
var emitted = 0;
function test(err) {
assert.isNotNull(err);
done();
});
emitted++;
}
redlock.on('clientError', test);
redlock.lock(error, 200, function(err, lock){
redlock.removeListener('clientError', test);
assert.isNotNull(err);
assert.equal(emitted, 3);
done();
});

@@ -90,3 +95,3 @@ });

it('should silently fail to unlock an already-unlocked resource', function(done) {
it('should unlock an already-unlocked resource', function(done) {
assert(two, 'Could not run because a required previous test failed.');

@@ -96,2 +101,12 @@ two.unlock(done);

it('should error when unable to fully release a resource', function(done) {
assert(two, 'Could not run because a required previous test failed.');
var failingTwo = Object.create(two);
failingTwo.resource = error;
failingTwo.unlock(function(err) {
assert.isNotNull(err);
done();
});
});
it('should fail to extend a lock on an already-unlocked resource', function(done) {

@@ -212,3 +227,3 @@ assert(two, 'Could not run because a required previous test failed.');

it('should silently fail to unlock an already-unlocked resource', function(done) {
it('should unlock an already-unlocked resource', function(done) {
assert(two, 'Could not run because a required previous test failed.');

@@ -218,2 +233,12 @@ two.unlock().done(done, done);

it('should error when unable to fully release a resource', function(done) {
assert(two, 'Could not run because a required previous test failed.');
var failingTwo = Object.create(two);
failingTwo.resource = error;
failingTwo.unlock().done(done, function(err) {
assert.isNotNull(err);
done();
});
});
it('should fail to extend a lock on an already-unlocked resource', function(done) {

@@ -329,2 +354,21 @@ assert(two, 'Could not run because a required previous test failed.');

it('should call unlockErrorHandler when unable to fully release a resource', function(done) {
assert(two, 'Could not run because a required previous test failed.');
var errs = 0;
var lock;
Promise.using(
redlock.disposer(resource, 800, function(err) {
errs++;
}),
function(l){
lock = l;
lock.resource = error;
}
).done(function() {
assert.equal(errs, 1);
lock.resource = resource;
lock.unlock().done(done, done);
}, done);
});
var three_original, three_extended;

@@ -331,0 +375,0 @@ var three_original_expiration;

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc