@dofe/infra-redis 0.1.1
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/cache.service.d.ts +16 -0
- package/dist/cache.service.d.ts.map +1 -0
- package/dist/cache.service.js +69 -0
- package/dist/cache.service.js.map +1 -0
- package/dist/dto/redis.dto.d.ts +11 -0
- package/dist/dto/redis.dto.d.ts.map +1 -0
- package/dist/dto/redis.dto.js +5 -0
- package/dist/dto/redis.dto.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/redis-lock.module.d.ts +3 -0
- package/dist/redis-lock.module.d.ts.map +1 -0
- package/dist/redis-lock.module.js +25 -0
- package/dist/redis-lock.module.js.map +1 -0
- package/dist/redis-lock.service.d.ts +33 -0
- package/dist/redis-lock.service.d.ts.map +1 -0
- package/dist/redis-lock.service.js +159 -0
- package/dist/redis-lock.service.js.map +1 -0
- package/dist/redis-version-check.d.ts +6 -0
- package/dist/redis-version-check.d.ts.map +1 -0
- package/dist/redis-version-check.js +43 -0
- package/dist/redis-version-check.js.map +1 -0
- package/dist/redis.module.d.ts +3 -0
- package/dist/redis.module.d.ts.map +1 -0
- package/dist/redis.module.js +77 -0
- package/dist/redis.module.js.map +1 -0
- package/dist/redis.service.d.ts +70 -0
- package/dist/redis.service.d.ts.map +1 -0
- package/dist/redis.service.js +800 -0
- package/dist/redis.service.js.map +1 -0
- package/dist/redis.service.spec.d.ts +2 -0
- package/dist/redis.service.spec.d.ts.map +1 -0
- package/dist/redis.service.spec.js +17 -0
- package/dist/redis.service.spec.js.map +1 -0
- package/dist/tenant-redis.module.d.ts +3 -0
- package/dist/tenant-redis.module.d.ts.map +1 -0
- package/dist/tenant-redis.module.js +25 -0
- package/dist/tenant-redis.module.js.map +1 -0
- package/dist/tenant-redis.service.d.ts +16 -0
- package/dist/tenant-redis.service.d.ts.map +1 -0
- package/dist/tenant-redis.service.js +62 -0
- package/dist/tenant-redis.service.js.map +1 -0
- package/package.json +37 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { OnModuleDestroy } from '@nestjs/common';
|
|
2
|
+
import { ConfigService } from '@nestjs/config';
|
|
3
|
+
import Redis from 'ioredis';
|
|
4
|
+
export declare class CacheService implements OnModuleDestroy {
|
|
5
|
+
private readonly configService;
|
|
6
|
+
private readonly redis;
|
|
7
|
+
constructor(configService: ConfigService);
|
|
8
|
+
get<T>(key: string): Promise<T | null>;
|
|
9
|
+
set(key: string, value: any, ttl?: number): Promise<void>;
|
|
10
|
+
delete(key: string): Promise<void>;
|
|
11
|
+
exists(key: string): Promise<boolean>;
|
|
12
|
+
getByPattern(pattern: string): Promise<string[]>;
|
|
13
|
+
getClient(): Redis;
|
|
14
|
+
onModuleDestroy(): void;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=cache.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.service.d.ts","sourceRoot":"","sources":["../src/cache.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,MAAM,SAAS,CAAC;AAE5B,qBACa,YAAa,YAAW,eAAe;IAIhD,OAAO,CAAC,QAAQ,CAAC,aAAa;IAHhC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;gBAGX,aAAa,EAAE,aAAa;IAMzC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAUtC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASzD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKrC,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAItD,SAAS,IAAI,KAAK;IAIlB,eAAe;CAGhB"}
|
|
@@ -0,0 +1,69 @@
|
|
|
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 __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.CacheService = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const config_1 = require("@nestjs/config");
|
|
18
|
+
const ioredis_1 = __importDefault(require("ioredis"));
|
|
19
|
+
let CacheService = class CacheService {
|
|
20
|
+
configService;
|
|
21
|
+
redis;
|
|
22
|
+
constructor(configService) {
|
|
23
|
+
this.configService = configService;
|
|
24
|
+
const redisUrl = this.configService.get('REDIS_URL', 'redis://localhost:6379');
|
|
25
|
+
this.redis = new ioredis_1.default(redisUrl);
|
|
26
|
+
}
|
|
27
|
+
async get(key) {
|
|
28
|
+
const value = await this.redis.get(key);
|
|
29
|
+
if (!value)
|
|
30
|
+
return null;
|
|
31
|
+
try {
|
|
32
|
+
return JSON.parse(value);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
async set(key, value, ttl) {
|
|
39
|
+
const serialized = typeof value === 'string' ? value : JSON.stringify(value);
|
|
40
|
+
if (ttl) {
|
|
41
|
+
await this.redis.setex(key, ttl, serialized);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
await this.redis.set(key, serialized);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async delete(key) {
|
|
48
|
+
await this.redis.del(key);
|
|
49
|
+
}
|
|
50
|
+
async exists(key) {
|
|
51
|
+
const result = await this.redis.exists(key);
|
|
52
|
+
return result === 1;
|
|
53
|
+
}
|
|
54
|
+
async getByPattern(pattern) {
|
|
55
|
+
return this.redis.keys(pattern);
|
|
56
|
+
}
|
|
57
|
+
getClient() {
|
|
58
|
+
return this.redis;
|
|
59
|
+
}
|
|
60
|
+
onModuleDestroy() {
|
|
61
|
+
this.redis.disconnect();
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
exports.CacheService = CacheService;
|
|
65
|
+
exports.CacheService = CacheService = __decorate([
|
|
66
|
+
(0, common_1.Injectable)(),
|
|
67
|
+
__metadata("design:paramtypes", [config_1.ConfigService])
|
|
68
|
+
], CacheService);
|
|
69
|
+
//# sourceMappingURL=cache.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.service.js","sourceRoot":"","sources":["../src/cache.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAA6D;AAC7D,2CAA+C;AAC/C,sDAA4B;AAGrB,IAAM,YAAY,GAAlB,MAAM,YAAY;IAIJ;IAHF,KAAK,CAAQ;IAE9B,YACmB,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;QAE7C,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,WAAW,EAAE,wBAAwB,CAAC,CAAC;QACvF,IAAI,CAAC,KAAK,GAAG,IAAI,iBAAK,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,GAAG,CAAI,GAAW;QACtB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAM,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAU,CAAC;QACpB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAU,EAAE,GAAY;QAC7C,MAAM,UAAU,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC7E,IAAI,GAAG,EAAE,CAAC;YACR,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC5C,OAAO,MAAM,KAAK,CAAC,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,OAAe;QAChC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,eAAe;QACb,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;IAC1B,CAAC;CACF,CAAA;AAjDY,oCAAY;uBAAZ,YAAY;IADxB,IAAA,mBAAU,GAAE;qCAKuB,sBAAa;GAJpC,YAAY,CAiDxB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redis cache key configuration interface
|
|
3
|
+
* Used for configuring named cache keys with expiration
|
|
4
|
+
*/
|
|
5
|
+
export interface RedisCacheKeyConfig {
|
|
6
|
+
name: string;
|
|
7
|
+
key: string;
|
|
8
|
+
expireIn?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare const REDIS_AUTH: unique symbol;
|
|
11
|
+
//# sourceMappingURL=redis.dto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.dto.d.ts","sourceRoot":"","sources":["../../src/dto/redis.dto.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,UAAU,eAAuB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.dto.js","sourceRoot":"","sources":["../../src/dto/redis.dto.ts"],"names":[],"mappings":";;;AAUa,QAAA,UAAU,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './redis.module';
|
|
2
|
+
export * from './redis.service';
|
|
3
|
+
export * from './cache.service';
|
|
4
|
+
export * from './dto/redis.dto';
|
|
5
|
+
export * from './redis-lock.module';
|
|
6
|
+
export * from './redis-lock.service';
|
|
7
|
+
export * from './tenant-redis.module';
|
|
8
|
+
export * from './tenant-redis.service';
|
|
9
|
+
export * from './redis-version-check';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./redis.module"), exports);
|
|
18
|
+
__exportStar(require("./redis.service"), exports);
|
|
19
|
+
__exportStar(require("./cache.service"), exports);
|
|
20
|
+
__exportStar(require("./dto/redis.dto"), exports);
|
|
21
|
+
__exportStar(require("./redis-lock.module"), exports);
|
|
22
|
+
__exportStar(require("./redis-lock.service"), exports);
|
|
23
|
+
__exportStar(require("./tenant-redis.module"), exports);
|
|
24
|
+
__exportStar(require("./tenant-redis.service"), exports);
|
|
25
|
+
__exportStar(require("./redis-version-check"), exports);
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iDAA+B;AAC/B,kDAAgC;AAChC,kDAAgC;AAChC,kDAAgC;AAChC,sDAAoC;AACpC,uDAAqC;AACrC,wDAAsC;AACtC,yDAAuC;AACvC,wDAAsC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-lock.module.d.ts","sourceRoot":"","sources":["../src/redis-lock.module.ts"],"names":[],"mappings":"AAKA,qBAMa,eAAe;CAAG"}
|
|
@@ -0,0 +1,25 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.RedisLockModule = void 0;
|
|
10
|
+
const common_1 = require("@nestjs/common");
|
|
11
|
+
const redis_module_1 = require("./redis.module");
|
|
12
|
+
const redis_lock_service_1 = require("./redis-lock.service");
|
|
13
|
+
const config_1 = require("@nestjs/config");
|
|
14
|
+
let RedisLockModule = class RedisLockModule {
|
|
15
|
+
};
|
|
16
|
+
exports.RedisLockModule = RedisLockModule;
|
|
17
|
+
exports.RedisLockModule = RedisLockModule = __decorate([
|
|
18
|
+
(0, common_1.Global)(),
|
|
19
|
+
(0, common_1.Module)({
|
|
20
|
+
imports: [config_1.ConfigModule, redis_module_1.RedisModule],
|
|
21
|
+
providers: [redis_lock_service_1.RedisLockService],
|
|
22
|
+
exports: [redis_lock_service_1.RedisLockService],
|
|
23
|
+
})
|
|
24
|
+
], RedisLockModule);
|
|
25
|
+
//# sourceMappingURL=redis-lock.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-lock.module.js","sourceRoot":"","sources":["../src/redis-lock.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAgD;AAChD,iDAA6C;AAC7C,6DAAwD;AACxD,2CAA8C;AAQvC,IAAM,eAAe,GAArB,MAAM,eAAe;CAAG,CAAA;AAAlB,0CAAe;0BAAf,eAAe;IAN3B,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,qBAAY,EAAE,0BAAW,CAAC;QACpC,SAAS,EAAE,CAAC,qCAAgB,CAAC;QAC7B,OAAO,EAAE,CAAC,qCAAgB,CAAC;KAC5B,CAAC;GACW,eAAe,CAAG"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import Redis from 'ioredis';
|
|
2
|
+
/**
|
|
3
|
+
* Simple console logger fallback when Winston is not available
|
|
4
|
+
*/
|
|
5
|
+
declare const consoleLogger: {
|
|
6
|
+
error: (message: string, meta?: any) => void;
|
|
7
|
+
warn: (message: string, meta?: any) => void;
|
|
8
|
+
info: (message: string, meta?: any) => void;
|
|
9
|
+
debug: (message: string, meta?: any) => void;
|
|
10
|
+
};
|
|
11
|
+
type LoggerLike = typeof consoleLogger;
|
|
12
|
+
export declare class RedisLockService {
|
|
13
|
+
private readonly redis;
|
|
14
|
+
private readonly logger;
|
|
15
|
+
constructor(redis: Redis, winstonLogger?: LoggerLike);
|
|
16
|
+
acquireLock(key: string, options?: {
|
|
17
|
+
ttl?: number;
|
|
18
|
+
retries?: number;
|
|
19
|
+
retryDelay?: number;
|
|
20
|
+
}): Promise<{
|
|
21
|
+
release: () => Promise<void>;
|
|
22
|
+
}>;
|
|
23
|
+
private releaseLock;
|
|
24
|
+
private generateLockValue;
|
|
25
|
+
private sleep;
|
|
26
|
+
tryLock(key: string, ttl?: number): Promise<{
|
|
27
|
+
release: () => Promise<void>;
|
|
28
|
+
} | null>;
|
|
29
|
+
isLocked(key: string): Promise<boolean>;
|
|
30
|
+
forceRelease(key: string): Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=redis-lock.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-lock.service.d.ts","sourceRoot":"","sources":["../src/redis-lock.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,SAAS,CAAC;AAU5B;;GAEG;AACH,QAAA,MAAM,aAAa;qBACA,MAAM,SAAS,GAAG;oBACnB,MAAM,SAAS,GAAG;oBAClB,MAAM,SAAS,GAAG;qBACjB,MAAM,SAAS,GAAG;CAGpC,CAAC;AAEF,KAAK,UAAU,GAAG,OAAO,aAAa,CAAC;AAEvC,qBACa,gBAAgB;IAIL,OAAO,CAAC,QAAQ,CAAC,KAAK;IAH5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;gBAGG,KAAK,EAAE,KAAK,EACX,aAAa,CAAC,EAAE,UAAU;IAK5D,WAAW,CACf,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;QACP,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;KAChB,GACL,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC;YAmD9B,WAAW;IA6BzB,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,KAAK;IAIP,OAAO,CACX,GAAG,EAAE,MAAM,EACX,GAAG,GAAE,MAAc,GAClB,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,GAAG,IAAI,CAAC;IAQ7C,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKvC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAW/C"}
|
|
@@ -0,0 +1,159 @@
|
|
|
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.RedisLockService = void 0;
|
|
19
|
+
const common_1 = require("@nestjs/common");
|
|
20
|
+
const ioredis_1 = __importDefault(require("ioredis"));
|
|
21
|
+
const redis_dto_1 = require("./dto/redis.dto");
|
|
22
|
+
/**
|
|
23
|
+
* Check if running in production environment
|
|
24
|
+
*/
|
|
25
|
+
function isProduction() {
|
|
26
|
+
return process.env.NODE_ENV === 'production';
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Simple console logger fallback when Winston is not available
|
|
30
|
+
*/
|
|
31
|
+
const consoleLogger = {
|
|
32
|
+
error: (message, meta) => console.error(message, meta),
|
|
33
|
+
warn: (message, meta) => console.warn(message, meta),
|
|
34
|
+
info: (message, meta) => console.info(message, meta),
|
|
35
|
+
debug: (message, meta) => {
|
|
36
|
+
if (!isProduction())
|
|
37
|
+
console.debug(message, meta);
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
let RedisLockService = class RedisLockService {
|
|
41
|
+
redis;
|
|
42
|
+
logger;
|
|
43
|
+
constructor(redis, winstonLogger) {
|
|
44
|
+
this.redis = redis;
|
|
45
|
+
this.logger = winstonLogger ?? consoleLogger;
|
|
46
|
+
}
|
|
47
|
+
async acquireLock(key, options = {}) {
|
|
48
|
+
const { ttl = 30000, retries = 3, retryDelay = 1000 } = options;
|
|
49
|
+
const lockValue = this.generateLockValue();
|
|
50
|
+
const ttlSeconds = Math.ceil(ttl / 1000);
|
|
51
|
+
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
52
|
+
try {
|
|
53
|
+
const result = await this.redis.set(key, lockValue, 'EX', ttlSeconds, 'NX');
|
|
54
|
+
if (result === 'OK') {
|
|
55
|
+
this.logger.debug('[RedisLock] Lock acquired', {
|
|
56
|
+
key,
|
|
57
|
+
lockValue,
|
|
58
|
+
ttl,
|
|
59
|
+
attempt,
|
|
60
|
+
});
|
|
61
|
+
return {
|
|
62
|
+
release: async () => {
|
|
63
|
+
await this.releaseLock(key, lockValue);
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
if (attempt < retries) {
|
|
68
|
+
this.logger.debug('[RedisLock] Lock acquisition failed, retrying', {
|
|
69
|
+
key,
|
|
70
|
+
attempt,
|
|
71
|
+
nextRetryIn: retryDelay,
|
|
72
|
+
});
|
|
73
|
+
await this.sleep(retryDelay);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
this.logger.error('[RedisLock] Error acquiring lock', {
|
|
78
|
+
key,
|
|
79
|
+
attempt,
|
|
80
|
+
error: error instanceof Error ? error.message : String(error),
|
|
81
|
+
});
|
|
82
|
+
if (attempt === retries) {
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
await this.sleep(retryDelay);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
throw new Error(`Failed to acquire lock after ${retries} attempts: ${key}`);
|
|
89
|
+
}
|
|
90
|
+
async releaseLock(key, lockValue) {
|
|
91
|
+
try {
|
|
92
|
+
const script = `
|
|
93
|
+
if redis.call("get", KEYS[1]) == ARGV[1] then
|
|
94
|
+
return redis.call("del", KEYS[1])
|
|
95
|
+
else
|
|
96
|
+
return 0
|
|
97
|
+
end
|
|
98
|
+
`;
|
|
99
|
+
const result = await this.redis.eval(script, 1, key, lockValue);
|
|
100
|
+
if (result === 1) {
|
|
101
|
+
this.logger.debug('[RedisLock] Lock released', { key, lockValue });
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
this.logger.warn('[RedisLock] Lock not released (already expired or not owned)', {
|
|
105
|
+
key,
|
|
106
|
+
lockValue,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
this.logger.error('[RedisLock] Error releasing lock', {
|
|
112
|
+
key,
|
|
113
|
+
lockValue,
|
|
114
|
+
error: error instanceof Error ? error.message : String(error),
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
generateLockValue() {
|
|
119
|
+
const timestamp = Date.now();
|
|
120
|
+
const random = Math.random().toString(36).substring(2, 15);
|
|
121
|
+
return `${timestamp}-${random}`;
|
|
122
|
+
}
|
|
123
|
+
sleep(ms) {
|
|
124
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
125
|
+
}
|
|
126
|
+
async tryLock(key, ttl = 30000) {
|
|
127
|
+
try {
|
|
128
|
+
return await this.acquireLock(key, { ttl, retries: 1, retryDelay: 0 });
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async isLocked(key) {
|
|
135
|
+
const exists = await this.redis.exists(key);
|
|
136
|
+
return exists === 1;
|
|
137
|
+
}
|
|
138
|
+
async forceRelease(key) {
|
|
139
|
+
try {
|
|
140
|
+
await this.redis.del(key);
|
|
141
|
+
this.logger.warn('[RedisLock] Lock force released', { key });
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
this.logger.error('[RedisLock] Error force releasing lock', {
|
|
145
|
+
key,
|
|
146
|
+
error: error instanceof Error ? error.message : String(error),
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
exports.RedisLockService = RedisLockService;
|
|
152
|
+
exports.RedisLockService = RedisLockService = __decorate([
|
|
153
|
+
(0, common_1.Injectable)(),
|
|
154
|
+
__param(0, (0, common_1.Inject)(redis_dto_1.REDIS_AUTH)),
|
|
155
|
+
__param(1, (0, common_1.Optional)()),
|
|
156
|
+
__param(1, (0, common_1.Inject)('WINSTON_LOGGER')),
|
|
157
|
+
__metadata("design:paramtypes", [ioredis_1.default, Object])
|
|
158
|
+
], RedisLockService);
|
|
159
|
+
//# sourceMappingURL=redis-lock.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-lock.service.js","sourceRoot":"","sources":["../src/redis-lock.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate Redis version meets BullMQ minimum requirement (>= 5.0.0).
|
|
3
|
+
* Called during bootstrap before NestJS DI is available, so uses console for logging.
|
|
4
|
+
*/
|
|
5
|
+
export declare function validateRedisVersion(redisUrl: string): Promise<void>;
|
|
6
|
+
//# sourceMappingURL=redis-version-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-version-check.d.ts","sourceRoot":"","sources":["../src/redis-version-check.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiC1E"}
|
|
@@ -0,0 +1,43 @@
|
|
|
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.validateRedisVersion = validateRedisVersion;
|
|
7
|
+
const ioredis_1 = __importDefault(require("ioredis"));
|
|
8
|
+
const MIN_REDIS_VERSION = 5;
|
|
9
|
+
/**
|
|
10
|
+
* Validate Redis version meets BullMQ minimum requirement (>= 5.0.0).
|
|
11
|
+
* Called during bootstrap before NestJS DI is available, so uses console for logging.
|
|
12
|
+
*/
|
|
13
|
+
async function validateRedisVersion(redisUrl) {
|
|
14
|
+
const checkClient = new ioredis_1.default(redisUrl, {
|
|
15
|
+
maxRetriesPerRequest: 1,
|
|
16
|
+
connectTimeout: 5000,
|
|
17
|
+
lazyConnect: true,
|
|
18
|
+
});
|
|
19
|
+
try {
|
|
20
|
+
await checkClient.connect();
|
|
21
|
+
const info = await checkClient.info('server');
|
|
22
|
+
const versionMatch = info.match(/redis_version:([\d.]+)/);
|
|
23
|
+
if (versionMatch) {
|
|
24
|
+
const version = versionMatch[1];
|
|
25
|
+
const [major] = version.split('.').map(Number);
|
|
26
|
+
if (major < MIN_REDIS_VERSION) {
|
|
27
|
+
const errorMsg = `❌ Redis 版本错误: 当前版本 ${version},BullMQ 需要 >= ${MIN_REDIS_VERSION}.0.0\n` +
|
|
28
|
+
`请升级 Redis 服务器。参考文档: docs/redis-version-error.md\n` +
|
|
29
|
+
`升级命令 (macOS): brew upgrade redis\n` +
|
|
30
|
+
`升级命令 (Linux): sudo apt update && sudo apt install redis-server`;
|
|
31
|
+
console.error(errorMsg);
|
|
32
|
+
throw new Error(`Redis version ${version} is too old. BullMQ requires Redis >= ${MIN_REDIS_VERSION}.0.0. Please upgrade Redis server.`);
|
|
33
|
+
}
|
|
34
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
35
|
+
console.log(`✓ Redis 版本检查通过: ${version}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
await checkClient.quit();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=redis-version-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-version-check.js","sourceRoot":"","sources":["../src/redis-version-check.ts"],"names":[],"mappings":";;;;;AAQA,oDAiCC;AAzCD,sDAA4B;AAE5B,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAE5B;;;GAGG;AACI,KAAK,UAAU,oBAAoB,CAAC,QAAgB;IACzD,MAAM,WAAW,GAAG,IAAI,iBAAK,CAAC,QAAQ,EAAE;QACtC,oBAAoB,EAAE,CAAC;QACvB,cAAc,EAAE,IAAI;QACpB,WAAW,EAAE,IAAI;KAClB,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,WAAW,CAAC,OAAO,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAE9C,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC1D,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YAChC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC/C,IAAI,KAAK,GAAG,iBAAiB,EAAE,CAAC;gBAC9B,MAAM,QAAQ,GACZ,sBAAsB,OAAO,iBAAiB,iBAAiB,QAAQ;oBACvE,mDAAmD;oBACnD,oCAAoC;oBACpC,gEAAgE,CAAC;gBACnE,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBACxB,MAAM,IAAI,KAAK,CACb,iBAAiB,OAAO,yCAAyC,iBAAiB,oCAAoC,CACvH,CAAC;YACJ,CAAC;YACD,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;gBAC1C,OAAO,CAAC,GAAG,CAAC,mBAAmB,OAAO,EAAE,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,WAAW,CAAC,IAAI,EAAE,CAAC;IAC3B,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.module.d.ts","sourceRoot":"","sources":["../src/redis.module.ts"],"names":[],"mappings":"AAcA,qBAmDa,WAAW;CAAG"}
|
|
@@ -0,0 +1,77 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.RedisModule = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const ioredis_1 = __importDefault(require("ioredis"));
|
|
15
|
+
const redis_dto_1 = require("./dto/redis.dto");
|
|
16
|
+
const redis_service_1 = require("./redis.service");
|
|
17
|
+
const cache_service_1 = require("./cache.service");
|
|
18
|
+
const config_1 = require("@nestjs/config");
|
|
19
|
+
/**
|
|
20
|
+
* Check if running in production environment
|
|
21
|
+
*/
|
|
22
|
+
function isProduction() {
|
|
23
|
+
return process.env.NODE_ENV === 'production';
|
|
24
|
+
}
|
|
25
|
+
let RedisModule = class RedisModule {
|
|
26
|
+
};
|
|
27
|
+
exports.RedisModule = RedisModule;
|
|
28
|
+
exports.RedisModule = RedisModule = __decorate([
|
|
29
|
+
(0, common_1.Module)({
|
|
30
|
+
imports: [config_1.ConfigModule],
|
|
31
|
+
providers: [
|
|
32
|
+
{
|
|
33
|
+
provide: redis_dto_1.REDIS_AUTH,
|
|
34
|
+
useFactory: async () => {
|
|
35
|
+
const redisUrl = process.env.REDIS_URL;
|
|
36
|
+
if (!redisUrl) {
|
|
37
|
+
console.error('Redis URL not configured');
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const client = new ioredis_1.default(redisUrl, {
|
|
42
|
+
retryStrategy(times) {
|
|
43
|
+
if (times > 10) {
|
|
44
|
+
console.error('Redis连接失败', 'Redis reconnect exhausted after 10 retries.');
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return Math.min(times * 150, 3000);
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
client.on('connect', () => {
|
|
51
|
+
if (isProduction()) {
|
|
52
|
+
console.log('Redis client connected');
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
client.on('error', (error) => {
|
|
56
|
+
if (isProduction()) {
|
|
57
|
+
console.error('Error connecting to Redis', error);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
console.debug('Error connecting to Redis', error);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
return client;
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
console.error('Redis error', e);
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
redis_service_1.RedisService,
|
|
72
|
+
cache_service_1.CacheService,
|
|
73
|
+
],
|
|
74
|
+
exports: [redis_dto_1.REDIS_AUTH, redis_service_1.RedisService, cache_service_1.CacheService],
|
|
75
|
+
})
|
|
76
|
+
], RedisModule);
|
|
77
|
+
//# sourceMappingURL=redis.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.module.js","sourceRoot":"","sources":["../src/redis.module.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAwC;AACxC,sDAA4B;AAC5B,+CAA6C;AAC7C,mDAA+C;AAC/C,mDAA+C;AAC/C,2CAA8C;AAE9C;;GAEG;AACH,SAAS,YAAY;IACnB,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;AAC/C,CAAC;AAqDM,IAAM,WAAW,GAAjB,MAAM,WAAW;CAAG,CAAA;AAAd,kCAAW;sBAAX,WAAW;IAnDvB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,qBAAY,CAAC;QACvB,SAAS,EAAE;YACT;gBACE,OAAO,EAAE,sBAAU;gBACnB,UAAU,EAAE,KAAK,IAAI,EAAE;oBACrB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;oBACvC,IAAI,CAAC,QAAQ,EAAE,CAAC;wBACd,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;wBAC1C,OAAO,IAAI,CAAC;oBACd,CAAC;oBACD,IAAI,CAAC;wBACH,MAAM,MAAM,GAAG,IAAI,iBAAK,CAAC,QAAQ,EAAE;4BACjC,aAAa,CAAC,KAAK;gCACjB,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;oCACf,OAAO,CAAC,KAAK,CACX,WAAW,EACX,6CAA6C,CAC9C,CAAC;oCACF,OAAO,IAAI,CAAC;gCACd,CAAC;gCACD,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,GAAG,EAAE,IAAI,CAAC,CAAC;4BACrC,CAAC;yBACF,CAAC,CAAC;wBAEH,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;4BACxB,IAAI,YAAY,EAAE,EAAE,CAAC;gCACnB,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;4BACxC,CAAC;wBACH,CAAC,CAAC,CAAC;wBAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;4BAC3B,IAAI,YAAY,EAAE,EAAE,CAAC;gCACnB,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;4BACpD,CAAC;iCAAM,CAAC;gCACN,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;4BACpD,CAAC;wBACH,CAAC,CAAC,CAAC;wBAEH,OAAO,MAAM,CAAC;oBAChB,CAAC;oBAAC,OAAO,CAAC,EAAE,CAAC;wBACX,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;wBAChC,OAAO,IAAI,CAAC;oBACd,CAAC;gBACH,CAAC;aACF;YACD,4BAAY;YACZ,4BAAY;SACb;QACD,OAAO,EAAE,CAAC,sBAAU,EAAE,4BAAY,EAAE,4BAAY,CAAC;KAClD,CAAC;GACW,WAAW,CAAG"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { OnModuleDestroy } from '@nestjs/common';
|
|
2
|
+
import { Redis } from 'ioredis';
|
|
3
|
+
import { ConfigService } from '@nestjs/config';
|
|
4
|
+
import type { Logger } from 'winston';
|
|
5
|
+
export declare class RedisService implements OnModuleDestroy {
|
|
6
|
+
private readonly configService;
|
|
7
|
+
private readonly redisClient;
|
|
8
|
+
private redisConfigs;
|
|
9
|
+
private lastClosedLogTime;
|
|
10
|
+
private readonly CLOSED_LOG_THROTTLE_MS;
|
|
11
|
+
private readonly logger;
|
|
12
|
+
constructor(configService: ConfigService, redisClient: Redis, winstonLogger?: Logger);
|
|
13
|
+
private isConnectionAvailable;
|
|
14
|
+
private shouldLogClosedError;
|
|
15
|
+
onModuleDestroy(): Promise<void>;
|
|
16
|
+
get redis(): Redis;
|
|
17
|
+
getExpireIn(name: string): number;
|
|
18
|
+
getRedisKey(name: string, key: string): string;
|
|
19
|
+
saveDataToList(name: string, key: string, value: any): Promise<void>;
|
|
20
|
+
getListData(name: string, key: string): Promise<any[]>;
|
|
21
|
+
pushDataToList(name: string, key: string, value: any, expireIn?: number): Promise<void>;
|
|
22
|
+
pushDatasToList(name: string, key: string, values: any[], expireIn?: number): Promise<void>;
|
|
23
|
+
saveData(name: string, key: string, value: any, expireIn?: number): Promise<"OK">;
|
|
24
|
+
getData(name: string, key: string): Promise<any>;
|
|
25
|
+
deleteData(name: string, key: string): Promise<number>;
|
|
26
|
+
incrData(name: string, key: string): Promise<number>;
|
|
27
|
+
decrData(name: string, key: string): Promise<number>;
|
|
28
|
+
incrbyData(name: string, key: string, increment: number): Promise<number>;
|
|
29
|
+
decrbyData(name: string, key: string, decrement: number): Promise<number>;
|
|
30
|
+
saveKeyFirstFileId(key: string, fileId: string): Promise<any>;
|
|
31
|
+
getKeyFirstFileId(key: string): Promise<any>;
|
|
32
|
+
saveQiniuUploadAuthKey(key: string): Promise<string>;
|
|
33
|
+
checkQiniuUploadAuthKey(key: string, authToken: string): Promise<boolean>;
|
|
34
|
+
setShortCode(key: string, value: any): Promise<"OK">;
|
|
35
|
+
getShortCode(key: string): Promise<any>;
|
|
36
|
+
saveProviderOauthNonce(name: string, state: string, nonce: any, expiresIn: number): Promise<void>;
|
|
37
|
+
getProviderOauthNonce(name: string, state: string): Promise<any>;
|
|
38
|
+
deleteProviderOauthNonce(name: string, state: string): Promise<void>;
|
|
39
|
+
saveProviderState(provider: string, state: string, expiresIn: number): Promise<void>;
|
|
40
|
+
getProviderState(provider: string, state: string): Promise<any>;
|
|
41
|
+
deleteProviderState(provider: string): Promise<void>;
|
|
42
|
+
set(key: string, value: any, options?: {
|
|
43
|
+
EX: number;
|
|
44
|
+
}): Promise<"OK">;
|
|
45
|
+
setNX(key: string, value: any, options: {
|
|
46
|
+
EX: number;
|
|
47
|
+
}): Promise<string | null>;
|
|
48
|
+
get(key: string): Promise<any>;
|
|
49
|
+
del(key: string): Promise<number>;
|
|
50
|
+
incr(key: string): Promise<number>;
|
|
51
|
+
incrby(key: string, increment: number): Promise<number>;
|
|
52
|
+
decr(key: string): Promise<number>;
|
|
53
|
+
decrby(key: string, decrement: number): Promise<number>;
|
|
54
|
+
expire(key: string, seconds: number): Promise<number>;
|
|
55
|
+
ttl(key: string): Promise<number>;
|
|
56
|
+
exists(key: string): Promise<number>;
|
|
57
|
+
deleteByPattern(pattern: string): Promise<number>;
|
|
58
|
+
pipeline(commands: (pipeline: ReturnType<typeof this.redisClient.pipeline>) => void[]): Promise<unknown[]>;
|
|
59
|
+
pipelineSave(items: Array<{
|
|
60
|
+
name: string;
|
|
61
|
+
key: string;
|
|
62
|
+
value: unknown;
|
|
63
|
+
expireIn?: number;
|
|
64
|
+
}>): Promise<void>;
|
|
65
|
+
pipelineGet(items: Array<{
|
|
66
|
+
name: string;
|
|
67
|
+
key: string;
|
|
68
|
+
}>): Promise<Map<string, unknown>>;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=redis.service.d.ts.map
|