Skip to content

Commit

Permalink
Add types
Browse files Browse the repository at this point in the history
  • Loading branch information
AmrSaber committed Jun 10, 2021
1 parent 060df1a commit b558adc
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 20 deletions.
42 changes: 42 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Redis } from 'ioredis';

/**
* Release the lock only if it has the same lockValue as acquireLock sets it.
* This will not release an already released token.
*/
type ReleaseFunction = () => Promise<void>;

interface acquireOptions {
/**
* Time interval at which attempt to acquire the lock.
*
* @default 100
*/
retryTimeMillis?: number;

/**
* Time span after which the acquired lock times out and is released.
*/
timeoutMillis?: number;

/**
* Time span after which will not attempt to acquire the lock, and the `lock` function will fail.
*/
failAfterMillis?: number;
}

/**
* Acquire mutex lock on the given resource name.
* If the lock is already acquired, wait until it's free and acquire it.
*
* @param client ioredis instance.
* @param lockName the name of the lock to be acquired.
* @param options lock acquire options.
*
* @returns a promise that resolves with release function.
*/
export function lock(
client: Redis,
lockName: string,
options: acquireOptions
): Promise<ReleaseFunction>;
28 changes: 8 additions & 20 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,5 @@
const crypto = require('crypto');

/**
* Acquire mutex lock on the given resource name. If the lock is already acquired, wait until it's free and acquire it.
*
* @param {import('ioredis').Redis} client
* @param {String} lockName
* @param {Object} [options]
* @param {Number} [options.retryTimeMillis=100]
* @param {Number} [options.timeoutMillis]
* @param {Number} [options.failAfterMillis]
*
* @returns {Promise<Function>} release function
*/
async function lock(client, lockName, { retryTimeMillis = 100, timeoutMillis, failAfterMillis } = {}) {
const lockValue = crypto.randomBytes(50).toString('hex');
const lockKey = `@simple-redis-mutex:lock-${lockName}`;
Expand Down Expand Up @@ -56,14 +44,13 @@ async function lock(client, lockName, { retryTimeMillis = 100, timeoutMillis, fa
attempt();
});

/**
* Release the lock only if it has the same lockValue as acquireLock sets it.
* This will prevent the release of an already released token.
*
* @returns {Promise}
*/
function releaseLock() {
// Script source: https://redis.io/commands/set#patterns - Redis official docs
/*
* Release the lock only if it has the same lockValue as acquireLock sets it.
* This will prevent the release of an already released lock.
*
* Script source: https://redis.io/commands/set#patterns - Redis official docs
*/
const luaReleaseScript = `
if redis.call("get", KEYS[1]) == ARGV[1]
then
Expand All @@ -73,7 +60,8 @@ async function lock(client, lockName, { retryTimeMillis = 100, timeoutMillis, fa
end
`;

return client.eval(luaReleaseScript, 1, lockKey, lockValue);
// After calling the script, make sure to return void promise.
return client.eval(luaReleaseScript, 1, lockKey, lockValue).then(() => {});
}

await acquireLock;
Expand Down

0 comments on commit b558adc

Please sign in to comment.