@jsnw/nestjs-ioredis 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,263 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+ //#endregion
24
+ let _nestjs_common = require("@nestjs/common");
25
+ let ioredis = require("ioredis");
26
+ ioredis = __toESM(ioredis);
27
+ let node_crypto = require("node:crypto");
28
+ let node_timers_promises = require("node:timers/promises");
29
+ let dedent = require("dedent");
30
+ dedent = __toESM(dedent);
31
+ //#region src/redis.consts.ts
32
+ const REDIS_OPTIONS_TOKEN = Symbol("REDIS_OPTIONS");
33
+ //#endregion
34
+ //#region src/redis.helpers.ts
35
+ /**
36
+ * @param {string} prefix
37
+ * @return {string}
38
+ */
39
+ const resolveKeyPrefix = (prefix) => {
40
+ if (!prefix) return "";
41
+ prefix = prefix.trim();
42
+ if (prefix.endsWith(":")) {
43
+ if (prefix.length === 1) return "";
44
+ return prefix;
45
+ }
46
+ return prefix + ":";
47
+ };
48
+ /**
49
+ * @param {number} iteration
50
+ * @param {RedisLockWaitAcquireParams["retryInterval"]} [retryInterval]
51
+ * @return {number}
52
+ */
53
+ const getRetryInterval = (iteration, retryInterval) => {
54
+ if (retryInterval === void 0) return 500;
55
+ if (typeof retryInterval === "number") return Math.max(1, retryInterval);
56
+ if (Array.isArray(retryInterval)) {
57
+ if (retryInterval.length === 0) return 500;
58
+ if (retryInterval.length === 1) return retryInterval[0];
59
+ return iteration < retryInterval.length ? retryInterval[iteration] : retryInterval[retryInterval.length - 1];
60
+ }
61
+ if (typeof retryInterval === "function") return Math.max(1, retryInterval(iteration) ?? 500);
62
+ return 500;
63
+ };
64
+ //#endregion
65
+ //#region src/redis-lock.ts
66
+ var RedisLock = class {
67
+ redis;
68
+ locksHashKey;
69
+ name;
70
+ value;
71
+ acquireLockPromise = null;
72
+ /**
73
+ * @param {Redis} redis
74
+ * @param {string} name
75
+ * @param {string} locksHashKey
76
+ * @protected
77
+ */
78
+ constructor(redis, name, locksHashKey) {
79
+ this.redis = redis;
80
+ this.name = name;
81
+ this.locksHashKey = locksHashKey;
82
+ this.value = (0, node_crypto.randomUUID)();
83
+ }
84
+ /**
85
+ * @param {RedisLockWaitAcquireParams} params
86
+ * @return {Promise<boolean>}
87
+ */
88
+ async waitAcquire(params) {
89
+ const startedAt = Date.now();
90
+ let iteration = 0;
91
+ while (true) {
92
+ const acquired = await this.acquire(params.lockTTL), RETRY_DELAY_MS = getRetryInterval(iteration, params.retryInterval);
93
+ if (acquired) return true;
94
+ if (params.signal?.aborted) return false;
95
+ let delayMs = RETRY_DELAY_MS;
96
+ if (params.waitTimeout !== void 0) {
97
+ const elapsed = Date.now() - startedAt, timeLeft = params.waitTimeout - elapsed;
98
+ if (timeLeft <= 0) return false;
99
+ delayMs = Math.max(1, Math.min(RETRY_DELAY_MS, timeLeft));
100
+ }
101
+ try {
102
+ await (0, node_timers_promises.setTimeout)(delayMs, void 0, { signal: params.signal });
103
+ } catch (e) {
104
+ if (e instanceof Error && e.name === "AbortError") return false;
105
+ throw e;
106
+ }
107
+ }
108
+ }
109
+ /**
110
+ * @param {number} ttlMs
111
+ * @return {Promise<boolean>}
112
+ */
113
+ acquire(ttlMs) {
114
+ if (this.acquireLockPromise) return this.acquireLockPromise;
115
+ this.acquireLockPromise = new Promise((resolve, reject) => {
116
+ this.redis.call("HSETEX", this.locksHashKey, "FNX", "PX", ttlMs, "FIELDS", 1, this.name, this.value).then((res) => {
117
+ if (res === 1) return resolve(true);
118
+ return resolve(false);
119
+ }).catch(reject);
120
+ });
121
+ this.acquireLockPromise.finally(() => {
122
+ this.acquireLockPromise = null;
123
+ });
124
+ return this.acquireLockPromise;
125
+ }
126
+ /**
127
+ * @return {Promise<void>}
128
+ */
129
+ async release() {
130
+ await this.redis.eval(dedent.default`
131
+ if redis.call("hget", KEYS[1], ARGV[1]) == ARGV[2]
132
+ then
133
+ return redis.call("hdel", KEYS[1], ARGV[1])
134
+ else
135
+ return 0
136
+ end
137
+ `, 1, this.locksHashKey, this.name, this.value);
138
+ }
139
+ };
140
+ //#endregion
141
+ //#region \0@oxc-project+runtime@0.137.0/helpers/esm/decorateMetadata.js
142
+ function __decorateMetadata(k, v) {
143
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
144
+ }
145
+ //#endregion
146
+ //#region \0@oxc-project+runtime@0.137.0/helpers/esm/decorateParam.js
147
+ function __decorateParam(paramIndex, decorator) {
148
+ return function(target, key) {
149
+ decorator(target, key, paramIndex);
150
+ };
151
+ }
152
+ //#endregion
153
+ //#region \0@oxc-project+runtime@0.137.0/helpers/esm/decorate.js
154
+ function __decorate(decorators, target, key, desc) {
155
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
156
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
157
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
158
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
159
+ }
160
+ //#endregion
161
+ //#region src/redis-lock.factory.ts
162
+ let RedisLockFactory = class RedisLockFactory {
163
+ options;
164
+ redis;
165
+ /**
166
+ * @param {RedisRegisterOptions} options
167
+ * @param {Redis} redis
168
+ */
169
+ constructor(options, redis) {
170
+ this.options = options;
171
+ this.redis = redis;
172
+ }
173
+ /**
174
+ * @param {string} name
175
+ * @return {RedisLock}
176
+ */
177
+ create(name) {
178
+ return new RedisLock(this.redis, name, this.options.locksHashKey);
179
+ }
180
+ };
181
+ RedisLockFactory = __decorate([
182
+ (0, _nestjs_common.Injectable)(),
183
+ __decorateParam(0, (0, _nestjs_common.Inject)(REDIS_OPTIONS_TOKEN)),
184
+ __decorateMetadata("design:paramtypes", [Object, typeof ioredis.default === "undefined" ? Object : ioredis.default])
185
+ ], RedisLockFactory);
186
+ //#endregion
187
+ //#region src/redis-core.module.ts
188
+ var _RedisCoreModule;
189
+ let RedisCoreModule = _RedisCoreModule = class RedisCoreModule {
190
+ /**
191
+ * @param {RedisRegisterOptions} options
192
+ * @return {DynamicModule}
193
+ */
194
+ static register(options) {
195
+ const optionsProvider = this.createOptionsProvider(options), redisProvider = this.createRedisProvider();
196
+ return {
197
+ module: _RedisCoreModule,
198
+ providers: [
199
+ optionsProvider,
200
+ redisProvider,
201
+ RedisLockFactory
202
+ ],
203
+ exports: [redisProvider, RedisLockFactory]
204
+ };
205
+ }
206
+ /**
207
+ * @param {RedisRegisterOptions} options
208
+ * @return {ValueProvider}
209
+ * @private
210
+ */
211
+ static createOptionsProvider(options) {
212
+ return {
213
+ provide: REDIS_OPTIONS_TOKEN,
214
+ useValue: {
215
+ ...options,
216
+ keyPrefix: resolveKeyPrefix(options.keyPrefix),
217
+ locksHashKey: options.locksHashKey ?? "__locks__"
218
+ }
219
+ };
220
+ }
221
+ /**
222
+ * @return {FactoryProvider}
223
+ * @private
224
+ */
225
+ static createRedisProvider() {
226
+ return {
227
+ provide: ioredis.default,
228
+ useFactory: (options) => new ioredis.default(options),
229
+ inject: [REDIS_OPTIONS_TOKEN]
230
+ };
231
+ }
232
+ };
233
+ RedisCoreModule = _RedisCoreModule = __decorate([(0, _nestjs_common.Global)(), (0, _nestjs_common.Module)({})], RedisCoreModule);
234
+ //#endregion
235
+ //#region src/redis.module.ts
236
+ var _RedisModule;
237
+ let RedisModule = _RedisModule = class RedisModule {
238
+ /**
239
+ * @param {RedisRegisterOptions} options
240
+ * @return {DynamicModule}
241
+ */
242
+ static register(options) {
243
+ return {
244
+ module: _RedisModule,
245
+ imports: [RedisCoreModule.register(options)]
246
+ };
247
+ }
248
+ };
249
+ RedisModule = _RedisModule = __decorate([(0, _nestjs_common.Module)({})], RedisModule);
250
+ //#endregion
251
+ exports.RedisLock = RedisLock;
252
+ Object.defineProperty(exports, "RedisLockFactory", {
253
+ enumerable: true,
254
+ get: function() {
255
+ return RedisLockFactory;
256
+ }
257
+ });
258
+ Object.defineProperty(exports, "RedisModule", {
259
+ enumerable: true,
260
+ get: function() {
261
+ return RedisModule;
262
+ }
263
+ });
@@ -0,0 +1,75 @@
1
+ import { DynamicModule } from "@nestjs/common";
2
+ import Redis, { RedisOptions } from "ioredis";
3
+
4
+ //#region src/redis.types.d.ts
5
+ type RedisRegisterOptions = RedisOptions & {
6
+ keyPrefix?: string;
7
+ locksHashKey?: string;
8
+ };
9
+ //#endregion
10
+ //#region src/redis.module.d.ts
11
+ declare class RedisModule {
12
+ /**
13
+ * @param {RedisRegisterOptions} options
14
+ * @return {DynamicModule}
15
+ */
16
+ static register(options: RedisRegisterOptions): DynamicModule;
17
+ }
18
+ //#endregion
19
+ //#region src/redis-lock.d.ts
20
+ type RedisLockWaitAcquireParams = {
21
+ lockTTL: number;
22
+ retryInterval?: number | number[] | ((iteration: number) => number);
23
+ } & ({
24
+ signal: AbortSignal;
25
+ waitTimeout?: number;
26
+ } | {
27
+ signal?: AbortSignal;
28
+ waitTimeout: number;
29
+ });
30
+ declare class RedisLock {
31
+ private readonly redis;
32
+ private readonly locksHashKey;
33
+ readonly name: string;
34
+ private readonly value;
35
+ private acquireLockPromise;
36
+ /**
37
+ * @param {Redis} redis
38
+ * @param {string} name
39
+ * @param {string} locksHashKey
40
+ * @protected
41
+ */
42
+ constructor(redis: Redis, name: string, locksHashKey: string);
43
+ /**
44
+ * @param {RedisLockWaitAcquireParams} params
45
+ * @return {Promise<boolean>}
46
+ */
47
+ waitAcquire(params: RedisLockWaitAcquireParams): Promise<boolean>;
48
+ /**
49
+ * @param {number} ttlMs
50
+ * @return {Promise<boolean>}
51
+ */
52
+ acquire(ttlMs: number): Promise<boolean>;
53
+ /**
54
+ * @return {Promise<void>}
55
+ */
56
+ release(): Promise<void>;
57
+ }
58
+ //#endregion
59
+ //#region src/redis-lock.factory.d.ts
60
+ declare class RedisLockFactory {
61
+ private readonly options;
62
+ private readonly redis;
63
+ /**
64
+ * @param {RedisRegisterOptions} options
65
+ * @param {Redis} redis
66
+ */
67
+ constructor(options: RedisRegisterOptions, redis: Redis);
68
+ /**
69
+ * @param {string} name
70
+ * @return {RedisLock}
71
+ */
72
+ create(name: string): RedisLock;
73
+ }
74
+ //#endregion
75
+ export { RedisLock, RedisLockFactory, type RedisLockWaitAcquireParams, RedisModule, type RedisRegisterOptions };
package/package.json CHANGED
@@ -1,23 +1,13 @@
1
1
  {
2
2
  "name": "@jsnw/nestjs-ioredis",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "NestJS module for integrating Redis",
5
- "main": "./dist/lib/index.js",
6
- "types": "./dist/types/index.d.ts",
7
5
  "exports": {
8
- ".": {
9
- "require": "./dist/lib/index.js",
10
- "types": "./dist/types/index.d.ts"
6
+ "require": {
7
+ "default": "./dist/index.cjs",
8
+ "types": "./dist/index.d.cts"
11
9
  }
12
10
  },
13
- "scripts": {
14
- "clean": "rimraf ./dist",
15
- "build": "npm run clean && tsc -p tsconfig.json",
16
- "test": "jest --passWithNoTests",
17
- "test:watch": "jest --watch",
18
- "test:coverage": "jest --coverage",
19
- "prepublishOnly": "npm run build"
20
- },
21
11
  "files": [
22
12
  "./dist",
23
13
  "README.md"
@@ -40,19 +30,20 @@
40
30
  "email": "jsnow0177@gmail.com"
41
31
  },
42
32
  "license": "MIT",
33
+ "dependencies": {
34
+ "dedent": "^1.7.2"
35
+ },
43
36
  "peerDependencies": {
44
- "@nestjs/common": "^11.1.14",
45
- "ioredis": "^5.9.3"
37
+ "@nestjs/common": "^11.1.27",
38
+ "ioredis": "^5.11.1"
46
39
  },
47
40
  "devDependencies": {
48
- "@nestjs/common": "^11.1.14",
49
- "ioredis": "^5.9.3",
50
- "jest": "^30.2.0",
51
- "rimraf": "^6.1.3",
52
- "ts-jest": "^29.4.6",
41
+ "@nestjs/common": "^11.1.27",
42
+ "ioredis": "^5.11.1",
43
+ "tsdown": "^0.22.3",
53
44
  "typescript": "^5.9.3"
54
45
  },
55
- "dependencies": {
56
- "dedent": "^1.7.1"
46
+ "scripts": {
47
+ "build": "tsdown"
57
48
  }
58
- }
49
+ }
package/dist/lib/index.js DELETED
@@ -1,9 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RedisLock = exports.RedisLockFactory = exports.RedisModule = void 0;
4
- var redis_module_1 = require("./redis.module");
5
- Object.defineProperty(exports, "RedisModule", { enumerable: true, get: function () { return redis_module_1.RedisModule; } });
6
- var redis_lock_factory_1 = require("./redis-lock.factory");
7
- Object.defineProperty(exports, "RedisLockFactory", { enumerable: true, get: function () { return redis_lock_factory_1.RedisLockFactory; } });
8
- var redis_lock_1 = require("./redis-lock");
9
- Object.defineProperty(exports, "RedisLock", { enumerable: true, get: function () { return redis_lock_1.RedisLock; } });
@@ -1,70 +0,0 @@
1
- "use strict";
2
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
- return c > 3 && r && Object.defineProperty(target, key, r), r;
7
- };
8
- var __importDefault = (this && this.__importDefault) || function (mod) {
9
- return (mod && mod.__esModule) ? mod : { "default": mod };
10
- };
11
- var RedisCoreModule_1;
12
- Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.RedisCoreModule = void 0;
14
- const common_1 = require("@nestjs/common");
15
- const ioredis_1 = __importDefault(require("ioredis"));
16
- const redis_consts_1 = require("./redis.consts");
17
- const redis_helpers_1 = require("./redis.helpers");
18
- const redis_lock_factory_1 = require("./redis-lock.factory");
19
- let RedisCoreModule = RedisCoreModule_1 = class RedisCoreModule {
20
- /**
21
- * @param {RedisRegisterOptions} options
22
- * @return {DynamicModule}
23
- */
24
- static register(options) {
25
- const optionsProvider = this.createOptionsProvider(options), redisProvider = this.createRedisProvider();
26
- return {
27
- module: RedisCoreModule_1,
28
- providers: [
29
- optionsProvider,
30
- redisProvider,
31
- redis_lock_factory_1.RedisLockFactory
32
- ],
33
- exports: [
34
- redisProvider,
35
- redis_lock_factory_1.RedisLockFactory
36
- ]
37
- };
38
- }
39
- /**
40
- * @param {RedisRegisterOptions} options
41
- * @return {ValueProvider}
42
- * @private
43
- */
44
- static createOptionsProvider(options) {
45
- return {
46
- provide: redis_consts_1.REDIS_OPTIONS_TOKEN,
47
- useValue: {
48
- ...options,
49
- keyPrefix: (0, redis_helpers_1.resolveKeyPrefix)(options.keyPrefix),
50
- locksHashKey: options.locksHashKey ?? redis_consts_1.REDIS_DEFAULT_LOCKS_HASH_KEY
51
- }
52
- };
53
- }
54
- /**
55
- * @return {FactoryProvider}
56
- * @private
57
- */
58
- static createRedisProvider() {
59
- return {
60
- provide: ioredis_1.default,
61
- useFactory: (options) => new ioredis_1.default(options),
62
- inject: [redis_consts_1.REDIS_OPTIONS_TOKEN]
63
- };
64
- }
65
- };
66
- exports.RedisCoreModule = RedisCoreModule;
67
- exports.RedisCoreModule = RedisCoreModule = RedisCoreModule_1 = __decorate([
68
- (0, common_1.Global)(),
69
- (0, common_1.Module)({})
70
- ], RedisCoreModule);
@@ -1,47 +0,0 @@
1
- "use strict";
2
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
- return c > 3 && r && Object.defineProperty(target, key, r), r;
7
- };
8
- var __metadata = (this && this.__metadata) || function (k, v) {
9
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
- };
11
- var __param = (this && this.__param) || function (paramIndex, decorator) {
12
- return function (target, key) { decorator(target, key, paramIndex); }
13
- };
14
- var __importDefault = (this && this.__importDefault) || function (mod) {
15
- return (mod && mod.__esModule) ? mod : { "default": mod };
16
- };
17
- Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.RedisLockFactory = void 0;
19
- const common_1 = require("@nestjs/common");
20
- const ioredis_1 = __importDefault(require("ioredis"));
21
- const redis_consts_1 = require("./redis.consts");
22
- const redis_lock_1 = require("./redis-lock");
23
- let RedisLockFactory = class RedisLockFactory {
24
- options;
25
- redis;
26
- /**
27
- * @param {RedisRegisterOptions} options
28
- * @param {Redis} redis
29
- */
30
- constructor(options, redis) {
31
- this.options = options;
32
- this.redis = redis;
33
- }
34
- /**
35
- * @param {string} name
36
- * @return {RedisLock}
37
- */
38
- create(name) {
39
- return new redis_lock_1.RedisLock(this.redis, name, this.options.locksHashKey);
40
- }
41
- };
42
- exports.RedisLockFactory = RedisLockFactory;
43
- exports.RedisLockFactory = RedisLockFactory = __decorate([
44
- (0, common_1.Injectable)(),
45
- __param(0, (0, common_1.Inject)(redis_consts_1.REDIS_OPTIONS_TOKEN)),
46
- __metadata("design:paramtypes", [Object, ioredis_1.default])
47
- ], RedisLockFactory);
@@ -1,94 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.RedisLock = void 0;
7
- const node_crypto_1 = require("node:crypto");
8
- const promises_1 = require("node:timers/promises");
9
- const dedent_1 = __importDefault(require("dedent"));
10
- const redis_helpers_1 = require("./redis.helpers");
11
- class RedisLock {
12
- redis;
13
- locksHashKey;
14
- name;
15
- value;
16
- acquireLockPromise = null;
17
- /**
18
- * @param {Redis} redis
19
- * @param {string} name
20
- * @param {string} locksHashKey
21
- * @protected
22
- */
23
- constructor(redis, name, locksHashKey) {
24
- this.redis = redis;
25
- this.name = name;
26
- this.locksHashKey = locksHashKey;
27
- this.value = (0, node_crypto_1.randomUUID)();
28
- }
29
- /**
30
- * @param {RedisLockWaitAcquireParams} params
31
- * @return {Promise<boolean>}
32
- */
33
- async waitAcquire(params) {
34
- const startedAt = Date.now();
35
- let iteration = 0;
36
- while (true) {
37
- const acquired = await this.acquire(params.lockTTL), RETRY_DELAY_MS = (0, redis_helpers_1.getRetryInterval)(iteration, params.retryInterval);
38
- if (acquired)
39
- return true;
40
- if (params.signal?.aborted)
41
- return false;
42
- let delayMs = RETRY_DELAY_MS;
43
- if (params.waitTimeout !== undefined) {
44
- const elapsed = Date.now() - startedAt, timeLeft = params.waitTimeout - elapsed;
45
- if (timeLeft <= 0)
46
- return false;
47
- delayMs = Math.max(1, Math.min(RETRY_DELAY_MS, timeLeft));
48
- }
49
- try {
50
- await (0, promises_1.setTimeout)(delayMs, undefined, { signal: params.signal });
51
- }
52
- catch (e) {
53
- if (e instanceof Error && e.name === 'AbortError')
54
- return false;
55
- throw e;
56
- }
57
- }
58
- }
59
- /**
60
- * @param {number} ttlMs
61
- * @return {Promise<boolean>}
62
- */
63
- acquire(ttlMs) {
64
- if (this.acquireLockPromise)
65
- return this.acquireLockPromise;
66
- this.acquireLockPromise = new Promise((resolve, reject) => {
67
- this.redis.call('HSETEX', this.locksHashKey, 'FNX', 'PX', ttlMs, 'FIELDS', 1, this.name, this.value)
68
- .then(res => {
69
- if (res === 1)
70
- return resolve(true);
71
- return resolve(false);
72
- })
73
- .catch(reject);
74
- });
75
- this.acquireLockPromise.finally(() => {
76
- this.acquireLockPromise = null;
77
- });
78
- return this.acquireLockPromise;
79
- }
80
- /**
81
- * @return {Promise<void>}
82
- */
83
- async release() {
84
- await this.redis.eval((0, dedent_1.default) `
85
- if redis.call("hget", KEYS[1], ARGV[1]) == ARGV[2]
86
- then
87
- return redis.call("hdel", KEYS[1], ARGV[1])
88
- else
89
- return 0
90
- end
91
- `, 1, this.locksHashKey, this.name, this.value);
92
- }
93
- }
94
- exports.RedisLock = RedisLock;
@@ -1,6 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.REDIS_DEFAULT_LOCK_ACQUIRE_RETRY_DELAY_MS = exports.REDIS_DEFAULT_LOCKS_HASH_KEY = exports.REDIS_OPTIONS_TOKEN = void 0;
4
- exports.REDIS_OPTIONS_TOKEN = Symbol('REDIS_OPTIONS');
5
- exports.REDIS_DEFAULT_LOCKS_HASH_KEY = '__locks__';
6
- exports.REDIS_DEFAULT_LOCK_ACQUIRE_RETRY_DELAY_MS = 500;
@@ -1,44 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getRetryInterval = exports.resolveKeyPrefix = void 0;
4
- const redis_consts_1 = require("./redis.consts");
5
- /**
6
- * @param {string} prefix
7
- * @return {string}
8
- */
9
- const resolveKeyPrefix = (prefix) => {
10
- if (!prefix)
11
- return '';
12
- prefix = prefix.trim();
13
- if (prefix.endsWith(':')) {
14
- if (prefix.length === 1)
15
- return '';
16
- return prefix;
17
- }
18
- return prefix + ':';
19
- };
20
- exports.resolveKeyPrefix = resolveKeyPrefix;
21
- /**
22
- * @param {number} iteration
23
- * @param {RedisLockWaitAcquireParams["retryInterval"]} [retryInterval]
24
- * @return {number}
25
- */
26
- const getRetryInterval = (iteration, retryInterval) => {
27
- if (retryInterval === undefined)
28
- return redis_consts_1.REDIS_DEFAULT_LOCK_ACQUIRE_RETRY_DELAY_MS;
29
- if (typeof retryInterval === 'number')
30
- return Math.max(1, retryInterval);
31
- if (Array.isArray(retryInterval)) {
32
- if (retryInterval.length === 0)
33
- return redis_consts_1.REDIS_DEFAULT_LOCK_ACQUIRE_RETRY_DELAY_MS;
34
- if (retryInterval.length === 1)
35
- return retryInterval[0];
36
- return iteration < retryInterval.length
37
- ? retryInterval[iteration]
38
- : retryInterval[retryInterval.length - 1];
39
- }
40
- if (typeof retryInterval === 'function')
41
- return Math.max(1, retryInterval(iteration) ?? redis_consts_1.REDIS_DEFAULT_LOCK_ACQUIRE_RETRY_DELAY_MS);
42
- return redis_consts_1.REDIS_DEFAULT_LOCK_ACQUIRE_RETRY_DELAY_MS;
43
- };
44
- exports.getRetryInterval = getRetryInterval;
@@ -1,30 +0,0 @@
1
- "use strict";
2
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
- return c > 3 && r && Object.defineProperty(target, key, r), r;
7
- };
8
- var RedisModule_1;
9
- Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.RedisModule = void 0;
11
- const common_1 = require("@nestjs/common");
12
- const redis_core_module_1 = require("./redis-core.module");
13
- let RedisModule = RedisModule_1 = class RedisModule {
14
- /**
15
- * @param {RedisRegisterOptions} options
16
- * @return {DynamicModule}
17
- */
18
- static register(options) {
19
- return {
20
- module: RedisModule_1,
21
- imports: [
22
- redis_core_module_1.RedisCoreModule.register(options)
23
- ]
24
- };
25
- }
26
- };
27
- exports.RedisModule = RedisModule;
28
- exports.RedisModule = RedisModule = RedisModule_1 = __decorate([
29
- (0, common_1.Module)({})
30
- ], RedisModule);
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,4 +0,0 @@
1
- export { RedisModule } from './redis.module';
2
- export type { RedisRegisterOptions } from './redis.types';
3
- export { RedisLockFactory } from './redis-lock.factory';
4
- export { RedisLock, type RedisLockWaitAcquireParams } from './redis-lock';
@@ -1,20 +0,0 @@
1
- import { type DynamicModule } from '@nestjs/common';
2
- import type { RedisRegisterOptions } from './redis.types';
3
- export declare class RedisCoreModule {
4
- /**
5
- * @param {RedisRegisterOptions} options
6
- * @return {DynamicModule}
7
- */
8
- static register(options: RedisRegisterOptions): DynamicModule;
9
- /**
10
- * @param {RedisRegisterOptions} options
11
- * @return {ValueProvider}
12
- * @private
13
- */
14
- private static createOptionsProvider;
15
- /**
16
- * @return {FactoryProvider}
17
- * @private
18
- */
19
- private static createRedisProvider;
20
- }
@@ -1,39 +0,0 @@
1
- import Redis from 'ioredis';
2
- export type RedisLockWaitAcquireParams = {
3
- lockTTL: number;
4
- retryInterval?: number | number[] | ((iteration: number) => number);
5
- } & ({
6
- signal: AbortSignal;
7
- waitTimeout?: number;
8
- } | {
9
- signal?: AbortSignal;
10
- waitTimeout: number;
11
- });
12
- export declare class RedisLock {
13
- private readonly redis;
14
- private readonly locksHashKey;
15
- readonly name: string;
16
- private readonly value;
17
- private acquireLockPromise;
18
- /**
19
- * @param {Redis} redis
20
- * @param {string} name
21
- * @param {string} locksHashKey
22
- * @protected
23
- */
24
- constructor(redis: Redis, name: string, locksHashKey: string);
25
- /**
26
- * @param {RedisLockWaitAcquireParams} params
27
- * @return {Promise<boolean>}
28
- */
29
- waitAcquire(params: RedisLockWaitAcquireParams): Promise<boolean>;
30
- /**
31
- * @param {number} ttlMs
32
- * @return {Promise<boolean>}
33
- */
34
- acquire(ttlMs: number): Promise<boolean>;
35
- /**
36
- * @return {Promise<void>}
37
- */
38
- release(): Promise<void>;
39
- }
@@ -1,17 +0,0 @@
1
- import Redis from 'ioredis';
2
- import type { RedisRegisterOptions } from './redis.types';
3
- import { RedisLock } from './redis-lock';
4
- export declare class RedisLockFactory {
5
- private readonly options;
6
- private readonly redis;
7
- /**
8
- * @param {RedisRegisterOptions} options
9
- * @param {Redis} redis
10
- */
11
- constructor(options: RedisRegisterOptions, redis: Redis);
12
- /**
13
- * @param {string} name
14
- * @return {RedisLock}
15
- */
16
- create(name: string): RedisLock;
17
- }
@@ -1,3 +0,0 @@
1
- export declare const REDIS_OPTIONS_TOKEN: unique symbol;
2
- export declare const REDIS_DEFAULT_LOCKS_HASH_KEY = "__locks__";
3
- export declare const REDIS_DEFAULT_LOCK_ACQUIRE_RETRY_DELAY_MS = 500;
@@ -1,12 +0,0 @@
1
- import { type RedisLockWaitAcquireParams } from './redis-lock';
2
- /**
3
- * @param {string} prefix
4
- * @return {string}
5
- */
6
- export declare const resolveKeyPrefix: (prefix?: string) => string;
7
- /**
8
- * @param {number} iteration
9
- * @param {RedisLockWaitAcquireParams["retryInterval"]} [retryInterval]
10
- * @return {number}
11
- */
12
- export declare const getRetryInterval: (iteration: number, retryInterval?: RedisLockWaitAcquireParams["retryInterval"]) => number;
@@ -1,9 +0,0 @@
1
- import { type DynamicModule } from '@nestjs/common';
2
- import type { RedisRegisterOptions } from './redis.types';
3
- export declare class RedisModule {
4
- /**
5
- * @param {RedisRegisterOptions} options
6
- * @return {DynamicModule}
7
- */
8
- static register(options: RedisRegisterOptions): DynamicModule;
9
- }
@@ -1,5 +0,0 @@
1
- import { type RedisOptions } from 'ioredis';
2
- export type RedisRegisterOptions = RedisOptions & {
3
- keyPrefix?: string;
4
- locksHashKey?: string;
5
- };