diff --git a/types/redlock/index.d.ts b/types/redlock/index.d.ts index 1e00de6ed1..3cd1bf7d2e 100644 --- a/types/redlock/index.d.ts +++ b/types/redlock/index.d.ts @@ -1,24 +1,22 @@ -// Type definitions for Redlock +// Type definitions for redlock 3.0 // Project: https://github.com/mike-marcacci/node-redlock // Definitions by: Ilya Mochalov +// BendingBender // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 2.3 -import * as redis from 'redis'; import * as Promise from 'bluebird'; +import { EventEmitter } from 'events'; export = Redlock; declare namespace Redlock { - interface Callback { - (err: any, value?: T): void; - } + type Callback = (err: any, value?: T) => void; interface Lock { - redlock: Redlock; resource: string; - value: any; + value: string | null; expiration: number; unlock(callback?: Callback): Promise; @@ -30,30 +28,50 @@ declare namespace Redlock { driftFactor?: number; retryCount?: number; retryDelay?: number; + retryJitter?: number; + lockScript?(origLockScript: string): string; + unlockScript?(origUnlockScript: string): string; + extendScript?(origExtendScript: string): string; } - interface LockError extends Error { } + interface LockErrorConstructor { + new(message?: string): LockError; + (message?: string): LockError; + readonly prototype: LockError; + } + + interface LockError extends Error { + readonly name: 'LockError'; + } + + interface CompatibleRedisClient { + eval(args: any[], callback?: (err: Error | null, res: any) => void): any; + eval(...args: any[]): any; + } } -declare class Redlock { - LockError: Redlock.LockError; - +declare class Redlock extends EventEmitter { + LockError: Redlock.LockErrorConstructor; driftFactor: number; retryCount: number; retryDelay: number; + retryJitter: number; + servers: Redlock.CompatibleRedisClient[]; - servers: redis.RedisClient[]; - - constructor(clients: any[], options?: Redlock.Options); + constructor(clients: Redlock.CompatibleRedisClient[], options?: Redlock.Options); acquire(resource: string, ttl: number, callback?: Redlock.Callback): Promise; lock(resource: string, ttl: number, callback?: Redlock.Callback): Promise; - disposer(resource: string, ttl: number, errorHandler?: Redlock.Callback): any; // bluebird Disposer + disposer(resource: string, ttl: number, errorHandler?: Redlock.Callback): Promise.Disposer; release(lock: Redlock.Lock, callback?: Redlock.Callback): Promise; unlock(lock: Redlock.Lock, callback?: Redlock.Callback): Promise; extend(lock: Redlock.Lock, ttl: number, callback?: Redlock.Callback): Promise; - _lock(resource: string, value: string, ttl: number, callback?: Redlock.Callback): Promise; + + addListener(event: 'clientError', listener: (err: any) => void): this; + on(event: 'clientError', listener: (err: any) => void): this; + once(event: 'clientError', listener: (err: any) => void): this; + removeListener(event: 'clientError', listener: (err: any) => void): this; } diff --git a/types/redlock/redlock-tests.ts b/types/redlock/redlock-tests.ts index 3b2c8f25f7..8a36679fe7 100644 --- a/types/redlock/redlock-tests.ts +++ b/types/redlock/redlock-tests.ts @@ -1,38 +1,97 @@ -import * as Redlock from 'redlock'; -import { Callback as NodeifyCallback, Options, Lock } from 'redlock'; -import * as Promise from 'bluebird'; +import Redlock = require('redlock'); +import { Lock } from 'redlock'; import { RedisClient } from 'redis'; +import IoRedisClient = require('ioredis'); +import { using } from 'bluebird'; -let redlock: Redlock; -let client: RedisClient; -let lock: Lock; +let lock: Lock = {}; -redlock = new Redlock([client]); -redlock = new Redlock([client], { - driftFactor: 0.1, - retryCount: 2, - retryDelay: 3 +const client1 = new RedisClient({port: 6379, host: 'redis1.example.com'}); +const client2 = new RedisClient({port: 6379, host: 'redis2.example.com'}); +const client3 = new IoRedisClient({port: 6379, host: 'redis3.example.com'}); + +const redlock = new Redlock( + [client1, client2, client3], + { + driftFactor: 0.01, + retryCount: 10, + retryDelay: 200, + retryJitter: 200 + } +); + +redlock.on('clientError', (err) => { + console.error('A redis error has occurred:', err); }); -redlock.acquire('resource', 30).then((lock: Lock) => { }); -redlock.acquire('resource', 30, (err: any, lock: Lock) => { }); -redlock.lock('resource', 30).then((lock: Lock) => { }); -redlock.lock('resource', 30, (err: any, lock: Lock) => { }); +redlock.acquire('resource', 30).then((lock: Lock) => {}); +redlock.acquire('resource', 30, (err: any, lock: Lock) => {}); +redlock.lock('resource', 30).then((lock: Lock) => {}); +redlock.lock('resource', 30, (err: any, lock: Lock) => {}); -// There is currently no way to test the disposer as the bluebird typings does not -// expose the .using method. -// promise.using(redlock.disposer('resource', 30), (lock: Lock) => {}); +using(redlock.disposer('locks:account:322456', 1000, err => console.error(err)), (lock) => { + return Promise.resolve(); +}); +using(redlock.disposer('locks:account:322456', 1000, err => console.error(err)), (lock) => { + return lock.extend(1000).then((extended: Lock) => {}); +}); redlock.release(lock); -redlock.release(lock, (err: any) => { }); +redlock.release(lock, (err: any) => {}); redlock.unlock(lock); -redlock.unlock(lock, (err: any) => { }); +redlock.unlock(lock, (err: any) => {}); -redlock.extend(lock, 30).then((lock: Lock) => { }); -redlock.extend(lock, 30, (err: any, lock: Lock) => { }); +redlock.extend(lock, 30).then((lock: Lock) => {}); +redlock.extend(lock, 30, (err: any, lock: Lock) => {}); lock.unlock(); -lock.unlock((err) => { }); +lock.unlock((err) => {}); -lock.extend(30).then((lock: Lock) => { }); -lock.extend(30, (err: any, lock: Lock) => { }); +lock.extend(30).then((lock: Lock) => {}); +lock.extend(30, (err: any, lock: Lock) => {}); + +redlock.lock('locks:account:322456', 1000).then((lock) => { + return lock + .unlock() + .catch((err) => { + console.error(err); + }); +}); + +redlock.lock('locks:account:322456', 1000).then(lock => { + return lock + .extend(1000) + .then(lock => { + return lock + .unlock() + .catch(err => { + console.error(err); + }); + }); +}); + +redlock.lock('locks:account:322456', 1000, (err, lock) => { + if (err || !lock) { + } else { + lock.unlock(err => { + console.error(err); + }); + } +}); + +redlock.lock('locks:account:322456', 1000, (err, lock) => { + if (err || !lock) { + } else { + lock.extend(1000, (err, lock) => { + if (err || !lock) { + } else { + lock.unlock(); + } + }); + } +}); + +new Error() instanceof redlock.LockError; + +redlock.LockError.prototype; +const lockError: Redlock.LockError = new redlock.LockError(); diff --git a/types/redlock/tsconfig.json b/types/redlock/tsconfig.json index 827a006b43..dff5c324f6 100644 --- a/types/redlock/tsconfig.json +++ b/types/redlock/tsconfig.json @@ -6,7 +6,7 @@ ], "noImplicitAny": true, "noImplicitThis": true, - "strictNullChecks": false, + "strictNullChecks": true, "baseUrl": "../", "typeRoots": [ "../" @@ -19,4 +19,4 @@ "index.d.ts", "redlock-tests.ts" ] -} \ No newline at end of file +} diff --git a/types/redlock/tslint.json b/types/redlock/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/redlock/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" } diff --git a/types/redlock/v2/index.d.ts b/types/redlock/v2/index.d.ts new file mode 100644 index 0000000000..5ef9bb80c1 --- /dev/null +++ b/types/redlock/v2/index.d.ts @@ -0,0 +1,64 @@ +// Type definitions for redlock 2.x +// Project: https://github.com/mike-marcacci/node-redlock +// Definitions by: Ilya Mochalov +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.3 + +import * as redis from 'redis'; +import * as Promise from 'bluebird'; + +export = Redlock; + +declare namespace Redlock { + type Callback = (err: any, value?: T) => void; + + interface Lock { + redlock: Redlock; + resource: string; + value: any; + expiration: number; + + unlock(callback?: Callback): Promise; + + extend(ttl: number, callback?: Callback): Promise; + } + + interface Options { + driftFactor?: number; + retryCount?: number; + retryDelay?: number; + } + + interface LockErrorConstructor { + new(message?: string): LockError; + (message?: string): LockError; + readonly prototype: LockError; + } + + interface LockError extends Error { + readonly name: 'LockError'; + } +} + +declare class Redlock { + LockError: Redlock.LockErrorConstructor; + + driftFactor: number; + retryCount: number; + retryDelay: number; + + servers: redis.RedisClient[]; + + constructor(clients: any[], options?: Redlock.Options); + + acquire(resource: string, ttl: number, callback?: Redlock.Callback): Promise; + lock(resource: string, ttl: number, callback?: Redlock.Callback): Promise; + + disposer(resource: string, ttl: number, errorHandler?: Redlock.Callback): any; // bluebird Disposer + + release(lock: Redlock.Lock, callback?: Redlock.Callback): Promise; + unlock(lock: Redlock.Lock, callback?: Redlock.Callback): Promise; + + extend(lock: Redlock.Lock, ttl: number, callback?: Redlock.Callback): Promise; + _lock(resource: string, value: string, ttl: number, callback?: Redlock.Callback): Promise; +} diff --git a/types/redlock/v2/redlock-tests.ts b/types/redlock/v2/redlock-tests.ts new file mode 100644 index 0000000000..8b1c83c282 --- /dev/null +++ b/types/redlock/v2/redlock-tests.ts @@ -0,0 +1,37 @@ +import * as Redlock from 'redlock'; +import { Lock } from 'redlock'; +import { RedisClient } from 'redis'; + +let redlock: Redlock; +let client: RedisClient = {}; +let lock: Lock = {}; + +redlock = new Redlock([client]); +redlock = new Redlock([client], { + driftFactor: 0.1, + retryCount: 2, + retryDelay: 3 +}); + +redlock.acquire('resource', 30).then((lock: Lock) => {}); +redlock.acquire('resource', 30, (err: any, lock: Lock) => {}); +redlock.lock('resource', 30).then((lock: Lock) => {}); +redlock.lock('resource', 30, (err: any, lock: Lock) => {}); + +// There is currently no way to test the disposer as the bluebird typings does not +// expose the .using method. +// promise.using(redlock.disposer('resource', 30), (lock: Lock) => {}); + +redlock.release(lock); +redlock.release(lock, (err: any) => {}); +redlock.unlock(lock); +redlock.unlock(lock, (err: any) => {}); + +redlock.extend(lock, 30).then((lock: Lock) => {}); +redlock.extend(lock, 30, (err: any, lock: Lock) => {}); + +lock.unlock(); +lock.unlock((err) => {}); + +lock.extend(30).then((lock: Lock) => {}); +lock.extend(30, (err: any, lock: Lock) => {}); diff --git a/types/redlock/v2/tsconfig.json b/types/redlock/v2/tsconfig.json new file mode 100644 index 0000000000..0ae54b3474 --- /dev/null +++ b/types/redlock/v2/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "baseUrl": "../../", + "typeRoots": [ + "../../" + ], + "paths": { + "redlock": [ "redlock/v2" ] + }, + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "redlock-tests.ts" + ] +} diff --git a/types/redlock/v2/tslint.json b/types/redlock/v2/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/redlock/v2/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" }