@nest-omni/core 3.1.1-10 → 3.1.1-11

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.
@@ -35,5 +35,16 @@ declare module 'typeorm' {
35
35
  leftJoin<AliasEntity extends AbstractEntity, A extends string>(this: SelectQueryBuilder<Entity>, property: `${A}.${Exclude<KeyOfType<AliasEntity, AbstractEntity>, symbol>}`, alias: string, condition?: string, parameters?: ObjectLiteral): this;
36
36
  innerJoinAndSelect<AliasEntity extends AbstractEntity, A extends string>(this: SelectQueryBuilder<Entity>, property: `${A}.${Exclude<KeyOfType<AliasEntity, AbstractEntity>, symbol>}`, alias: string, condition?: string, parameters?: ObjectLiteral): this;
37
37
  innerJoin<AliasEntity extends AbstractEntity, A extends string>(this: SelectQueryBuilder<Entity>, property: `${A}.${Exclude<KeyOfType<AliasEntity, AbstractEntity>, symbol>}`, alias: string, condition?: string, parameters?: ObjectLiteral): this;
38
+ iterate(this: SelectQueryBuilder<Entity>, options?: {
39
+ batchSize?: number;
40
+ }): AsyncIterableIterator<Entity[]>;
41
+ eachBatch(this: SelectQueryBuilder<Entity>, callback: (item: Entity) => Promise<void> | void, options?: {
42
+ batchSize?: number;
43
+ mode?: 'single';
44
+ }): Promise<void>;
45
+ eachBatch(this: SelectQueryBuilder<Entity>, callback: (items: Entity[]) => Promise<void> | void, options?: {
46
+ batchSize?: number;
47
+ mode?: 'batch';
48
+ }): Promise<void>;
38
49
  }
39
50
  }
@@ -8,6 +8,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
+ var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
12
+ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
13
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
14
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
15
+ return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
16
+ function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
17
+ function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
18
+ function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
19
+ function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
20
+ function fulfill(value) { resume("next", value); }
21
+ function reject(value) { resume("throw", value); }
22
+ function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
23
+ };
11
24
  Object.defineProperty(exports, "__esModule", { value: true });
12
25
  require("source-map-support/register");
13
26
  const lodash_1 = require("lodash");
@@ -75,3 +88,47 @@ typeorm_1.SelectQueryBuilder.prototype.withTenant = function (tenantId, tenantFi
75
88
  }
76
89
  return this;
77
90
  };
