@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 +263 -0
- package/dist/index.d.cts +75 -0
- package/package.json +15 -24
- package/dist/lib/index.js +0 -9
- package/dist/lib/redis-core.module.js +0 -70
- package/dist/lib/redis-lock.factory.js +0 -47
- package/dist/lib/redis-lock.js +0 -94
- package/dist/lib/redis.consts.js +0 -6
- package/dist/lib/redis.helpers.js +0 -44
- package/dist/lib/redis.module.js +0 -30
- package/dist/lib/redis.types.js +0 -2
- package/dist/types/index.d.ts +0 -4
- package/dist/types/redis-core.module.d.ts +0 -20
- package/dist/types/redis-lock.d.ts +0 -39
- package/dist/types/redis-lock.factory.d.ts +0 -17
- package/dist/types/redis.consts.d.ts +0 -3
- package/dist/types/redis.helpers.d.ts +0 -12
- package/dist/types/redis.module.d.ts +0 -9
- package/dist/types/redis.types.d.ts +0 -5
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
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -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.
|
|
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
|
-
"
|
|
10
|
-
"types": "./dist/
|
|
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.
|
|
45
|
-
"ioredis": "^5.
|
|
37
|
+
"@nestjs/common": "^11.1.27",
|
|
38
|
+
"ioredis": "^5.11.1"
|
|
46
39
|
},
|
|
47
40
|
"devDependencies": {
|
|
48
|
-
"@nestjs/common": "^11.1.
|
|
49
|
-
"ioredis": "^5.
|
|
50
|
-
"
|
|
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
|
-
"
|
|
56
|
-
"
|
|
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);
|
package/dist/lib/redis-lock.js
DELETED
|
@@ -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;
|
package/dist/lib/redis.consts.js
DELETED
|
@@ -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;
|
package/dist/lib/redis.module.js
DELETED
|
@@ -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);
|
package/dist/lib/redis.types.js
DELETED
package/dist/types/index.d.ts
DELETED
|
@@ -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,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
|
-
}
|