redis-semaphore
Advanced tools
Comparing version
@@ -0,1 +1,6 @@ | ||
### redis-semaphore@5.6.0 | ||
- Added interface compatible client support (ex. `ioredis-mock`) | ||
- Removed `instanceof Redis` validation in constructor | ||
- `ioredis` marked as optional peerDependency, explicit `ioredis` install is required now | ||
### redis-semaphore@5.5.1 | ||
@@ -2,0 +7,0 @@ - Fix race condition for refresh started before release and finished after release |
@@ -1,2 +0,2 @@ | ||
import Redis from 'ioredis'; | ||
import { RedisClient } from '../../types'; | ||
export interface Options { | ||
@@ -9,2 +9,2 @@ identifier: string; | ||
} | ||
export declare function acquireSemaphore(client: Redis, key: string, limit: number, permits: number, options: Options): Promise<boolean>; | ||
export declare function acquireSemaphore(client: RedisClient, key: string, limit: number, permits: number, options: Options): Promise<boolean>; |
@@ -8,3 +8,3 @@ "use strict"; | ||
const debug_1 = __importDefault(require("debug")); | ||
const index_1 = require("../../utils/index"); | ||
const utils_1 = require("../../utils"); | ||
const lua_1 = require("./lua"); | ||
@@ -33,3 +33,3 @@ const debug = (0, debug_1.default)('redis-semaphore:multi-semaphore:acquire'); | ||
else { | ||
await (0, index_1.delay)(retryInterval); | ||
await (0, utils_1.delay)(retryInterval); | ||
} | ||
@@ -36,0 +36,0 @@ } |
@@ -1,1 +0,1 @@ | ||
export declare const acquireLua: (client: import("ioredis/built/Redis").default, args: [string, number, number, string, number, number]) => Promise<0 | 1>; | ||
export declare const acquireLua: (client: import("../../types").RedisClient, args: [string, number, number, string, number, number]) => Promise<0 | 1>; |
@@ -1,2 +0,2 @@ | ||
import Redis from 'ioredis'; | ||
import { RedisClient } from '../../types'; | ||
export interface Options { | ||
@@ -6,2 +6,2 @@ identifier: string; | ||
} | ||
export declare function refreshSemaphore(client: Redis, key: string, limit: number, permits: number, options: Options): Promise<boolean>; | ||
export declare function refreshSemaphore(client: RedisClient, key: string, limit: number, permits: number, options: Options): Promise<boolean>; |
@@ -1,1 +0,1 @@ | ||
export declare const refreshLua: (client: import("ioredis/built/Redis").default, args: [string, number, number, string, number, number]) => Promise<0 | 1>; | ||
export declare const refreshLua: (client: import("../../types").RedisClient, args: [string, number, number, string, number, number]) => Promise<0 | 1>; |
@@ -1,2 +0,2 @@ | ||
import Redis from 'ioredis'; | ||
import { RedisClient } from '../../types'; | ||
export interface Options { | ||
@@ -7,2 +7,2 @@ identifier: string; | ||
} | ||
export declare function releaseSemaphore(client: Redis, key: string, permits: number, identifier: string): Promise<void>; | ||
export declare function releaseSemaphore(client: RedisClient, key: string, permits: number, identifier: string): Promise<void>; |
@@ -1,1 +0,1 @@ | ||
export declare const releaseLua: (client: import("ioredis/built/Redis").default, args: [string, number, string]) => Promise<number>; | ||
export declare const releaseLua: (client: import("../../types").RedisClient, args: [string, number, string]) => Promise<number>; |
@@ -1,2 +0,2 @@ | ||
import Redis from 'ioredis'; | ||
import { RedisClient } from '../types'; | ||
export interface Options { | ||
@@ -9,2 +9,2 @@ identifier: string; | ||
} | ||
export declare function acquireMutex(client: Redis, key: string, options: Options): Promise<boolean>; | ||
export declare function acquireMutex(client: RedisClient, key: string, options: Options): Promise<boolean>; |
@@ -8,3 +8,3 @@ "use strict"; | ||
const debug_1 = __importDefault(require("debug")); | ||
const index_1 = require("../utils/index"); | ||
const utils_1 = require("../utils"); | ||
const debug = (0, debug_1.default)('redis-semaphore:mutex:acquire'); | ||
@@ -24,3 +24,3 @@ async function acquireMutex(client, key, options) { | ||
else { | ||
await (0, index_1.delay)(retryInterval); | ||
await (0, utils_1.delay)(retryInterval); | ||
} | ||
@@ -27,0 +27,0 @@ } |
@@ -1,3 +0,3 @@ | ||
import Redis from 'ioredis'; | ||
export declare const expireIfEqualLua: (client: Redis, args: [string, string, number]) => Promise<0 | 1>; | ||
export declare function refreshMutex(client: Redis, key: string, identifier: string, lockTimeout: number): Promise<boolean>; | ||
import { RedisClient } from '../types'; | ||
export declare const expireIfEqualLua: (client: RedisClient, args: [string, string, number]) => Promise<0 | 1>; | ||
export declare function refreshMutex(client: RedisClient, key: string, identifier: string, lockTimeout: number): Promise<boolean>; |
@@ -1,3 +0,3 @@ | ||
import Redis from 'ioredis'; | ||
export declare const delIfEqualLua: (client: Redis, args: [string, string]) => Promise<0 | 1>; | ||
export declare function releaseMutex(client: Redis, key: string, identifier: string): Promise<void>; | ||
import type { RedisClient } from '../types'; | ||
export declare const delIfEqualLua: (client: RedisClient, args: [string, string]) => Promise<0 | 1>; | ||
export declare function releaseMutex(client: RedisClient, key: string, identifier: string): Promise<void>; |
@@ -1,8 +0,7 @@ | ||
import Redis from 'ioredis'; | ||
import RedisSemaphore from './RedisSemaphore'; | ||
import { LockOptions } from './types'; | ||
import { LockOptions, RedisClient } from './types'; | ||
export default class RedisMultiSemaphore extends RedisSemaphore { | ||
protected _kind: string; | ||
protected _permits: number; | ||
constructor(client: Redis, key: string, limit: number, permits: number, options?: LockOptions); | ||
constructor(client: RedisClient, key: string, limit: number, permits: number, options?: LockOptions); | ||
protected _refresh(): Promise<boolean>; | ||
@@ -9,0 +8,0 @@ protected _acquire(): Promise<boolean>; |
@@ -6,5 +6,5 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const index_1 = require("./multiSemaphore/acquire/index"); | ||
const index_2 = require("./multiSemaphore/refresh/index"); | ||
const index_3 = require("./multiSemaphore/release/index"); | ||
const acquire_1 = require("./multiSemaphore/acquire"); | ||
const refresh_1 = require("./multiSemaphore/refresh"); | ||
const release_1 = require("./multiSemaphore/release"); | ||
const RedisSemaphore_1 = __importDefault(require("./RedisSemaphore")); | ||
@@ -24,9 +24,9 @@ class RedisMultiSemaphore extends RedisSemaphore_1.default { | ||
async _refresh() { | ||
return await (0, index_2.refreshSemaphore)(this._client, this._key, this._limit, this._permits, this._acquireOptions); | ||
return await (0, refresh_1.refreshSemaphore)(this._client, this._key, this._limit, this._permits, this._acquireOptions); | ||
} | ||
async _acquire() { | ||
return await (0, index_1.acquireSemaphore)(this._client, this._key, this._limit, this._permits, this._acquireOptions); | ||
return await (0, acquire_1.acquireSemaphore)(this._client, this._key, this._limit, this._permits, this._acquireOptions); | ||
} | ||
async _release() { | ||
await (0, index_3.releaseSemaphore)(this._client, this._key, this._permits, this._identifier); | ||
await (0, release_1.releaseSemaphore)(this._client, this._key, this._permits, this._identifier); | ||
} | ||
@@ -33,0 +33,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import Redis from 'ioredis'; | ||
import type { RedisClient } from './types'; | ||
import { Lock } from './Lock'; | ||
@@ -7,4 +7,4 @@ import { LockOptions } from './types'; | ||
protected _key: string; | ||
protected _client: Redis; | ||
constructor(client: Redis, key: string, options?: LockOptions); | ||
protected _client: RedisClient; | ||
constructor(client: RedisClient, key: string, options?: LockOptions); | ||
protected _refresh(): Promise<boolean>; | ||
@@ -11,0 +11,0 @@ protected _acquire(): Promise<boolean>; |
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const ioredis_1 = __importDefault(require("ioredis")); | ||
const Lock_1 = require("./Lock"); | ||
@@ -18,5 +14,2 @@ const acquire_1 = require("./mutex/acquire"); | ||
} | ||
if (!(client instanceof ioredis_1.default)) { | ||
throw new Error('"client" must be instance of ioredis client or cluster'); | ||
} | ||
if (!key) { | ||
@@ -23,0 +16,0 @@ throw new Error('"key" is required'); |
@@ -1,8 +0,7 @@ | ||
import Redis from 'ioredis'; | ||
import RedisMutex from './RedisMutex'; | ||
import { LockOptions } from './types'; | ||
import { LockOptions, RedisClient } from './types'; | ||
export default class RedisSemaphore extends RedisMutex { | ||
protected _kind: string; | ||
protected _limit: number; | ||
constructor(client: Redis, key: string, limit: number, options?: LockOptions); | ||
constructor(client: RedisClient, key: string, limit: number, options?: LockOptions); | ||
protected _refresh(): Promise<boolean>; | ||
@@ -9,0 +8,0 @@ protected _acquire(): Promise<boolean>; |
@@ -7,4 +7,4 @@ "use strict"; | ||
const RedisMutex_1 = __importDefault(require("./RedisMutex")); | ||
const index_1 = require("./semaphore/acquire/index"); | ||
const index_2 = require("./semaphore/refresh/index"); | ||
const acquire_1 = require("./semaphore/acquire"); | ||
const refresh_1 = require("./semaphore/refresh"); | ||
const release_1 = require("./semaphore/release"); | ||
@@ -25,6 +25,6 @@ class RedisSemaphore extends RedisMutex_1.default { | ||
async _refresh() { | ||
return await (0, index_2.refreshSemaphore)(this._client, this._key, this._limit, this._acquireOptions); | ||
return await (0, refresh_1.refreshSemaphore)(this._client, this._key, this._limit, this._acquireOptions); | ||
} | ||
async _acquire() { | ||
return await (0, index_1.acquireSemaphore)(this._client, this._key, this._limit, this._acquireOptions); | ||
return await (0, acquire_1.acquireSemaphore)(this._client, this._key, this._limit, this._acquireOptions); | ||
} | ||
@@ -31,0 +31,0 @@ async _release() { |
@@ -1,8 +0,7 @@ | ||
import Redis from 'ioredis'; | ||
import RedlockSemaphore from './RedlockSemaphore'; | ||
import { LockOptions } from './types'; | ||
import { LockOptions, RedisClient } from './types'; | ||
export default class RedlockMultiSemaphore extends RedlockSemaphore { | ||
protected _kind: string; | ||
protected _permits: number; | ||
constructor(clients: Redis[], key: string, limit: number, permits: number, options?: LockOptions); | ||
constructor(clients: RedisClient[], key: string, limit: number, permits: number, options?: LockOptions); | ||
protected _refresh(): Promise<boolean>; | ||
@@ -9,0 +8,0 @@ protected _acquire(): Promise<boolean>; |
@@ -1,2 +0,2 @@ | ||
import Redis from 'ioredis'; | ||
import { RedisClient } from '../types'; | ||
export interface Options { | ||
@@ -9,2 +9,2 @@ identifier: string; | ||
} | ||
export declare function acquireRedlockMultiSemaphore(clients: Redis[], key: string, limit: number, permits: number, options: Options): Promise<boolean>; | ||
export declare function acquireRedlockMultiSemaphore(clients: RedisClient[], key: string, limit: number, permits: number, options: Options): Promise<boolean>; |
@@ -9,3 +9,3 @@ "use strict"; | ||
const lua_1 = require("../multiSemaphore/acquire/lua"); | ||
const index_1 = require("../utils/index"); | ||
const utils_1 = require("../utils"); | ||
const redlock_1 = require("../utils/redlock"); | ||
@@ -32,3 +32,3 @@ const debug = (0, debug_1.default)('redis-semaphore:redlock-multi-semaphore:acquire'); | ||
await Promise.all(promises); | ||
await (0, index_1.delay)(retryInterval); | ||
await (0, utils_1.delay)(retryInterval); | ||
} | ||
@@ -35,0 +35,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import Redis from 'ioredis'; | ||
import { RedisClient } from '../types'; | ||
interface Options { | ||
@@ -6,3 +6,3 @@ identifier: string; | ||
} | ||
export declare function refreshRedlockMultiSemaphore(clients: Redis[], key: string, limit: number, permits: number, options: Options): Promise<boolean>; | ||
export declare function refreshRedlockMultiSemaphore(clients: RedisClient[], key: string, limit: number, permits: number, options: Options): Promise<boolean>; | ||
export {}; |
@@ -1,2 +0,2 @@ | ||
import Redis from 'ioredis'; | ||
export declare function releaseRedlockMultiSemaphore(clients: Redis[], key: string, permits: number, identifier: string): Promise<void>; | ||
import { RedisClient } from '../types'; | ||
export declare function releaseRedlockMultiSemaphore(clients: RedisClient[], key: string, permits: number, identifier: string): Promise<void>; |
@@ -1,9 +0,8 @@ | ||
import Redis from 'ioredis'; | ||
import { Lock } from './Lock'; | ||
import { LockOptions } from './types'; | ||
import { LockOptions, RedisClient } from './types'; | ||
export default class RedlockMutex extends Lock { | ||
protected _kind: string; | ||
protected _key: string; | ||
protected _clients: Redis[]; | ||
constructor(clients: Redis[], key: string, options?: LockOptions); | ||
protected _clients: RedisClient[]; | ||
constructor(clients: RedisClient[], key: string, options?: LockOptions); | ||
protected _refresh(): Promise<boolean>; | ||
@@ -10,0 +9,0 @@ protected _acquire(): Promise<boolean>; |
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const ioredis_1 = __importDefault(require("ioredis")); | ||
const Lock_1 = require("./Lock"); | ||
@@ -19,5 +15,2 @@ const misc_1 = require("./misc"); | ||
} | ||
if (!clients.every(client => client instanceof ioredis_1.default)) { | ||
throw new Error('"client" must be instance of ioredis client'); | ||
} | ||
if (!key) { | ||
@@ -24,0 +17,0 @@ throw new Error('"key" is required'); |
@@ -1,2 +0,2 @@ | ||
import Redis from 'ioredis'; | ||
import { RedisClient } from '../types'; | ||
export interface Options { | ||
@@ -9,2 +9,2 @@ identifier: string; | ||
} | ||
export declare function acquireRedlockMutex(clients: Redis[], key: string, options: Options): Promise<boolean>; | ||
export declare function acquireRedlockMutex(clients: RedisClient[], key: string, options: Options): Promise<boolean>; |
@@ -9,3 +9,3 @@ "use strict"; | ||
const release_1 = require("../mutex/release"); | ||
const index_1 = require("../utils/index"); | ||
const utils_1 = require("../utils"); | ||
const redlock_1 = require("../utils/redlock"); | ||
@@ -32,3 +32,3 @@ const debug = (0, debug_1.default)('redis-semaphore:redlock-mutex:acquire'); | ||
await Promise.all(promises); | ||
await (0, index_1.delay)(retryInterval); | ||
await (0, utils_1.delay)(retryInterval); | ||
} | ||
@@ -35,0 +35,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import Redis from 'ioredis'; | ||
export declare function refreshRedlockMutex(clients: Redis[], key: string, identifier: string, lockTimeout: number): Promise<boolean>; | ||
import { RedisClient } from '../types'; | ||
export declare function refreshRedlockMutex(clients: RedisClient[], key: string, identifier: string, lockTimeout: number): Promise<boolean>; |
@@ -1,2 +0,2 @@ | ||
import Redis from 'ioredis'; | ||
export declare function releaseRedlockMutex(clients: Redis[], key: string, identifier: string): Promise<void>; | ||
import type { RedisClient } from '../types'; | ||
export declare function releaseRedlockMutex(clients: RedisClient[], key: string, identifier: string): Promise<void>; |
@@ -1,8 +0,7 @@ | ||
import Redis from 'ioredis'; | ||
import RedlockMutex from './RedlockMutex'; | ||
import { LockOptions } from './types'; | ||
import { LockOptions, RedisClient } from './types'; | ||
export default class RedlockSemaphore extends RedlockMutex { | ||
protected _kind: string; | ||
protected _limit: number; | ||
constructor(clients: Redis[], key: string, limit: number, options?: LockOptions); | ||
constructor(clients: RedisClient[], key: string, limit: number, options?: LockOptions); | ||
protected _refresh(): Promise<boolean>; | ||
@@ -9,0 +8,0 @@ protected _acquire(): Promise<boolean>; |
@@ -1,2 +0,2 @@ | ||
import Redis from 'ioredis'; | ||
import { RedisClient } from '../types'; | ||
export interface Options { | ||
@@ -9,2 +9,2 @@ identifier: string; | ||
} | ||
export declare function acquireRedlockSemaphore(clients: Redis[], key: string, limit: number, options: Options): Promise<boolean>; | ||
export declare function acquireRedlockSemaphore(clients: RedisClient[], key: string, limit: number, options: Options): Promise<boolean>; |
@@ -9,3 +9,3 @@ "use strict"; | ||
const lua_1 = require("../semaphore/acquire/lua"); | ||
const index_1 = require("../utils/index"); | ||
const utils_1 = require("../utils"); | ||
const redlock_1 = require("../utils/redlock"); | ||
@@ -32,3 +32,3 @@ const debug = (0, debug_1.default)('redis-semaphore:redlock-semaphore:acquire'); | ||
await Promise.all(promises); | ||
await (0, index_1.delay)(retryInterval); | ||
await (0, utils_1.delay)(retryInterval); | ||
} | ||
@@ -35,0 +35,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import Redis from 'ioredis'; | ||
import type { RedisClient } from '../types'; | ||
interface Options { | ||
@@ -6,3 +6,3 @@ identifier: string; | ||
} | ||
export declare function refreshRedlockSemaphore(clients: Redis[], key: string, limit: number, options: Options): Promise<boolean>; | ||
export declare function refreshRedlockSemaphore(clients: RedisClient[], key: string, limit: number, options: Options): Promise<boolean>; | ||
export {}; |
@@ -1,2 +0,2 @@ | ||
import Redis from 'ioredis'; | ||
export declare function releaseRedlockSemaphore(clients: Redis[], key: string, identifier: string): Promise<void>; | ||
import type { RedisClient } from '../types'; | ||
export declare function releaseRedlockSemaphore(clients: RedisClient[], key: string, identifier: string): Promise<void>; |
@@ -1,2 +0,2 @@ | ||
import Redis from 'ioredis'; | ||
import { RedisClient } from '../../types'; | ||
export interface Options { | ||
@@ -9,2 +9,2 @@ identifier: string; | ||
} | ||
export declare function acquireSemaphore(client: Redis, key: string, limit: number, options: Options): Promise<boolean>; | ||
export declare function acquireSemaphore(client: RedisClient, key: string, limit: number, options: Options): Promise<boolean>; |
@@ -8,3 +8,3 @@ "use strict"; | ||
const debug_1 = __importDefault(require("debug")); | ||
const index_1 = require("../../utils/index"); | ||
const utils_1 = require("../../utils"); | ||
const lua_1 = require("./lua"); | ||
@@ -33,3 +33,3 @@ const debug = (0, debug_1.default)('redis-semaphore:semaphore:acquire'); | ||
else { | ||
await (0, index_1.delay)(retryInterval); | ||
await (0, utils_1.delay)(retryInterval); | ||
} | ||
@@ -36,0 +36,0 @@ } |
@@ -1,1 +0,1 @@ | ||
export declare const acquireLua: (client: import("ioredis/built/Redis").default, args: [string, number, string, number, number]) => Promise<0 | 1>; | ||
export declare const acquireLua: (client: import("../../types").RedisClient, args: [string, number, string, number, number]) => Promise<0 | 1>; |
@@ -1,2 +0,2 @@ | ||
import Redis from 'ioredis'; | ||
import { RedisClient } from '../../types'; | ||
export interface Options { | ||
@@ -6,2 +6,2 @@ identifier: string; | ||
} | ||
export declare function refreshSemaphore(client: Redis, key: string, limit: number, options: Options): Promise<boolean>; | ||
export declare function refreshSemaphore(client: RedisClient, key: string, limit: number, options: Options): Promise<boolean>; |
@@ -1,1 +0,1 @@ | ||
export declare const refreshLua: (client: import("ioredis/built/Redis").default, args: [string, number, string, number, number]) => Promise<0 | 1>; | ||
export declare const refreshLua: (client: import("../../types").RedisClient, args: [string, number, string, number, number]) => Promise<0 | 1>; |
@@ -1,2 +0,2 @@ | ||
import Redis from 'ioredis'; | ||
export declare function releaseSemaphore(client: Redis, key: string, identifier: string): Promise<void>; | ||
import { RedisClient } from '../types'; | ||
export declare function releaseSemaphore(client: RedisClient, key: string, identifier: string): Promise<void>; |
import LostLockError from './errors/LostLockError'; | ||
import { Lock } from './Lock'; | ||
import type * as ioredis from 'ioredis'; | ||
/** | ||
* ioredis-like Redis client | ||
*/ | ||
export type RedisClient = Pick<ioredis.Redis, 'eval' | 'evalsha' | 'get' | 'set' | 'zrem'> & Partial<Pick<ioredis.Redis, 'options'>>; | ||
export interface LockLostCallback { | ||
@@ -4,0 +9,0 @@ (this: Lock, err: LostLockError): void; |
@@ -1,2 +0,2 @@ | ||
import Redis from 'ioredis'; | ||
export default function createEval<Args extends Array<number | string>, Result>(script: string, keysCount: number): (client: Redis, args: Args) => Promise<Result>; | ||
import { RedisClient } from '../types'; | ||
export default function createEval<Args extends Array<number | string>, Result>(script: string, keysCount: number): (client: RedisClient, args: Args) => Promise<Result>; |
@@ -1,5 +0,5 @@ | ||
import Redis from 'ioredis'; | ||
import { RedisClient } from '../types'; | ||
import createEval from './createEval'; | ||
export { createEval }; | ||
export declare function delay(ms: number): Promise<unknown>; | ||
export declare function getConnectionName(client: Redis): string; | ||
export declare function getConnectionName(client: RedisClient): string; |
@@ -7,3 +7,2 @@ "use strict"; | ||
exports.getConnectionName = exports.delay = exports.createEval = void 0; | ||
const ioredis_1 = __importDefault(require("ioredis")); | ||
const createEval_1 = __importDefault(require("./createEval")); | ||
@@ -16,7 +15,6 @@ exports.createEval = createEval_1.default; | ||
function getConnectionName(client) { | ||
return client instanceof ioredis_1.default && client.options.connectionName | ||
? `<${client.options.connectionName}>` | ||
: '<unknown client>'; | ||
const connectionName = client.options?.connectionName; | ||
return connectionName ? `<${connectionName}>` : '<unknown client>'; | ||
} | ||
exports.getConnectionName = getConnectionName; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "redis-semaphore", | ||
"version": "5.5.1", | ||
"version": "5.6.0", | ||
"description": "Distributed mutex and semaphore based on Redis", | ||
@@ -8,12 +8,12 @@ "main": "lib/index.js", | ||
"scripts": { | ||
"test": "eslint --ext .js,.ts . && mocha", | ||
"test-ci-with-coverage": "eslint --ext .js,.ts . && nyc mocha && nyc report --reporter=text-lcov | coveralls", | ||
"lint": "eslint --ext .js,.ts .", | ||
"test": "mocha", | ||
"test-ci-with-coverage": "nyc mocha && nyc report --reporter=text-lcov | coveralls", | ||
"coverage-html": "nyc mocha && nyc report --reporter=html", | ||
"converalls": "nyc mocha && nyc report --reporter=text-lcov | coveralls", | ||
"dev": "mocha -w", | ||
"check-types": "tsc -b tsconfig.check-types.json", | ||
"build": "yarn build-commonjs", | ||
"build-commonjs": "rm -rf lib && yarn tsc -b tsconfig.build-commonjs.json", | ||
"build-es": "rm -rf es && yarn tsc -b tsconfig.build-es.json", | ||
"preversion": "yarn test && yarn build" | ||
"preversion": "yarn lint && yarn test && yarn build" | ||
}, | ||
@@ -34,14 +34,17 @@ "repository": { | ||
"@swarthy/wait-for": "^2.1.1", | ||
"@types/chai": "^4.3.12", | ||
"@swc-node/register": "1.9.1", | ||
"@swc/core": "1.5.7", | ||
"@types/chai": "^4.3.16", | ||
"@types/chai-as-promised": "^7.1.8", | ||
"@types/debug": "^4.1.12", | ||
"@types/ioredis-mock": "^8", | ||
"@types/mocha": "^10.0.6", | ||
"@types/node": "20.11.21", | ||
"@types/node": "20.12.12", | ||
"@types/sinon": "^17.0.3", | ||
"@types/sinon-chai": "^3.2.12", | ||
"@typescript-eslint/eslint-plugin": "7.1.0", | ||
"@typescript-eslint/parser": "7.1.0", | ||
"@typescript-eslint/eslint-plugin": "7.10.0", | ||
"@typescript-eslint/parser": "7.10.0", | ||
"benchmark": "^2.1.4", | ||
"chai": "4.4.1", | ||
"chai-as-promised": "7.1.1", | ||
"chai-as-promised": "7.1.2", | ||
"coveralls": "^3.1.1", | ||
@@ -51,11 +54,12 @@ "eslint": "8.57.0", | ||
"eslint-plugin-node": "11.1.0", | ||
"ioredis": "^5.3.2", | ||
"mocha": "10.3.0", | ||
"ioredis": "5.4.1", | ||
"ioredis-mock": "8.9.0", | ||
"mocha": "10.4.0", | ||
"mocha-lcov-reporter": "^1.3.0", | ||
"nyc": "^15.1.0", | ||
"sinon": "17.0.1", | ||
"sinon": "18.0.0", | ||
"sinon-chai": "3.7.0", | ||
"snyk": "1.1280.1", | ||
"snyk": "1.1291.0", | ||
"ts-node": "^10.9.2", | ||
"typescript": "^5.3.3" | ||
"typescript": "^5.4.5" | ||
}, | ||
@@ -68,2 +72,7 @@ "engines": { | ||
}, | ||
"peerDependenciesMeta": { | ||
"ioredis": { | ||
"optional": true | ||
} | ||
}, | ||
"dependencies": { | ||
@@ -70,0 +79,0 @@ "debug": "^4.3.4" |
@@ -27,2 +27,6 @@ # redis-semaphore | ||
ioredis is the officially supported Redis client. This library's test code runs on it. | ||
Users of other Redis clients should ensure ioredis-compatible API (see src/types.ts) when creating lock objects. | ||
### Mutex | ||
@@ -414,2 +418,10 @@ | ||
## Development | ||
```shell | ||
yarn --immutable | ||
./setup-redis-servers.sh | ||
yarn dev | ||
``` | ||
## License | ||
@@ -416,0 +428,0 @@ |
import createDebug from 'debug' | ||
import Redis from 'ioredis' | ||
import { RedisClient } from '../../types' | ||
import { delay } from '../../utils/index' | ||
import { delay } from '../../utils' | ||
import { acquireLua } from './lua' | ||
@@ -18,3 +18,3 @@ | ||
export async function acquireSemaphore( | ||
client: Redis, | ||
client: RedisClient, | ||
key: string, | ||
@@ -21,0 +21,0 @@ limit: number, |
import createDebug from 'debug' | ||
import Redis from 'ioredis' | ||
import { RedisClient } from '../../types' | ||
@@ -14,3 +14,3 @@ import { refreshLua } from './lua' | ||
export async function refreshSemaphore( | ||
client: Redis, | ||
client: RedisClient, | ||
key: string, | ||
@@ -17,0 +17,0 @@ limit: number, |
import createDebug from 'debug' | ||
import Redis from 'ioredis' | ||
import { releaseLua } from './lua' | ||
import { RedisClient } from '../../types' | ||
@@ -15,3 +15,3 @@ const debug = createDebug('redis-semaphore:multi-semaphore:release') | ||
export async function releaseSemaphore( | ||
client: Redis, | ||
client: RedisClient, | ||
key: string, | ||
@@ -18,0 +18,0 @@ permits: number, |
import createDebug from 'debug' | ||
import Redis from 'ioredis' | ||
import { RedisClient } from '../types' | ||
import { delay } from '../utils/index' | ||
import { delay } from '../utils' | ||
@@ -17,3 +17,3 @@ const debug = createDebug('redis-semaphore:mutex:acquire') | ||
export async function acquireMutex( | ||
client: Redis, | ||
client: RedisClient, | ||
key: string, | ||
@@ -20,0 +20,0 @@ options: Options |
import createDebug from 'debug' | ||
import Redis from 'ioredis' | ||
import { RedisClient } from '../types' | ||
@@ -27,3 +27,3 @@ import { createEval } from '../utils/index' | ||
export async function refreshMutex( | ||
client: Redis, | ||
client: RedisClient, | ||
key: string, | ||
@@ -30,0 +30,0 @@ identifier: string, |
import createDebug from 'debug' | ||
import Redis from 'ioredis' | ||
import type { RedisClient } from '../types' | ||
@@ -23,3 +23,3 @@ import { createEval } from '../utils/index' | ||
export async function releaseMutex( | ||
client: Redis, | ||
client: RedisClient, | ||
key: string, | ||
@@ -26,0 +26,0 @@ identifier: string |
@@ -1,8 +0,6 @@ | ||
import Redis from 'ioredis' | ||
import { acquireSemaphore } from './multiSemaphore/acquire/index' | ||
import { refreshSemaphore } from './multiSemaphore/refresh/index' | ||
import { releaseSemaphore } from './multiSemaphore/release/index' | ||
import { acquireSemaphore } from './multiSemaphore/acquire' | ||
import { refreshSemaphore } from './multiSemaphore/refresh' | ||
import { releaseSemaphore } from './multiSemaphore/release' | ||
import RedisSemaphore from './RedisSemaphore' | ||
import { LockOptions } from './types' | ||
import { LockOptions, RedisClient } from './types' | ||
@@ -14,3 +12,3 @@ export default class RedisMultiSemaphore extends RedisSemaphore { | ||
constructor( | ||
client: Redis, | ||
client: RedisClient, | ||
key: string, | ||
@@ -17,0 +15,0 @@ limit: number, |
@@ -1,2 +0,2 @@ | ||
import Redis from 'ioredis' | ||
import type { RedisClient } from './types' | ||
@@ -12,5 +12,5 @@ import { Lock } from './Lock' | ||
protected _key: string | ||
protected _client: Redis | ||
protected _client: RedisClient | ||
constructor(client: Redis, key: string, options?: LockOptions) { | ||
constructor(client: RedisClient, key: string, options?: LockOptions) { | ||
super(options) | ||
@@ -20,5 +20,2 @@ if (!client) { | ||
} | ||
if (!(client instanceof Redis)) { | ||
throw new Error('"client" must be instance of ioredis client or cluster') | ||
} | ||
if (!key) { | ||
@@ -25,0 +22,0 @@ throw new Error('"key" is required') |
@@ -1,8 +0,6 @@ | ||
import Redis from 'ioredis' | ||
import RedisMutex from './RedisMutex' | ||
import { acquireSemaphore } from './semaphore/acquire/index' | ||
import { refreshSemaphore } from './semaphore/refresh/index' | ||
import { acquireSemaphore } from './semaphore/acquire' | ||
import { refreshSemaphore } from './semaphore/refresh' | ||
import { releaseSemaphore } from './semaphore/release' | ||
import { LockOptions } from './types' | ||
import { LockOptions, RedisClient } from './types' | ||
@@ -14,3 +12,3 @@ export default class RedisSemaphore extends RedisMutex { | ||
constructor( | ||
client: Redis, | ||
client: RedisClient, | ||
key: string, | ||
@@ -17,0 +15,0 @@ limit: number, |
@@ -1,3 +0,1 @@ | ||
import Redis from 'ioredis' | ||
import { acquireRedlockMultiSemaphore } from './redlockMultiSemaphore/acquire' | ||
@@ -7,3 +5,3 @@ import { refreshRedlockMultiSemaphore } from './redlockMultiSemaphore/refresh' | ||
import RedlockSemaphore from './RedlockSemaphore' | ||
import { LockOptions } from './types' | ||
import { LockOptions, RedisClient } from './types' | ||
@@ -15,3 +13,3 @@ export default class RedlockMultiSemaphore extends RedlockSemaphore { | ||
constructor( | ||
clients: Redis[], | ||
clients: RedisClient[], | ||
key: string, | ||
@@ -18,0 +16,0 @@ limit: number, |
import createDebug from 'debug' | ||
import Redis from 'ioredis' | ||
import { RedisClient } from '../types' | ||
import { acquireLua } from '../multiSemaphore/acquire/lua' | ||
import { delay } from '../utils/index' | ||
import { delay } from '../utils' | ||
import { getQuorum, smartSum } from '../utils/redlock' | ||
@@ -19,3 +19,3 @@ | ||
export async function acquireRedlockMultiSemaphore( | ||
clients: Redis[], | ||
clients: RedisClient[], | ||
key: string, | ||
@@ -22,0 +22,0 @@ limit: number, |
import createDebug from 'debug' | ||
import Redis from 'ioredis' | ||
import { acquireLua } from '../multiSemaphore/acquire/lua' | ||
import { RedisClient } from '../types' | ||
@@ -17,3 +17,3 @@ import { refreshLua } from '../multiSemaphore/refresh/lua' | ||
export async function refreshRedlockMultiSemaphore( | ||
clients: Redis[], | ||
clients: RedisClient[], | ||
key: string, | ||
@@ -41,3 +41,3 @@ limit: number, | ||
const promises = results | ||
.reduce<Redis[]>((failedClients, result, index) => { | ||
.reduce<RedisClient[]>((failedClients, result, index) => { | ||
if (!result) { | ||
@@ -44,0 +44,0 @@ failedClients.push(clients[index]) |
import createDebug from 'debug' | ||
import Redis from 'ioredis' | ||
import { RedisClient } from '../types' | ||
@@ -9,3 +9,3 @@ import { releaseLua } from '../multiSemaphore/release/lua' | ||
export async function releaseRedlockMultiSemaphore( | ||
clients: Redis[], | ||
clients: RedisClient[], | ||
key: string, | ||
@@ -12,0 +12,0 @@ permits: number, |
@@ -1,3 +0,1 @@ | ||
import Redis from 'ioredis' | ||
import { Lock } from './Lock' | ||
@@ -8,3 +6,3 @@ import { defaultTimeoutOptions } from './misc' | ||
import { releaseRedlockMutex } from './redlockMutex/release' | ||
import { LockOptions } from './types' | ||
import { LockOptions, RedisClient } from './types' | ||
@@ -14,6 +12,6 @@ export default class RedlockMutex extends Lock { | ||
protected _key: string | ||
protected _clients: Redis[] | ||
protected _clients: RedisClient[] | ||
constructor( | ||
clients: Redis[], | ||
clients: RedisClient[], | ||
key: string, | ||
@@ -26,5 +24,2 @@ options: LockOptions = defaultTimeoutOptions | ||
} | ||
if (!clients.every(client => client instanceof Redis)) { | ||
throw new Error('"client" must be instance of ioredis client') | ||
} | ||
if (!key) { | ||
@@ -31,0 +26,0 @@ throw new Error('"key" is required') |
import createDebug from 'debug' | ||
import Redis from 'ioredis' | ||
import { delIfEqualLua } from '../mutex/release' | ||
import { delay } from '../utils/index' | ||
import { delay } from '../utils' | ||
import { getQuorum, smartSum } from '../utils/redlock' | ||
import { RedisClient } from '../types' | ||
@@ -19,3 +19,3 @@ const debug = createDebug('redis-semaphore:redlock-mutex:acquire') | ||
export async function acquireRedlockMutex( | ||
clients: Redis[], | ||
clients: RedisClient[], | ||
key: string, | ||
@@ -22,0 +22,0 @@ options: Options |
import createDebug from 'debug' | ||
import Redis from 'ioredis' | ||
@@ -7,2 +6,3 @@ import { expireIfEqualLua } from '../mutex/refresh' | ||
import { getQuorum, smartSum } from '../utils/redlock' | ||
import { RedisClient } from '../types' | ||
@@ -12,3 +12,3 @@ const debug = createDebug('redis-semaphore:redlock-mutex:refresh') | ||
export async function refreshRedlockMutex( | ||
clients: Redis[], | ||
clients: RedisClient[], | ||
key: string, | ||
@@ -33,3 +33,3 @@ identifier: string, | ||
const promises = results | ||
.reduce<Redis[]>((failedClients, result, index) => { | ||
.reduce<RedisClient[]>((failedClients, result, index) => { | ||
if (!result) { | ||
@@ -36,0 +36,0 @@ failedClients.push(clients[index]) |
import createDebug from 'debug' | ||
import Redis from 'ioredis' | ||
import type { RedisClient } from '../types' | ||
@@ -9,3 +9,3 @@ import { delIfEqualLua } from '../mutex/release' | ||
export async function releaseRedlockMutex( | ||
clients: Redis[], | ||
clients: RedisClient[], | ||
key: string, | ||
@@ -12,0 +12,0 @@ identifier: string |
@@ -1,3 +0,1 @@ | ||
import Redis from 'ioredis' | ||
import RedlockMutex from './RedlockMutex' | ||
@@ -7,3 +5,3 @@ import { acquireRedlockSemaphore } from './redlockSemaphore/acquire' | ||
import { releaseRedlockSemaphore } from './redlockSemaphore/release' | ||
import { LockOptions } from './types' | ||
import { LockOptions, RedisClient } from './types' | ||
@@ -15,3 +13,3 @@ export default class RedlockSemaphore extends RedlockMutex { | ||
constructor( | ||
clients: Redis[], | ||
clients: RedisClient[], | ||
key: string, | ||
@@ -18,0 +16,0 @@ limit: number, |
import createDebug from 'debug' | ||
import Redis from 'ioredis' | ||
import { acquireLua } from '../semaphore/acquire/lua' | ||
import { delay } from '../utils/index' | ||
import { delay } from '../utils' | ||
import { getQuorum, smartSum } from '../utils/redlock' | ||
import { RedisClient } from '../types' | ||
@@ -19,3 +19,3 @@ const debug = createDebug('redis-semaphore:redlock-semaphore:acquire') | ||
export async function acquireRedlockSemaphore( | ||
clients: Redis[], | ||
clients: RedisClient[], | ||
key: string, | ||
@@ -22,0 +22,0 @@ limit: number, |
import createDebug from 'debug' | ||
import Redis from 'ioredis' | ||
import { acquireLua } from '../semaphore/acquire/lua' | ||
import type { RedisClient } from '../types' | ||
@@ -16,3 +16,3 @@ import { refreshLua } from '../semaphore/refresh/lua' | ||
export async function refreshRedlockSemaphore( | ||
clients: Redis[], | ||
clients: RedisClient[], | ||
key: string, | ||
@@ -39,3 +39,3 @@ limit: number, | ||
const promises = results | ||
.reduce<Redis[]>((failedClients, result, index) => { | ||
.reduce<RedisClient[]>((failedClients, result, index) => { | ||
if (!result) { | ||
@@ -42,0 +42,0 @@ failedClients.push(clients[index]) |
import createDebug from 'debug' | ||
import Redis from 'ioredis' | ||
import type { RedisClient } from '../types' | ||
@@ -7,3 +7,3 @@ const debug = createDebug('redis-semaphore:redlock-mutex:release') | ||
export async function releaseRedlockSemaphore( | ||
clients: Redis[], | ||
clients: RedisClient[], | ||
key: string, | ||
@@ -10,0 +10,0 @@ identifier: string |
import createDebug from 'debug' | ||
import Redis from 'ioredis' | ||
import { RedisClient } from '../../types' | ||
import { delay } from '../../utils/index' | ||
import { delay } from '../../utils' | ||
import { acquireLua } from './lua' | ||
@@ -18,3 +18,3 @@ | ||
export async function acquireSemaphore( | ||
client: Redis, | ||
client: RedisClient, | ||
key: string, | ||
@@ -21,0 +21,0 @@ limit: number, |
import createDebug from 'debug' | ||
import Redis from 'ioredis' | ||
import { RedisClient } from '../../types' | ||
@@ -14,3 +14,3 @@ import { refreshLua } from './lua' | ||
export async function refreshSemaphore( | ||
client: Redis, | ||
client: RedisClient, | ||
key: string, | ||
@@ -17,0 +17,0 @@ limit: number, |
import createDebug from 'debug' | ||
import Redis from 'ioredis' | ||
import { RedisClient } from '../types' | ||
@@ -7,3 +7,3 @@ const debug = createDebug('redis-semaphore:semaphore:release') | ||
export async function releaseSemaphore( | ||
client: Redis, | ||
client: RedisClient, | ||
key: string, | ||
@@ -10,0 +10,0 @@ identifier: string |
import LostLockError from './errors/LostLockError' | ||
import { Lock } from './Lock' | ||
import type * as ioredis from 'ioredis' | ||
/** | ||
* ioredis-like Redis client | ||
*/ | ||
export type RedisClient = Pick< | ||
ioredis.Redis, | ||
'eval' | 'evalsha' | 'get' | 'set' | 'zrem' | ||
> & | ||
Partial<Pick<ioredis.Redis, 'options'>> | ||
export interface LockLostCallback { | ||
@@ -5,0 +16,0 @@ (this: Lock, err: LostLockError): void |
import { createHash } from 'crypto' | ||
import createDebug from 'debug' | ||
import Redis from 'ioredis' | ||
import { RedisClient } from '../types' | ||
@@ -24,3 +24,3 @@ import { getConnectionName } from './index' | ||
return async function optimizedEval( | ||
client: Redis, | ||
client: RedisClient, | ||
args: Args | ||
@@ -27,0 +27,0 @@ ): Promise<Result> { |
@@ -1,2 +0,2 @@ | ||
import Redis from 'ioredis' | ||
import { RedisClient } from '../types' | ||
import createEval from './createEval' | ||
@@ -10,6 +10,5 @@ | ||
export function getConnectionName(client: Redis) { | ||
return client instanceof Redis && client.options.connectionName | ||
? `<${client.options.connectionName}>` | ||
: '<unknown client>' | ||
export function getConnectionName(client: RedisClient) { | ||
const connectionName = client.options?.connectionName | ||
return connectionName ? `<${connectionName}>` : '<unknown client>' | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
154177
0.25%446
2.76%30
15.38%2732
-0.69%