91
+ typeorm_1.SelectQueryBuilder.prototype.iterate = function (options) {
92
+ return __asyncGenerator(this, arguments, function* () {
93
+ const batchSize = (options === null || options === void 0 ? void 0 : options.batchSize) || 100;
94
+ let offset = 0;
95
+ let hasMore = true;
96
+ while (hasMore) {
97
+ const batch = yield __await(this.clone().skip(offset).take(batchSize).getMany());
98
+ if (batch.length > 0) {
99
+ yield yield __await(batch);
100
+ offset += batchSize;
101
+ hasMore = batch.length === batchSize;
102
+ }
103
+ else {
104
+ hasMore = false;
105
+ }
106
+ }
107
+ });
108
+ };
109
+ typeorm_1.SelectQueryBuilder.prototype.eachBatch = function (callback, options) {
110
+ return __awaiter(this, void 0, void 0, function* () {
111
+ const batchSize = (options === null || options === void 0 ? void 0 : options.batchSize) || 100;
112
+ const mode = (options === null || options === void 0 ? void 0 : options.mode) || 'batch';
113
+ let offset = 0;
114
+ let hasMore = true;
115
+ while (hasMore) {
116
+ const batch = yield this.clone().skip(offset).take(batchSize).getMany();
117
+ if (batch.length > 0) {
118
+ if (mode === 'single') {
119
+ for (const item of batch) {
120
+ yield callback(item);
121
+ }
122
+ }
123
+ else {
124
+ yield callback(batch);
125
+ }
126
+ offset += batchSize;
127
+ hasMore = batch.length === batchSize;
128
+ }
129
+ else {
130
+ hasMore = false;
131
+ }
132
+ }
133
+ });
134
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nest-omni/core",
3
- "version": "3.1.1-10",
3
+ "version": "3.1.1-11",
4
4
  "description": "A comprehensive NestJS framework for building enterprise-grade applications with best practices",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -69,8 +69,6 @@
69
69
  "@dataui/crud": "^5.3.0",
70
70
  "@dataui/crud-typeorm": "^5.3.0",
71
71
  "@keyv/redis": "^5.1.3",
72
- "@songkeys/nestjs-redis": "^11.0.0",
73
- "@songkeys/nestjs-redis-health": "^11.0.0",
74
72
  "@nestjs/bull": "^11.0.0",
75
73
  "@nestjs/cache-manager": "^3.0.0",
76
74
  "@nestjs/common": "^11.0.0",
@@ -81,13 +79,15 @@
81
79
  "@nestjs/swagger": "^11.0.0",
82
80
  "@nestjs/terminus": "^11.0.0",
83
81
  "@nestjs/typeorm": "^11.0.0",
82
+ "@songkeys/nestjs-redis": "^11.0.0",
83
+ "@songkeys/nestjs-redis-health": "^11.0.0",
84
84
  "bcrypt": "^6.0.0",
85
85
  "bull": "^4.16.0",
86
86
  "cache-manager": "^7.0.0",
87
- "keyv": "^5.5.3",
88
87
  "connect-redis": "^9.0.0",
89
88
  "express": "^5.0.0",
90
89
  "express-session": "^1.18.0",
90
+ "keyv": "^5.5.3",
91
91
  "mime-types": "^3.0.0",
92
92
  "mysql2": "^3.0.0",
93
93
  "nestjs-cls": "^6.0.0",
package/setup/index.d.ts CHANGED
@@ -2,5 +2,5 @@ export * from './bootstrap.setup';
2
2
  export * from './mode.setup';
3
3
  export * from './worker.decorator';
4
4
  export * from './schedule.decorator';
5
- export * from './redis.lock.service';
6
- export * from './redis.lock.decorator';
5
+ export * from './redis-lock.service';
6
+ export * from './redis-lock.decorator';
package/setup/index.js CHANGED
@@ -18,5 +18,5 @@ __exportStar(require("./bootstrap.setup"), exports);
18
18
  __exportStar(require("./mode.setup"), exports);
19
19
  __exportStar(require("./worker.decorator"), exports);
20
20
  __exportStar(require("./schedule.decorator"), exports);
21
- __exportStar(require("./redis.lock.service"), exports);
22
- __exportStar(require("./redis.lock.decorator"), exports);
21
+ __exportStar(require("./redis-lock.service"), exports);
22
+ __exportStar(require("./redis-lock.decorator"), exports);
@@ -1,4 +1,4 @@
1
- import type { LockOptions } from './redis.lock.service';
1
+ import type { LockOptions } from './redis-lock.service';
2
2
  export declare function UseRedisLock(lockKey: string, options?: LockOptions & {
3
3
  skipReturnValue?: any;
4
4
  }): MethodDecorator;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.UseRedisLock = UseRedisLock;
13
+ exports.UseRedisLockOrSkip = UseRedisLockOrSkip;
14
+ const common_1 = require("@nestjs/common");
15
+ function UseRedisLock(lockKey, options = {}) {
16
+ return function (target, propertyKey, descriptor) {
17
+ const originalMethod = descriptor.value;
18
+ const logger = new common_1.Logger(`RedisLock:${String(propertyKey)}`);
19
+ descriptor.value = function (...args) {
20
+ return __awaiter(this, void 0, void 0, function* () {
21
+ var _a;
22
+ const { RedisLockService } = yield Promise.resolve().then(() => require('./redis-lock.service'));
23
+ let lockService = RedisLockService.getGlobalInstance();
24
+ if (!lockService) {
25
+ try {
26
+ lockService = RedisLockService.getOrCreateGlobalInstance();
27
+ logger.debug('RedisLockService auto-initialized for decorator');
28
+ }
29
+ catch (error) {
30
+ logger.error(`Failed to auto-initialize RedisLockService: ${error.message}. ` +
31
+ `Please ensure Redis is accessible or call configureRedisLock() in your application setup.`);
32
+ throw new Error(`RedisLockService initialization failed. Please check Redis connection or call configureRedisLock() in your application setup.`);
33
+ }
34
+ }
35
+ const skipReturnValue = (_a = options.skipReturnValue) !== null && _a !== void 0 ? _a : null;
36
+ try {
37
+ const lockResult = yield lockService.acquireLock(lockKey, options);
38
+ if (!lockResult.acquired) {
39
+ logger.log(`Lock '${lockKey}' is already held, skipping execution of ${String(propertyKey)}`);
40
+ return skipReturnValue;
41
+ }
42
+ logger.debug(`Lock '${lockKey}' acquired, executing ${String(propertyKey)}`);
43
+ try {
44
+ return yield originalMethod.apply(this, args);
45
+ }
46
+ catch (error) {
47
+ logger.error(`Error executing ${String(propertyKey)} with lock '${lockKey}':`, error);
48
+ throw error;
49
+ }
50
+ finally {
51
+ if (lockResult.autoExtendTimer) {
52
+ clearInterval(lockResult.autoExtendTimer);
53
+ }
54
+ yield lockService.releaseLock(lockKey, lockResult.lockValue, options.keyPrefix);
55
+ logger.debug(`Lock '${lockKey}' released`);
56
+ }
57
+ }
58
+ catch (error) {
59
+ if (error.message.includes('ECONNREFUSED') ||
60
+ error.message.includes('Redis connection') ||
61
+ error.message.includes('RedisLockService initialization failed')) {
62
+ logger.error(`Redis connection error in ${String(propertyKey)}: ${error.message}. ` +
63
+ `Skipping execution to prevent issues.`);
64
+ return skipReturnValue;
65
+ }
66
+ throw error;
67
+ }
68
+ });
69
+ };
70
+ return descriptor;
71
+ };
72
+ }
73
+ function UseRedisLockOrSkip(lockKey, ttl = 300000) {
74
+ return UseRedisLock(lockKey, {
75
+ ttl,
76
+ skipReturnValue: false,
77
+ });
78
+ }
@@ -24,6 +24,7 @@ export interface RedisOptions {
24
24
  }
25
25
  export declare class RedisLockService implements OnModuleInit, OnModuleDestroy {
26
26
  private static globalInstance;
27
+ private static globalConfig;
27
28
  private readonly logger;
28
29
  private redis;
29
30
  private redisOptions;
@@ -33,7 +34,9 @@ export declare class RedisLockService implements OnModuleInit, OnModuleDestroy {
33
34
  private readonly defaultOptions;
34
35
  private readonly defaultRedisOptions;
35
36
  constructor(redisOptions?: RedisOptions);
37
+ static initializeGlobalInstance(config?: RedisOptions): RedisLockService;
36
38
  static getGlobalInstance(): RedisLockService | null;
39
+ static getOrCreateGlobalInstance(): RedisLockService;
37
40
  static setGlobalInstance(instance: RedisLockService): void;
38
41
  onModuleInit(): Promise<void>;
39
42
  onModuleDestroy(): Promise<void>;
@@ -49,14 +49,37 @@ let RedisLockService = RedisLockService_1 = class RedisLockService {
49
49
  return true;
50
50
  },
51
51
  };
52
- this.redisOptions = Object.assign(Object.assign({}, this.defaultRedisOptions), redisOptions);
52
+ this.redisOptions = redisOptions ||
53
+ RedisLockService_1.globalConfig || Object.assign({}, this.defaultRedisOptions);
53
54
  if (!RedisLockService_1.globalInstance) {
54
55
  RedisLockService_1.globalInstance = this;
55
56
  }
56
57
  }
58
+ static initializeGlobalInstance(config) {
59
+ if (!RedisLockService_1.globalInstance) {
60
+ new RedisLockService_1(config || RedisLockService_1.globalConfig);
61
+ }
62
+ return RedisLockService_1.globalInstance;
63
+ }
57
64
  static getGlobalInstance() {
58
65
  return RedisLockService_1.globalInstance;
59
66
  }
67
+ static getOrCreateGlobalInstance() {
68
+ if (!RedisLockService_1.globalInstance) {
69
+ if (!RedisLockService_1.globalConfig) {
70
+ RedisLockService_1.globalConfig = {
71
+ host: process.env.REDIS_HOST || 'localhost',
72
+ port: parseInt(process.env.REDIS_PORT || '6379', 10),
73
+ password: process.env.REDIS_PASSWORD,
74
+ db: parseInt(process.env.REDIS_DB || '0', 10),
75
+ retryDelay: 2000,
76
+ maxRetries: 10,
77
+ };
78
+ }
79
+ return RedisLockService_1.initializeGlobalInstance();
80
+ }
81
+ return RedisLockService_1.globalInstance;
82
+ }
60
83
  static setGlobalInstance(instance) {
61
84
  RedisLockService_1.globalInstance = instance;
62
85
  }
@@ -332,6 +355,7 @@ let RedisLockService = RedisLockService_1 = class RedisLockService {
332
355
  };
333
356
  exports.RedisLockService = RedisLockService;
334
357
  RedisLockService.globalInstance = null;
358
+ RedisLockService.globalConfig = null;
335
359
  exports.RedisLockService = RedisLockService = RedisLockService_1 = __decorate([
336
360
  (0, common_1.Injectable)(),
337
361
  __metadata("design:paramtypes", [Object])
@@ -1,21 +1,23 @@
1
1
  import type { CronOptions } from '@nestjs/schedule';
2
- export declare function WorkerCron(cronTime: string | Date, options?: CronOptions): MethodDecorator;
3
- export declare function WorkerInterval(timeout: number, options?: {
4
- name?: string;
5
- }): MethodDecorator;
6
- export declare function WorkerTimeout(timeout: number, options?: {
7
- name?: string;
8
- }): MethodDecorator;
9
- export declare function WorkerCronWithLock(cronTime: string | Date, lockKey: string, lockTtl?: number, cronOptions?: CronOptions): MethodDecorator;
10
- export declare function WorkerIntervalWithLock(timeout: number, lockKey: string, lockTtl?: number, intervalOptions?: {
11
- name?: string;
12
- }): MethodDecorator;
13
- export declare function WorkerTimeoutWithLock(timeout: number, lockKey: string, lockTtl?: number, timeoutOptions?: {
14
- name?: string;
15
- }): MethodDecorator;
16
- export declare function WorkerCronAdvanced(cronTime: string | Date, lockKey: string, options?: {
2
+ export interface ScheduleWithLockOptions {
17
3
  lockTtl?: number;
18
- cronOptions?: CronOptions;
4
+ retryCount?: number;
5
+ retryDelay?: number;
6
+ useExponentialBackoff?: boolean;
7
+ maxRetryDelay?: number;
19
8
  logExecution?: boolean;
20
- onError?: (error: Error) => void;
21
- }): MethodDecorator;
9
+ lockKeyPrefix?: string;
10
+ autoExtendLock?: number;
11
+ onSuccess?: (duration: number) => void | Promise<void>;
12
+ onError?: (error: Error) => void | Promise<void>;
13
+ skipIfLocked?: boolean;
14
+ }
15
+ export declare function WorkerCron(cronTime: string | Date, options?: CronOptions): MethodDecorator;
16
+ export declare function WorkerInterval(timeout: number, name?: string): MethodDecorator;
17
+ export declare function WorkerTimeout(timeout: number, name?: string): MethodDecorator;
18
+ export declare function WorkerCronWithLock(cronTime: string | Date, lockKeyOrOptions: string | ScheduleWithLockOptions, lockTtl?: number, cronOptions?: CronOptions): MethodDecorator;
19
+ export declare function WorkerIntervalWithLock(timeout: number, lockKeyOrOptions: string | ScheduleWithLockOptions, lockTtl?: number): MethodDecorator;
20
+ export declare function WorkerTimeoutWithLock(timeout: number, lockKeyOrOptions: string | ScheduleWithLockOptions, lockTtl?: number): MethodDecorator;
21
+ export declare function WorkerCronSmart(cronTime: string | Date, options?: ScheduleWithLockOptions, cronOptions?: CronOptions): MethodDecorator;
22
+ export declare function WorkerIntervalSmart(timeout: number, options?: ScheduleWithLockOptions): MethodDecorator;
23
+ export declare function WorkerCronAdvanced(cronTime: string | Date, lockKeyOrOptions: string | ScheduleWithLockOptions, options?: ScheduleWithLockOptions, cronOptions?: CronOptions): MethodDecorator;
@@ -0,0 +1,18 @@
1
+ export declare class SchedulerExamples {
2
+ dailyBasicTask(): Promise<void>;
3
+ sixHourlyTaskWithLock(): Promise<void>;
4
+ twoHourlyTaskWithOptions(): Promise<void>;
5
+ hourlySmartTask(): Promise<void>;
6
+ nightlySmartTask(): Promise<void>;
7
+ weeklyReportTask(): Promise<void>;
8
+ monthlyReportTask(): Promise<void>;
9
+ checkStatusWithLock(): Promise<void>;
10
+ checkStatusWithOptions(): Promise<void>;
11
+ checkStatusSmart(): Promise<void>;
12
+ syncDataSmart(): Promise<void>;
13
+ initializeWithLock(): Promise<void>;
14
+ warmUpWithOptions(): Promise<void>;
15
+ weekdayTask(): Promise<void>;
16
+ processDataWithRetry(): Promise<void>;
17
+ private performDataProcessing;
18
+ }
@@ -0,0 +1,255 @@
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 __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
12
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
13
+ return new (P || (P = Promise))(function (resolve, reject) {
14
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
15
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
16
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
17
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
18
+ });
19
+ };
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.SchedulerExamples = void 0;
22
+ const common_1 = require("@nestjs/common");
23
+ const schedule_decorator_1 = require("./schedule.decorator");
24
+ let SchedulerExamples = class SchedulerExamples {
25
+ dailyBasicTask() {
26
+ return __awaiter(this, void 0, void 0, function* () {
27
+ console.log('执行基本定时任务');
28
+ });
29
+ }
30
+ sixHourlyTaskWithLock() {
31
+ return __awaiter(this, void 0, void 0, function* () {
32
+ console.log('执行带锁的定时任务');
33
+ });
34
+ }
35
+ twoHourlyTaskWithOptions() {
36
+ return __awaiter(this, void 0, void 0, function* () {
37
+ console.log('执行带选项的定时任务');
38
+ });
39
+ }
40
+ hourlySmartTask() {
41
+ return __awaiter(this, void 0, void 0, function* () {
42
+ console.log('执行智能定时任务');
43
+ });
44
+ }
45
+ nightlySmartTask() {
46
+ return __awaiter(this, void 0, void 0, function* () {
47
+ console.log('执行夜间智能定时任务');
48
+ });
49
+ }
50
+ weeklyReportTask() {
51
+ return __awaiter(this, void 0, void 0, function* () {
52
+ console.log('生成周报');
53
+ });
54
+ }
55
+ monthlyReportTask() {
56
+ return __awaiter(this, void 0, void 0, function* () {
57
+ console.log('生成月报');
58
+ });
59
+ }
60
+ checkStatusWithLock() {
61
+ return __awaiter(this, void 0, void 0, function* () {
62
+ console.log('检查系统状态');
63
+ });
64
+ }
65
+ checkStatusWithOptions() {
66
+ return __awaiter(this, void 0, void 0, function* () {
67
+ console.log('检查系统状态(带选项)');
68
+ });
69
+ }
70
+ checkStatusSmart() {
71
+ return __awaiter(this, void 0, void 0, function* () {
72
+ console.log('智能检查系统状态');
73
+ });
74
+ }
75
+ syncDataSmart() {
76
+ return __awaiter(this, void 0, void 0, function* () {
77
+ console.log('智能同步数据');
78
+ });
79
+ }
80
+ initializeWithLock() {
81
+ return __awaiter(this, void 0, void 0, function* () {
82
+ console.log('初始化系统');
83
+ });
84
+ }
85
+ warmUpWithOptions() {
86
+ return __awaiter(this, void 0, void 0, function* () {
87
+ console.log('系统预热');
88
+ });
89
+ }
90
+ weekdayTask() {
91
+ return __awaiter(this, void 0, void 0, function* () {
92
+ console.log('执行工作日任务');
93
+ });
94
+ }
95
+ processDataWithRetry() {
96
+ return __awaiter(this, void 0, void 0, function* () {
97
+ console.log('开始处理数据');
98
+ try {
99
+ yield this.performDataProcessing();
100
+ }
101
+ catch (error) {
102
+ console.error('数据处理失败:', error);
103
+ throw error;
104
+ }
105
+ });
106
+ }
107
+ performDataProcessing() {
108
+ return __awaiter(this, void 0, void 0, function* () {
109
+ console.log('数据处理完成');
110
+ });
111
+ }
112
+ };
113
+ exports.SchedulerExamples = SchedulerExamples;
114
+ __decorate([
115
+ (0, schedule_decorator_1.WorkerCron)('0 0 * * *'),
116
+ __metadata("design:type", Function),
117
+ __metadata("design:paramtypes", []),
118
+ __metadata("design:returntype", Promise)
119
+ ], SchedulerExamples.prototype, "dailyBasicTask", null);
120
+ __decorate([
121
+ (0, schedule_decorator_1.WorkerCronWithLock)('0 */6 * * *', 'six-hourly-task', 3600000),
122
+ __metadata("design:type", Function),
123
+ __metadata("design:paramtypes", []),
124
+ __metadata("design:returntype", Promise)
125
+ ], SchedulerExamples.prototype, "sixHourlyTaskWithLock", null);
126
+ __decorate([
127
+ (0, schedule_decorator_1.WorkerCronWithLock)('0 */2 * * *', {
128
+ lockTtl: 5400000,
129
+ logExecution: true,
130
+ onError: (error) => console.error('任务执行失败:', error),
131
+ }),
132
+ __metadata("design:type", Function),
133
+ __metadata("design:paramtypes", []),
134
+ __metadata("design:returntype", Promise)
135
+ ], SchedulerExamples.prototype, "twoHourlyTaskWithOptions", null);
136
+ __decorate([
137
+ (0, schedule_decorator_1.WorkerCronSmart)('0 * * * *'),
138
+ __metadata("design:type", Function),
139
+ __metadata("design:paramtypes", []),
140
+ __metadata("design:returntype", Promise)
141
+ ], SchedulerExamples.prototype, "hourlySmartTask", null);
142
+ __decorate([
143
+ (0, schedule_decorator_1.WorkerCronSmart)('30 2 * * *', {
144
+ lockTtl: 3600000,
145
+ logExecution: true,
146
+ onError: (error) => console.error('夜间任务失败:', error),
147
+ onSuccess: (duration) => console.log(`夜间任务完成,耗时: ${duration}ms`),
148
+ }),
149
+ __metadata("design:type", Function),
150
+ __metadata("design:paramtypes", []),
151
+ __metadata("design:returntype", Promise)
152
+ ], SchedulerExamples.prototype, "nightlySmartTask", null);
153
+ __decorate([
154
+ (0, schedule_decorator_1.WorkerCronAdvanced)('0 0 * * 0', 'weekly-report', {
155
+ lockTtl: 7200000,
156
+ logExecution: true,
157
+ onError: (error) => console.error('周报生成失败:', error),
158
+ }),
159
+ __metadata("design:type", Function),
160
+ __metadata("design:paramtypes", []),
161
+ __metadata("design:returntype", Promise)
162
+ ], SchedulerExamples.prototype, "weeklyReportTask", null);
163
+ __decorate([
164
+ (0, schedule_decorator_1.WorkerCronAdvanced)('0 0 1 * *', {
165
+ lockTtl: 14400000,
166
+ logExecution: true,
167
+ onError: (error) => console.error('月报生成失败:', error),
168
+ onSuccess: (duration) => console.log(`月报生成完成,耗时: ${duration}ms`),
169
+ }),
170
+ __metadata("design:type", Function),
171
+ __metadata("design:paramtypes", []),
172
+ __metadata("design:returntype", Promise)
173
+ ], SchedulerExamples.prototype, "monthlyReportTask", null);
174
+ __decorate([
175
+ (0, schedule_decorator_1.WorkerIntervalWithLock)(60000, 'status-check'),
176
+ __metadata("design:type", Function),
177
+ __metadata("design:paramtypes", []),
178
+ __metadata("design:returntype", Promise)
179
+ ], SchedulerExamples.prototype, "checkStatusWithLock", null);
180
+ __decorate([
181
+ (0, schedule_decorator_1.WorkerIntervalWithLock)(300000, {
182
+ lockTtl: 240000,
183
+ logExecution: true,
184
+ onError: (error) => console.error('状态检查失败:', error),
185
+ }),
186
+ __metadata("design:type", Function),
187
+ __metadata("design:paramtypes", []),
188
+ __metadata("design:returntype", Promise)
189
+ ], SchedulerExamples.prototype, "checkStatusWithOptions", null);
190
+ __decorate([
191
+ (0, schedule_decorator_1.WorkerIntervalSmart)(120000),
192
+ __metadata("design:type", Function),
193
+ __metadata("design:paramtypes", []),
194
+ __metadata("design:returntype", Promise)
195
+ ], SchedulerExamples.prototype, "checkStatusSmart", null);
196
+ __decorate([
197
+ (0, schedule_decorator_1.WorkerIntervalSmart)(600000, {
198
+ lockTtl: 480000,
199
+ logExecution: true,
200
+ onError: (error) => console.error('数据同步失败:', error),
201
+ onSuccess: (duration) => console.log(`数据同步完成,耗时: ${duration}ms`),
202
+ }),
203
+ __metadata("design:type", Function),
204
+ __metadata("design:paramtypes", []),
205
+ __metadata("design:returntype", Promise)
206
+ ], SchedulerExamples.prototype, "syncDataSmart", null);
207
+ __decorate([
208
+ (0, schedule_decorator_1.WorkerTimeoutWithLock)(5000, 'init-task', 10000),
209
+ __metadata("design:type", Function),
210
+ __metadata("design:paramtypes", []),
211
+ __metadata("design:returntype", Promise)
212
+ ], SchedulerExamples.prototype, "initializeWithLock", null);
213
+ __decorate([
214
+ (0, schedule_decorator_1.WorkerTimeoutWithLock)(10000, {
215
+ lockTtl: 30000,
216
+ logExecution: true,
217
+ onError: (error) => console.error('预热任务失败:', error),
218
+ }),
219
+ __metadata("design:type", Function),
220
+ __metadata("design:paramtypes", []),
221
+ __metadata("design:returntype", Promise)
222
+ ], SchedulerExamples.prototype, "warmUpWithOptions", null);
223
+ __decorate([
224
+ (0, schedule_decorator_1.WorkerCronSmart)('0 9 * * 1-5', {
225
+ lockTtl: 3600000,
226
+ logExecution: true,
227
+ onError: (error) => console.error('工作日任务失败:', error),
228
+ onSuccess: (duration) => {
229
+ console.log(`工作日任务完成,耗时: ${duration}ms`);
230
+ },
231
+ }),
232
+ __metadata("design:type", Function),
233
+ __metadata("design:paramtypes", []),
234
+ __metadata("design:returntype", Promise)
235
+ ], SchedulerExamples.prototype, "weekdayTask", null);
236
+ __decorate([
237
+ (0, schedule_decorator_1.WorkerCronSmart)('0 */30 * * * *', {
238
+ lockTtl: 1500000,
239
+ logExecution: true,
240
+ onError: (error) => __awaiter(void 0, void 0, void 0, function* () {
241
+ console.error('数据处理任务失败:', error);
242
+ }),
243
+ onSuccess: (duration) => {
244
+ if (duration > 60000) {
245
+ console.warn(`数据处理任务耗时较长: ${duration}ms`);
246
+ }
247
+ },
248
+ }),
249
+ __metadata("design:type", Function),
250
+ __metadata("design:paramtypes", []),
251
+ __metadata("design:returntype", Promise)
252
+ ], SchedulerExamples.prototype, "processDataWithRetry", null);
253
+ exports.SchedulerExamples = SchedulerExamples = __decorate([
254
+ (0, common_1.Injectable)()
255
+ ], SchedulerExamples);
@@ -15,113 +15,219 @@ exports.WorkerTimeout = WorkerTimeout;
15
15
  exports.WorkerCronWithLock = WorkerCronWithLock;
16
16
  exports.WorkerIntervalWithLock = WorkerIntervalWithLock;
17
17
  exports.WorkerTimeoutWithLock = WorkerTimeoutWithLock;
18
+ exports.WorkerCronSmart = WorkerCronSmart;
19
+ exports.WorkerIntervalSmart = WorkerIntervalSmart;
18
20
  exports.WorkerCronAdvanced = WorkerCronAdvanced;
21
+ const common_1 = require("@nestjs/common");
19
22
  const schedule_1 = require("@nestjs/schedule");
20
23
  const mode_setup_1 = require("./mode.setup");
21
- const redis_lock_decorator_1 = require("./redis.lock.decorator");
22
- const common_1 = require("@nestjs/common");
23
- function WorkerCron(cronTime, options) {
24
- if ((0, mode_setup_1.shouldProcessQueues)()) {
25
- return (0, schedule_1.Cron)(cronTime, options);
26
- }
27
- return function (target, propertyKey, descriptor) {
28
- return descriptor;
29
- };
30
- }
31
- function WorkerInterval(timeout, options) {
32
- if ((0, mode_setup_1.shouldProcessQueues)()) {
33
- return (0, schedule_1.Interval)((options === null || options === void 0 ? void 0 : options.name) || `interval-${timeout}`, timeout);
34
- }
35
- return function (target, propertyKey, descriptor) {
36
- return descriptor;
37
- };
38
- }
39
- function WorkerTimeout(timeout, options) {
40
- if ((0, mode_setup_1.shouldProcessQueues)()) {
41
- return (0, schedule_1.Timeout)((options === null || options === void 0 ? void 0 : options.name) || `timeout-${timeout}`, timeout);
42
- }
43
- return function (target, propertyKey, descriptor) {
44
- return descriptor;
45
- };
24
+ const redis_lock_service_1 = require("./redis-lock.service");
25
+ function generateLockKey(className, methodName) {
26
+ return `${className}.${methodName}`;
46
27
  }
47
- function WorkerCronWithLock(cronTime, lockKey, lockTtl = 300000, cronOptions) {
48
- if (!(0, mode_setup_1.shouldProcessQueues)()) {
49
- return function (target, propertyKey, descriptor) {
50
- return descriptor;
51
- };
52
- }
53
- return function (target, propertyKey, descriptor) {
54
- (0, schedule_1.Cron)(cronTime, cronOptions)(target, propertyKey, descriptor);
55
- (0, redis_lock_decorator_1.UseRedisLockOrSkip)(lockKey, lockTtl)(target, propertyKey, descriptor);
56
- return descriptor;
57
- };
28
+ function executeWithRetry(fn, options) {
29
+ return __awaiter(this, void 0, void 0, function* () {
30
+ const { retryCount = 0, retryDelay = 1000, useExponentialBackoff = false, maxRetryDelay = 60000, logger, taskName, } = options;
31
+ let lastError;
32
+ let attempt = 0;
33
+ while (attempt <= retryCount) {
34
+ try {
35
+ return yield fn();
36
+ }
37
+ catch (error) {
38
+ lastError = error;
39
+ attempt++;
40
+ if (attempt <= retryCount) {
41
+ let delay = retryDelay;
42
+ if (useExponentialBackoff) {
43
+ delay = Math.min(retryDelay * Math.pow(2, attempt - 1), maxRetryDelay);
44
+ }
45
+ logger.warn(`Task "${taskName}" failed (attempt ${attempt}/${retryCount + 1}), ` +
46
+ `retrying in ${delay}ms... Error: ${error.message}`);
47
+ yield new Promise((resolve) => setTimeout(resolve, delay));
48
+ }
49
+ }
50
+ }
51
+ throw lastError;
52
+ });
58
53
  }
59
- function WorkerIntervalWithLock(timeout, lockKey, lockTtl, intervalOptions) {
60
- if (!(0, mode_setup_1.shouldProcessQueues)()) {
61
- return function (target, propertyKey, descriptor) {
62
- return descriptor;
63
- };
64
- }
65
- const ttl = lockTtl !== null && lockTtl !== void 0 ? lockTtl : timeout;
54
+ function createWorkerDecorator(baseDecorator, decoratorName) {
66
55
  return function (target, propertyKey, descriptor) {
67
- (0, schedule_1.Interval)((intervalOptions === null || intervalOptions === void 0 ? void 0 : intervalOptions.name) || `interval-with-lock-${timeout}`, timeout)(target, propertyKey, descriptor);
68
- (0, redis_lock_decorator_1.UseRedisLockOrSkip)(lockKey, ttl)(target, propertyKey, descriptor);
69
- return descriptor;
70
- };
71
- }
72
- function WorkerTimeoutWithLock(timeout, lockKey, lockTtl = 300000, timeoutOptions) {
73
- if (!(0, mode_setup_1.shouldProcessQueues)()) {
74
- return function (target, propertyKey, descriptor) {
75
- return descriptor;
56
+ const originalMethod = descriptor.value;
57
+ descriptor.value = function (...args) {
58
+ return __awaiter(this, void 0, void 0, function* () {
59
+ if (!(0, mode_setup_1.shouldProcessQueues)()) {
60
+ return;
61
+ }
62
+ return originalMethod.apply(this, args);
63
+ });
76
64
  };
77
- }
78
- return function (target, propertyKey, descriptor) {
79
- (0, schedule_1.Timeout)((timeoutOptions === null || timeoutOptions === void 0 ? void 0 : timeoutOptions.name) || `timeout-with-lock-${timeout}`, timeout)(target, propertyKey, descriptor);
80
- (0, redis_lock_decorator_1.UseRedisLockOrSkip)(lockKey, lockTtl)(target, propertyKey, descriptor);
65
+ baseDecorator(target, propertyKey, descriptor);
81
66
  return descriptor;
82
67
  };
83
68
  }
84
- function WorkerCronAdvanced(cronTime, lockKey, options = {}) {
85
- if (!(0, mode_setup_1.shouldProcessQueues)()) {
86
- return function (target, propertyKey, descriptor) {
87
- return descriptor;
88
- };
89
- }
90
- const { lockTtl = 300000, cronOptions, logExecution = true, onError, } = options;
69
+ function createWorkerDecoratorWithLock(baseDecorator, decoratorName, lockKey, options = {}) {
91
70
  return function (target, propertyKey, descriptor) {
92
71
  const originalMethod = descriptor.value;
93
- const logger = new common_1.Logger(`Scheduler:${String(propertyKey)}`);
72
+ const className = target.constructor.name;
73
+ const methodName = String(propertyKey);
74
+ const logger = new common_1.Logger(`${className}.${methodName}`);
75
+ const resolvedLockKey = typeof lockKey === 'function' ? lockKey() : lockKey;
94
76
  descriptor.value = function (...args) {
95
77
  return __awaiter(this, void 0, void 0, function* () {
78
+ if (!(0, mode_setup_1.shouldProcessQueues)()) {
79
+ return;
80
+ }
81
+ const lockService = redis_lock_service_1.RedisLockService.getOrCreateGlobalInstance();
82
+ const { lockTtl = 3600000, retryCount = 0, retryDelay = 1000, useExponentialBackoff = false, maxRetryDelay = 60000, logExecution = true, lockKeyPrefix = 'schedule', autoExtendLock = 0, onSuccess, onError, skipIfLocked = true, } = options;
83
+ const fullLockKey = `${lockKeyPrefix}:${resolvedLockKey}`;
96
84
  const startTime = Date.now();
85
+ if (logExecution) {
86
+ logger.log(`Task starting...`);
87
+ }
97
88
  try {
98
- if (logExecution) {
99
- logger.log(`Starting scheduled task: ${String(propertyKey)}`);
89
+ const lockResult = yield lockService.acquireLock(resolvedLockKey, {
90
+ ttl: lockTtl,
91
+ keyPrefix: lockKeyPrefix,
92
+ autoExtend: autoExtendLock,
93
+ });
94
+ if (!lockResult.acquired) {
95
+ if (skipIfLocked) {
96
+ logger.debug(`Lock "${fullLockKey}" is held by another instance, skipping execution`);
97
+ return null;
98
+ }
99
+ else {
100
+ throw new Error(`Failed to acquire lock "${fullLockKey}"`);
101
+ }
100
102
  }
101
- const result = yield originalMethod.apply(this, args);
102
- if (logExecution) {
103
+ try {
104
+ const result = yield executeWithRetry(() => originalMethod.apply(this, args), {
105
+ retryCount,
106
+ retryDelay,
107
+ useExponentialBackoff,
108
+ maxRetryDelay,
109
+ logger,
110
+ taskName: `${className}.${methodName}`,
111
+ });
103
112
  const duration = Date.now() - startTime;
104
- logger.log(`Completed scheduled task: ${String(propertyKey)} (${duration}ms)`);
113
+ if (logExecution) {
114
+ logger.log(`Task completed successfully in ${duration}ms`);
115
+ }
116
+ if (onSuccess) {
117
+ yield onSuccess(duration);
118
+ }
119
+ return result;
120
+ }
121
+ finally {
122
+ if (lockResult.autoExtendTimer) {
123
+ clearInterval(lockResult.autoExtendTimer);
124
+ }
125
+ yield lockService.releaseLock(resolvedLockKey, lockResult.lockValue, lockKeyPrefix);
126
+ if (logExecution) {
127
+ logger.debug(`Lock "${fullLockKey}" released`);
128
+ }
105
129
  }
106
- return result;
107
130
  }
108
131
  catch (error) {
109
132
  const duration = Date.now() - startTime;
110
- logger.error(`Error in scheduled task: ${String(propertyKey)} (${duration}ms)`, error.stack);
133
+ if (logExecution) {
134
+ logger.error(`Task failed after ${duration}ms: ${error.message}`, error.stack);
135
+ }
111
136
  if (onError) {
112
- try {
113
- onError(error);
114
- }
115
- catch (handlerError) {
116
- logger.error('Error handler threw an error:', handlerError);
117
- }
137
+ yield onError(error);
118
138
  }
119
139
  throw error;
120
140
  }
121
141
  });
122
142
  };
123
- (0, schedule_1.Cron)(cronTime, cronOptions)(target, propertyKey, descriptor);
124
- (0, redis_lock_decorator_1.UseRedisLockOrSkip)(lockKey, lockTtl)(target, propertyKey, descriptor);
143
+ baseDecorator(target, propertyKey, descriptor);
125
144
  return descriptor;
126
145
  };
127
146
  }
147
+ function WorkerCron(cronTime, options) {
148
+ return createWorkerDecorator((0, schedule_1.Cron)(cronTime, options), 'WorkerCron');
149
+ }
150
+ function WorkerInterval(timeout, name) {
151
+ if (name) {
152
+ return createWorkerDecorator((0, schedule_1.Interval)(name, timeout), 'WorkerInterval');
153
+ }
154
+ return createWorkerDecorator((0, schedule_1.Interval)(timeout), 'WorkerInterval');
155
+ }
156
+ function WorkerTimeout(timeout, name) {
157
+ if (name) {
158
+ return createWorkerDecorator((0, schedule_1.Timeout)(name, timeout), 'WorkerTimeout');
159
+ }
160
+ return createWorkerDecorator((0, schedule_1.Timeout)(timeout), 'WorkerTimeout');
161
+ }
162
+ function WorkerCronWithLock(cronTime, lockKeyOrOptions, lockTtl, cronOptions) {
163
+ return function (target, propertyKey, descriptor) {
164
+ let lockKey;
165
+ let options;
166
+ if (typeof lockKeyOrOptions === 'string') {
167
+ lockKey = lockKeyOrOptions;
168
+ options = { lockTtl: lockTtl || 3600000 };
169
+ }
170
+ else {
171
+ lockKey = generateLockKey(target.constructor.name, String(propertyKey));
172
+ options = lockKeyOrOptions;
173
+ }
174
+ return createWorkerDecoratorWithLock((0, schedule_1.Cron)(cronTime, cronOptions), 'WorkerCronWithLock', lockKey, options)(target, propertyKey, descriptor);
175
+ };
176
+ }
177
+ function WorkerIntervalWithLock(timeout, lockKeyOrOptions, lockTtl) {
178
+ return function (target, propertyKey, descriptor) {
179
+ let lockKey;
180
+ let options;
181
+ if (typeof lockKeyOrOptions === 'string') {
182
+ lockKey = lockKeyOrOptions;
183
+ options = { lockTtl: lockTtl || Math.floor(timeout * 0.8) };
184
+ }
185
+ else {
186
+ lockKey = generateLockKey(target.constructor.name, String(propertyKey));
187
+ options = Object.assign({ lockTtl: Math.floor(timeout * 0.8) }, lockKeyOrOptions);
188
+ }
189
+ return createWorkerDecoratorWithLock((0, schedule_1.Interval)(timeout), 'WorkerIntervalWithLock', lockKey, options)(target, propertyKey, descriptor);
190
+ };
191
+ }
192
+ function WorkerTimeoutWithLock(timeout, lockKeyOrOptions, lockTtl) {
193
+ return function (target, propertyKey, descriptor) {
194
+ let lockKey;
195
+ let options;
196
+ if (typeof lockKeyOrOptions === 'string') {
197
+ lockKey = lockKeyOrOptions;
198
+ options = { lockTtl: lockTtl || 300000 };
199
+ }
200
+ else {
201
+ lockKey = generateLockKey(target.constructor.name, String(propertyKey));
202
+ options = lockKeyOrOptions;
203
+ }
204
+ return createWorkerDecoratorWithLock((0, schedule_1.Timeout)(timeout), 'WorkerTimeoutWithLock', lockKey, options)(target, propertyKey, descriptor);
205
+ };
206
+ }
207
+ function WorkerCronSmart(cronTime, options = {}, cronOptions) {
208
+ return function (target, propertyKey, descriptor) {
209
+ const lockKey = generateLockKey(target.constructor.name, String(propertyKey));
210
+ return createWorkerDecoratorWithLock((0, schedule_1.Cron)(cronTime, cronOptions), 'WorkerCronSmart', lockKey, Object.assign({ lockTtl: 3600000, logExecution: true }, options))(target, propertyKey, descriptor);
211
+ };
212
+ }
213
+ function WorkerIntervalSmart(timeout, options = {}) {
214
+ return function (target, propertyKey, descriptor) {
215
+ const lockKey = generateLockKey(target.constructor.name, String(propertyKey));
216
+ return createWorkerDecoratorWithLock((0, schedule_1.Interval)(timeout), 'WorkerIntervalSmart', lockKey, Object.assign({ lockTtl: Math.floor(timeout * 0.8), logExecution: true }, options))(target, propertyKey, descriptor);
217
+ };
218
+ }
219
+ function WorkerCronAdvanced(cronTime, lockKeyOrOptions, options, cronOptions) {
220
+ return function (target, propertyKey, descriptor) {
221
+ let lockKey;
222
+ let finalOptions;
223
+ if (typeof lockKeyOrOptions === 'string') {
224
+ lockKey = lockKeyOrOptions;
225
+ finalOptions = Object.assign({ lockTtl: 3600000, logExecution: true }, options);
226
+ }
227
+ else {
228
+ lockKey = generateLockKey(target.constructor.name, String(propertyKey));
229
+ finalOptions = Object.assign({ lockTtl: 3600000, logExecution: true }, lockKeyOrOptions);
230
+ }
231
+ return createWorkerDecoratorWithLock((0, schedule_1.Cron)(cronTime, cronOptions), 'WorkerCronAdvanced', lockKey, finalOptions)(target, propertyKey, descriptor);
232
+ };
233
+ }
@@ -1,60 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.UseRedisLock = UseRedisLock;
13
- exports.UseRedisLockOrSkip = UseRedisLockOrSkip;
14
- const common_1 = require("@nestjs/common");
15
- function UseRedisLock(lockKey, options = {}) {
16
- return function (target, propertyKey, descriptor) {
17
- const originalMethod = descriptor.value;
18
- const logger = new common_1.Logger(`RedisLock:${String(propertyKey)}`);
19
- descriptor.value = function (...args) {
20
- return __awaiter(this, void 0, void 0, function* () {
21
- var _a;
22
- const { RedisLockService } = yield Promise.resolve().then(() => require('./redis.lock.service'));
23
- const lockService = RedisLockService.getGlobalInstance();
24
- if (!lockService) {
25
- logger.error(`RedisLockService global instance not found. ` +
26
- `Please ensure RedisLockService is registered in your application module.`);
27
- throw new Error(`RedisLockService not initialized. Please register it in your module.`);
28
- }
29
- const skipReturnValue = (_a = options.skipReturnValue) !== null && _a !== void 0 ? _a : null;
30
- const lockResult = yield lockService.acquireLock(lockKey, options);
31
- if (!lockResult.acquired) {
32
- logger.log(`Lock '${lockKey}' is already held, skipping execution of ${String(propertyKey)}`);
33
- return skipReturnValue;
34
- }
35
- logger.debug(`Lock '${lockKey}' acquired, executing ${String(propertyKey)}`);
36
- try {
37
- return yield originalMethod.apply(this, args);
38
- }
39
- catch (error) {
40
- logger.error(`Error executing ${String(propertyKey)} with lock '${lockKey}':`, error);
41
- throw error;
42
- }
43
- finally {
44
- if (lockResult.autoExtendTimer) {
45
- clearInterval(lockResult.autoExtendTimer);
46
- }
47
- yield lockService.releaseLock(lockKey, lockResult.lockValue, options.keyPrefix);
48
- logger.debug(`Lock '${lockKey}' released`);
49
- }
50
- });
51
- };
52
- return descriptor;
53
- };
54
- }
55
- function UseRedisLockOrSkip(lockKey, ttl = 300000) {
56
- return UseRedisLock(lockKey, {
57
- ttl,
58
- skipReturnValue: false,
59
- });
60
- }