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 4.1.0 to 4.2.0

docker-compose.yml

9

CHANGELOG.md

@@ -9,2 +9,9 @@ ## v4.0.0

- Update scripts for compatibility with LUA 5.2 (via [#63](https://github.com/mike-marcacci/node-redlock/pull/63)).
- Update scripts for compatibility with LUA 5.2 (via [#63](https://github.com/mike-marcacci/node-redlock/pull/63)).
### v4.2.0
- Update dependencies.
- Stop testing on node version 8. (Due to dev dependency requirements only.)
- Update docs (@ricmatsui via [#80](https://github.com/mike-marcacci/node-redlock/pull/80)).
- Use evalsha for scripts (@yosiat via [#77](https://github.com/mike-marcacci/node-redlock/pull/77)).

12

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

@@ -30,10 +30,10 @@ "main": "redlock.js",

"chai": "^4.2.0",
"coveralls": "^3.0.4",
"ioredis": "^4.10.0",
"coveralls": "^3.1.0",
"ioredis": "^4.18.0",
"istanbul": "^0.4.2",
"mocha": "^6.1.4",
"redis": "^2.7.1"
"mocha": "^8.1.3",
"redis": "^3.0.2"
},
"dependencies": {
"bluebird": "^3.3.3"
"bluebird": "^3.7.2"
},

@@ -40,0 +40,0 @@ "engines": {

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

// see http://redis.io/topics/distlock
driftFactor: 0.01, // time in ms
driftFactor: 0.01, // multiplied by lock ttl to determine drift time

@@ -72,0 +72,0 @@ // the max number of times Redlock will attempt

@@ -29,7 +29,7 @@ 'use strict';

for i, key in ipairs(KEYS) do
-- Only remove entries for *this* lock value.
if redis.call("get", key) == ARGV[1] then
redis.pcall("del", key)
count = count + 1
end
-- Only remove entries for *this* lock value.
if redis.call("get", key) == ARGV[1] then
redis.pcall("del", key)
count = count + 1
end
end

@@ -44,5 +44,5 @@

for i, key in ipairs(KEYS) do
if redis.call("get", key) ~= ARGV[1] then
return 0
end
if redis.call("get", key) ~= ARGV[1] then
return 0
end
end

@@ -52,3 +52,3 @@

for i, key in ipairs(KEYS) do
redis.call("set", key, ARGV[1], "PX", ARGV[2])
redis.call("set", key, ARGV[1], "PX", ARGV[2])
end

@@ -95,8 +95,9 @@

// itself.
function Lock(redlock, resource, value, expiration, attempts) {
this.redlock = redlock;
this.resource = resource;
this.value = value;
this.expiration = expiration;
this.attempts = attempts;
function Lock(redlock, resource, value, expiration, attempts, attemptsRemaining) {
this.redlock = redlock;
this.resource = resource;
this.value = value;
this.expiration = expiration;
this.attempts = attempts;
this.attemptsRemaining = attemptsRemaining;
}

@@ -117,5 +118,2 @@

// Redlock

@@ -140,2 +138,8 @@ // -------

throw new Error('Redlock must be instantiated with at least one redis server.');
this.scripts = {
lockScript: { value: this.lockScript, hash: this._hashScript(this.lockScript) },
unlockScript: { value: this.unlockScript, hash: this._hashScript(this.unlockScript) },
extendScript: { value: this.extendScript, hash: this._hashScript(this.extendScript) },
};
}

@@ -151,3 +155,2 @@

// quit

@@ -184,5 +187,23 @@ // ----

Redlock.prototype.lock = function lock(resource, ttl, callback) {
return this._lock(resource, null, ttl, callback);
return this._lock(resource, null, ttl, {}, callback);
};
// lockWithOptions
// ---------------
// This method locks a resource and overwrites some of the options
// ```js
// redlock.lockWithOptions(
// 'some-resource', // the resource to lock
// 2000, // ttl in ms
// { retryCount: 1, retryDelay: 100 }, // additional options
// function(err, lock) { // callback function (optional)
// ...
// }
// )
// ```
Redlock.prototype.acquireWithOptions =
Redlock.prototype.lockWithOptions = function lock(resource, ttl, options, callback) {
return this._lock(resource, null, ttl, options, callback);
};
// lock

@@ -206,3 +227,3 @@ // ----

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

@@ -244,11 +265,7 @@ });

self.servers.forEach(function(server){
return server.eval(
[
self.unlockScript,
return self._executeScript(server, 'unlockScript', [
resource.length,
...resource,
lock.value
],
loop
)
], loop);
});

@@ -295,3 +312,3 @@

// extend the lock
return self._lock(lock.resource, lock.value, ttl)
return self._lock(lock.resource, lock.value, ttl, {})

@@ -321,2 +338,3 @@ // modify and return the original lock object

// 2000, // ttl in ms
// {}, // option overrides {retryCount, retryDelay}
// function(err, lock) { // callback function (optional)

@@ -335,2 +353,3 @@ // ...

// 2000, // ttl in ms
// {}, // option overrides {retryCount, retryDelay}
// function(err, lock) { // callback function (optional)

@@ -341,5 +360,11 @@ // ...

// ```
Redlock.prototype._lock = function _lock(resource, value, ttl, callback) {
Redlock.prototype._lock = function _lock(resource, value, ttl, options, callback) {
const self = this;
// backwards compatibility with previous method signature: _lock(resource, value, ttl, callback)
if (typeof options === 'function' && typeof callback === 'undefined') {
callback = options;
options = {};
}
// array of locked resources

@@ -358,5 +383,3 @@ resource = Array.isArray(resource) ? resource : [resource];

request = function(server, loop){
return server.eval(
[
self.lockScript,
return self._executeScript(server, 'lockScript', [
resource.length,

@@ -366,5 +389,3 @@ ...resource,

ttl
],
loop
);
], loop);
};

@@ -376,5 +397,3 @@ }

request = function(server, loop){
return server.eval(
[
self.extendScript,
return self._executeScript(server, 'extendScript', [
resource.length,

@@ -384,5 +403,3 @@ ...resource,

ttl
],
loop
);
], loop);
};

@@ -394,2 +411,5 @@ }

let retryCount = options.retryCount || self.retryCount;
let retryDelay = options.retryDelay || self.retryDelay;
// the time when this attempt started

@@ -415,3 +435,3 @@ const start = Date.now();

const drift = Math.round(self.driftFactor * ttl) + 2;
const lock = new Lock(self, resource, value, start + ttl - drift, attempts);
const lock = new Lock(self, resource, value, start + ttl - drift, attempts, retryCount - attempts);

@@ -427,7 +447,7 @@ // SUCCESS: there is concensus and the lock is not expired

// RETRY
if(self.retryCount === -1 || attempts <= self.retryCount)
return setTimeout(attempt, Math.max(0, self.retryDelay + Math.floor((Math.random() * 2 - 1) * self.retryJitter)));
if(retryCount === -1 || attempts <= retryCount)
return setTimeout(attempt, Math.max(0, retryDelay + Math.floor((Math.random() * 2 - 1) * self.retryJitter)));
// FAILED
return reject(new LockError('Exceeded ' + self.retryCount + ' attempts to lock the resource "' + resource + '".', attempts));
return reject(new LockError('Exceeded ' + retryCount + ' attempts to lock the resource "' + resource + '".', attempts));
});

@@ -453,2 +473,20 @@ }

Redlock.prototype._executeScript = function(server, name, args, callback) {
const script = this.scripts[name];
return server.evalsha(script.hash, args, (err, result) => {
if(err !== null && err.message.startsWith("NOSCRIPT")) {
// Script is not loaded yet, call eval and it will populate it in redis lua scripts cache
args.unshift(script.value);
return server.eval(args, callback);
}
return callback(err, result);
});
}
Redlock.prototype._hashScript = function(value) {
return crypto.createHash('sha1').update(value).digest('hex');
}
module.exports = Redlock;

@@ -34,2 +34,10 @@ 'use strict';

before(function(done) {
var err;
var l = clients.length; function cb(e){ if(e) err = e; l--; if(l === 0) done(err); }
for (var i = clients.length - 1; i >= 0; i--) {
clients[i].script('flush', cb);
}
})
it('should throw an error if not passed any clients', function(){

@@ -203,6 +211,31 @@ assert.throws(function(){

assert.equal(lock.attempts, 1);
done();
lock.unlock(done);
});
});
describe('lockWithOptions', function() {
it('should lock a resource with additional options', function(done) {
redlock.lockWithOptions(resourceString, 200, {retryCount:10,retryDelay:1}, function(err, lock){
if(err) throw err;
assert.isObject(lock);
assert.instanceOf(lock, Redlock.Lock);
assert.isAbove(lock.expiration, Date.now()-1);
assert.equal(lock.attempts, 1);
assert.equal(lock.attemptsRemaining, 9);
lock.unlock(done);
});
});
it('should be backwards compatible', function(done) {
redlock._lock(resourceString, null, 200, function(err, lock){
if(err) throw err;
assert.isObject(lock);
assert.instanceOf(lock, Redlock.Lock);
assert.isAbove(lock.expiration, Date.now()-1);
assert.equal(lock.attempts, 1);
assert.equal(lock.attemptsRemaining, 1);
lock.unlock(done);
});
});
});
after(function(done) {

@@ -209,0 +242,0 @@ var err;

Sorry, the diff of this file is not supported yet

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