koatty_schedule 3.1.0 → 3.3.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/.rollup.config.js +48 -51
- package/CHANGELOG.md +33 -0
- package/README.md +2 -4
- package/dist/README.md +2 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +30 -28
- package/dist/index.mjs +30 -28
- package/dist/package.json +14 -7
- package/package.json +14 -7
package/.rollup.config.js
CHANGED
|
@@ -3,61 +3,58 @@
|
|
|
3
3
|
* @Usage:
|
|
4
4
|
* @Author: richen
|
|
5
5
|
* @Date: 2021-12-17 10:20:44
|
|
6
|
-
* @LastEditTime:
|
|
6
|
+
* @LastEditTime: 2024-11-04 22:04:45
|
|
7
7
|
*/
|
|
8
|
+
import commonjs from '@rollup/plugin-commonjs';
|
|
8
9
|
import json from "@rollup/plugin-json";
|
|
10
|
+
import resolve from '@rollup/plugin-node-resolve';
|
|
11
|
+
import { builtinModules } from 'module';
|
|
12
|
+
import del from "rollup-plugin-delete";
|
|
9
13
|
import typescript from 'rollup-plugin-typescript2';
|
|
10
14
|
// import babel from '@rollup/plugin-babel';
|
|
15
|
+
const pkg = require('./package.json');
|
|
11
16
|
|
|
12
17
|
export default [
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
declaration: false,
|
|
56
|
-
declarationMap: false,
|
|
57
|
-
module: "ESNext"
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
})
|
|
61
|
-
]
|
|
62
|
-
}
|
|
18
|
+
{
|
|
19
|
+
input: './src/index.ts',
|
|
20
|
+
output: [
|
|
21
|
+
{
|
|
22
|
+
format: 'cjs',
|
|
23
|
+
file: './dist/index.js',
|
|
24
|
+
banner: require('./scripts/copyright'),
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
format: 'es',
|
|
28
|
+
file: './dist/index.mjs',
|
|
29
|
+
banner: require('./scripts/copyright'),
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
plugins: [
|
|
33
|
+
del({ targets: ["dist/*", "temp/*", "docs/api"] }),
|
|
34
|
+
// babel({
|
|
35
|
+
// babelHelpers: "runtime",
|
|
36
|
+
// configFile: './babel.config.js',
|
|
37
|
+
// exclude: 'node_modules/**',
|
|
38
|
+
// }),
|
|
39
|
+
json(),
|
|
40
|
+
resolve({
|
|
41
|
+
preferBuiltins: true, // 优先选择内置模块
|
|
42
|
+
}),
|
|
43
|
+
commonjs(),
|
|
44
|
+
typescript({
|
|
45
|
+
tsconfigOverride: {
|
|
46
|
+
compilerOptions: {
|
|
47
|
+
declaration: false,
|
|
48
|
+
declarationMap: false,
|
|
49
|
+
module: "ESNext"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
],
|
|
54
|
+
external: [
|
|
55
|
+
...builtinModules, // 排除 Node.js 内置模块
|
|
56
|
+
...Object.keys(pkg.dependencies || {}), // 排除 package.json 中的外部依赖
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
|
|
63
60
|
]
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [3.3.0](https://github.com/thinkkoa/koatty_schedule/compare/v3.2.0...v3.3.0) (2025-06-22)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* enhance distributed locking and scheduling system with global configuration management and improved validation ([79a10f5](https://github.com/thinkkoa/koatty_schedule/commit/79a10f5a1ac66958aa44d3ea9151a65826748724))
|
|
11
|
+
* improve RedLock singleton management with thread-safe initialization and lock renewal enhancements ([ec426aa](https://github.com/thinkkoa/koatty_schedule/commit/ec426aae3cd0d824661b1b94ae8043bf66ace606))
|
|
12
|
+
* introduce component-specific metadata keys for scheduled and redlock decorators ([173e79a](https://github.com/thinkkoa/koatty_schedule/commit/173e79ac916c13b20c93d2efac7e69009cc5cf32))
|
|
13
|
+
* refactor RedLock configuration and remove deprecated ScheduleConfig ([7bd4667](https://github.com/thinkkoa/koatty_schedule/commit/7bd4667242c6fd07cfd58a4322d93f4c4548100a))
|
|
14
|
+
* update decorator types to support symbol property keys and improve IOC container integration ([f7b6382](https://github.com/thinkkoa/koatty_schedule/commit/f7b6382e855914176c130b10a769b03cc74c0f23))
|
|
15
|
+
* use dynamic componentType instead of hardcoded constants for IOCContainer registration ([42ca073](https://github.com/thinkkoa/koatty_schedule/commit/42ca07353a8082b1af9e49d43914497d41cddd27))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* 修复IOC容器元数据键格式不匹配问题 ([644714f](https://github.com/thinkkoa/koatty_schedule/commit/644714f20497196fb705e551880a9ef527257cb7))
|
|
21
|
+
|
|
22
|
+
### [2.1.1](https://github.com/thinkkoa/koatty_schedule/compare/v2.1.0...v2.1.1) (2025-06-09)
|
|
23
|
+
|
|
24
|
+
### [1.6.2](https://github.com/thinkkoa/koatty_schedule/compare/v2.0.1...v1.6.2) (2024-11-07)
|
|
25
|
+
|
|
26
|
+
## [3.2.0](https://github.com/thinkkoa/koatty_schedule/compare/v3.1.0...v3.2.0) (2025-06-22)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### Features
|
|
30
|
+
|
|
31
|
+
* introduce component-specific metadata keys for scheduled and redlock decorators ([803b350](https://github.com/thinkkoa/koatty_schedule/commit/803b3503489c02ab138b3f9f14cb520dd6c7fec4))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
### Bug Fixes
|
|
35
|
+
|
|
36
|
+
* 修复IOC容器元数据键格式不匹配问题 ([065d456](https://github.com/thinkkoa/koatty_schedule/commit/065d456fc65004e25eb19838da96bf0a52cb2af1))
|
|
37
|
+
|
|
5
38
|
## [3.1.0](https://github.com/thinkkoa/koatty_schedule/compare/v3.0.0...v3.1.0) (2025-06-21)
|
|
6
39
|
|
|
7
40
|
|
package/README.md
CHANGED
|
@@ -30,11 +30,9 @@ npm install koatty_schedule
|
|
|
30
30
|
Use Koatty CLI to generate the plugin template:
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
kt plugin
|
|
33
|
+
kt plugin Scheduled
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
### 2. Create Scheduled Plugin
|
|
37
|
-
|
|
38
36
|
Create `src/plugin/Scheduled.ts`:
|
|
39
37
|
|
|
40
38
|
```typescript
|
|
@@ -49,7 +47,7 @@ export class Scheduled implements IPlugin {
|
|
|
49
47
|
}
|
|
50
48
|
```
|
|
51
49
|
|
|
52
|
-
###
|
|
50
|
+
### 2. Configure Plugin
|
|
53
51
|
|
|
54
52
|
Update `src/config/plugin.ts`:
|
|
55
53
|
|
package/dist/README.md
CHANGED
|
@@ -30,11 +30,9 @@ npm install koatty_schedule
|
|
|
30
30
|
Use Koatty CLI to generate the plugin template:
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
kt plugin
|
|
33
|
+
kt plugin Scheduled
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
### 2. Create Scheduled Plugin
|
|
37
|
-
|
|
38
36
|
Create `src/plugin/Scheduled.ts`:
|
|
39
37
|
|
|
40
38
|
```typescript
|
|
@@ -49,7 +47,7 @@ export class Scheduled implements IPlugin {
|
|
|
49
47
|
}
|
|
50
48
|
```
|
|
51
49
|
|
|
52
|
-
###
|
|
50
|
+
### 2. Configure Plugin
|
|
53
51
|
|
|
54
52
|
Update `src/config/plugin.ts`:
|
|
55
53
|
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* @Author: richen
|
|
3
|
-
* @Date: 2025-06-
|
|
3
|
+
* @Date: 2025-06-22 23:27:42
|
|
4
4
|
* @License: BSD (3-Clause)
|
|
5
5
|
* @Copyright (c) - <richenlin(at)gmail.com>
|
|
6
6
|
* @HomePage: https://koatty.org/
|
|
@@ -23,6 +23,8 @@ var cron = require('cron');
|
|
|
23
23
|
* @License: BSD (3-Clause)
|
|
24
24
|
* @Copyright (c): <richenlin(at)gmail.com>
|
|
25
25
|
*/
|
|
26
|
+
const COMPONENT_SCHEDULED = 'COMPONENT_SCHEDULED';
|
|
27
|
+
const COMPONENT_REDLOCK = 'COMPONENT_REDLOCK';
|
|
26
28
|
/**
|
|
27
29
|
* Decorator types supported by the system
|
|
28
30
|
*/
|
|
@@ -138,10 +140,10 @@ function getEffectiveTimezone(userTimezone) {
|
|
|
138
140
|
function getEffectiveRedLockOptions(methodOptions) {
|
|
139
141
|
const globalOptions = getGlobalScheduledOptions();
|
|
140
142
|
return {
|
|
141
|
-
lockTimeOut:
|
|
142
|
-
clockDriftFactor:
|
|
143
|
-
maxRetries:
|
|
144
|
-
retryDelayMs:
|
|
143
|
+
lockTimeOut: methodOptions?.lockTimeOut || globalOptions.lockTimeOut || 10000,
|
|
144
|
+
clockDriftFactor: methodOptions?.clockDriftFactor || globalOptions.clockDriftFactor || 0.01,
|
|
145
|
+
maxRetries: methodOptions?.maxRetries || globalOptions.maxRetries || 3,
|
|
146
|
+
retryDelayMs: methodOptions?.retryDelayMs || globalOptions.retryDelayMs || 200
|
|
145
147
|
};
|
|
146
148
|
}
|
|
147
149
|
|
|
@@ -209,9 +211,9 @@ function RedLock(lockName, options) {
|
|
|
209
211
|
validateRedLockMethodOptions(options);
|
|
210
212
|
}
|
|
211
213
|
// 保存类到IOC容器
|
|
212
|
-
koatty_container.IOCContainer.saveClass(
|
|
214
|
+
koatty_container.IOCContainer.saveClass(componentType, targetClass, targetClass.name);
|
|
213
215
|
// 保存RedLock元数据到 IOC 容器(lockName已确定)
|
|
214
|
-
koatty_container.IOCContainer.attachClassMetadata(
|
|
216
|
+
koatty_container.IOCContainer.attachClassMetadata(COMPONENT_REDLOCK, DecoratorType.REDLOCK, {
|
|
215
217
|
method: methodName,
|
|
216
218
|
name: lockName, // 确定的锁名称,不会为undefined
|
|
217
219
|
options
|
|
@@ -279,9 +281,9 @@ function Scheduled(cron, timezone) {
|
|
|
279
281
|
throw Error("@Scheduled decorator can only be applied to methods");
|
|
280
282
|
}
|
|
281
283
|
// 保存类到IOC容器
|
|
282
|
-
koatty_container.IOCContainer.saveClass(
|
|
284
|
+
koatty_container.IOCContainer.saveClass(componentType, targetClass, targetClass.name);
|
|
283
285
|
// 保存调度元数据到 IOC 容器
|
|
284
|
-
koatty_container.IOCContainer.attachClassMetadata(
|
|
286
|
+
koatty_container.IOCContainer.attachClassMetadata(COMPONENT_SCHEDULED, DecoratorType.SCHEDULED, {
|
|
285
287
|
method: methodName,
|
|
286
288
|
cron,
|
|
287
289
|
timezone // 保存用户指定的值,可能为undefined
|
|
@@ -325,12 +327,15 @@ const defaultRedLockConfig = {
|
|
|
325
327
|
* Implements singleton pattern for safe instance management
|
|
326
328
|
*/
|
|
327
329
|
class RedLocker {
|
|
330
|
+
static instance = null;
|
|
331
|
+
static instanceLock = Symbol('RedLocker.instanceLock');
|
|
332
|
+
redlock = null;
|
|
333
|
+
redis = null;
|
|
334
|
+
config;
|
|
335
|
+
isInitialized = false;
|
|
336
|
+
initializationPromise = null;
|
|
328
337
|
// 私有构造函数防止外部直接实例化
|
|
329
338
|
constructor(options) {
|
|
330
|
-
this.redlock = null;
|
|
331
|
-
this.redis = null;
|
|
332
|
-
this.isInitialized = false;
|
|
333
|
-
this.initializationPromise = null;
|
|
334
339
|
this.config = { ...defaultRedLockConfig, ...options };
|
|
335
340
|
// Register this instance in IOC container
|
|
336
341
|
this.registerInContainer();
|
|
@@ -622,10 +627,9 @@ class RedLocker {
|
|
|
622
627
|
* @returns Health status
|
|
623
628
|
*/
|
|
624
629
|
async healthCheck() {
|
|
625
|
-
var _a;
|
|
626
630
|
try {
|
|
627
631
|
await this.initialize();
|
|
628
|
-
const redisStatus =
|
|
632
|
+
const redisStatus = this.redis?.status || 'unknown';
|
|
629
633
|
const isReady = this.isReady();
|
|
630
634
|
return {
|
|
631
635
|
status: isReady ? 'healthy' : 'unhealthy',
|
|
@@ -648,15 +652,13 @@ class RedLocker {
|
|
|
648
652
|
}
|
|
649
653
|
}
|
|
650
654
|
}
|
|
651
|
-
RedLocker.instance = null;
|
|
652
|
-
RedLocker.instanceLock = Symbol('RedLocker.instanceLock');
|
|
653
655
|
|
|
654
656
|
/*
|
|
655
657
|
* @Description:
|
|
656
658
|
* @Usage:
|
|
657
659
|
* @Author: richen
|
|
658
660
|
* @Date: 2024-01-16 19:53:14
|
|
659
|
-
* @LastEditTime: 2024-
|
|
661
|
+
* @LastEditTime: 2024-11-07 16:47:58
|
|
660
662
|
* @License: BSD (3-Clause)
|
|
661
663
|
* @Copyright (c): <richenlin(at)gmail.com>
|
|
662
664
|
*/
|
|
@@ -717,9 +719,9 @@ async function initRedLock(options, app) {
|
|
|
717
719
|
async function injectRedLock(_options, _app) {
|
|
718
720
|
try {
|
|
719
721
|
koatty_logger.DefaultLogger.Debug('Starting batch RedLock injection...');
|
|
720
|
-
const componentList = koatty_container.IOCContainer.listClass(
|
|
722
|
+
const componentList = koatty_container.IOCContainer.listClass(COMPONENT_REDLOCK);
|
|
721
723
|
for (const component of componentList) {
|
|
722
|
-
const classMetadata = koatty_container.IOCContainer.getClassMetadata(
|
|
724
|
+
const classMetadata = koatty_container.IOCContainer.getClassMetadata(COMPONENT_REDLOCK, DecoratorType.REDLOCK, component.target);
|
|
723
725
|
if (!classMetadata) {
|
|
724
726
|
continue;
|
|
725
727
|
}
|
|
@@ -732,7 +734,7 @@ async function injectRedLock(_options, _app) {
|
|
|
732
734
|
}
|
|
733
735
|
// 查找所有RedLock方法的元数据
|
|
734
736
|
for (const [key, value] of Object.entries(metadata)) {
|
|
735
|
-
if (key.startsWith('REDLOCK
|
|
737
|
+
if (key.startsWith('REDLOCK')) {
|
|
736
738
|
const redlockData = value;
|
|
737
739
|
const targetMethod = instance[redlockData.method];
|
|
738
740
|
if (!koatty_lib.Helper.isFunction(targetMethod)) {
|
|
@@ -794,10 +796,10 @@ function redLockerDescriptor(descriptor, name, method, methodOptions) {
|
|
|
794
796
|
}
|
|
795
797
|
// 设置默认选项,合并方法级别的选项
|
|
796
798
|
const lockOptions = {
|
|
797
|
-
lockTimeOut:
|
|
798
|
-
clockDriftFactor:
|
|
799
|
-
maxRetries:
|
|
800
|
-
retryDelayMs:
|
|
799
|
+
lockTimeOut: methodOptions?.lockTimeOut,
|
|
800
|
+
clockDriftFactor: methodOptions?.clockDriftFactor,
|
|
801
|
+
maxRetries: methodOptions?.maxRetries,
|
|
802
|
+
retryDelayMs: methodOptions?.retryDelayMs
|
|
801
803
|
};
|
|
802
804
|
/**
|
|
803
805
|
* Enhanced function wrapper with proper lock renewal and safety
|
|
@@ -903,9 +905,9 @@ function redLockerDescriptor(descriptor, name, method, methodOptions) {
|
|
|
903
905
|
async function injectSchedule(_options, _app) {
|
|
904
906
|
try {
|
|
905
907
|
koatty_logger.DefaultLogger.Debug('Starting batch schedule injection...');
|
|
906
|
-
const componentList = koatty_container.IOCContainer.listClass(
|
|
908
|
+
const componentList = koatty_container.IOCContainer.listClass(COMPONENT_SCHEDULED);
|
|
907
909
|
for (const component of componentList) {
|
|
908
|
-
const classMetadata = koatty_container.IOCContainer.getClassMetadata(
|
|
910
|
+
const classMetadata = koatty_container.IOCContainer.getClassMetadata(COMPONENT_SCHEDULED, DecoratorType.SCHEDULED, component.target);
|
|
909
911
|
if (!classMetadata) {
|
|
910
912
|
continue;
|
|
911
913
|
}
|
|
@@ -918,7 +920,7 @@ async function injectSchedule(_options, _app) {
|
|
|
918
920
|
}
|
|
919
921
|
// 查找所有调度方法的元数据
|
|
920
922
|
for (const [key, value] of Object.entries(metadata)) {
|
|
921
|
-
if (key.startsWith('SCHEDULED
|
|
923
|
+
if (key.startsWith('SCHEDULED')) {
|
|
922
924
|
const scheduleData = value;
|
|
923
925
|
const targetMethod = instance[scheduleData.method];
|
|
924
926
|
if (!koatty_lib.Helper.isFunction(targetMethod)) {
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* @Author: richen
|
|
3
|
-
* @Date: 2025-06-
|
|
3
|
+
* @Date: 2025-06-22 23:27:42
|
|
4
4
|
* @License: BSD (3-Clause)
|
|
5
5
|
* @Copyright (c) - <richenlin(at)gmail.com>
|
|
6
6
|
* @HomePage: https://koatty.org/
|
|
@@ -21,6 +21,8 @@ import { CronJob } from 'cron';
|
|
|
21
21
|
* @License: BSD (3-Clause)
|
|
22
22
|
* @Copyright (c): <richenlin(at)gmail.com>
|
|
23
23
|
*/
|
|
24
|
+
const COMPONENT_SCHEDULED = 'COMPONENT_SCHEDULED';
|
|
25
|
+
const COMPONENT_REDLOCK = 'COMPONENT_REDLOCK';
|
|
24
26
|
/**
|
|
25
27
|
* Decorator types supported by the system
|
|
26
28
|
*/
|
|
@@ -136,10 +138,10 @@ function getEffectiveTimezone(userTimezone) {
|
|
|
136
138
|
function getEffectiveRedLockOptions(methodOptions) {
|
|
137
139
|
const globalOptions = getGlobalScheduledOptions();
|
|
138
140
|
return {
|
|
139
|
-
lockTimeOut:
|
|
140
|
-
clockDriftFactor:
|
|
141
|
-
maxRetries:
|
|
142
|
-
retryDelayMs:
|
|
141
|
+
lockTimeOut: methodOptions?.lockTimeOut || globalOptions.lockTimeOut || 10000,
|
|
142
|
+
clockDriftFactor: methodOptions?.clockDriftFactor || globalOptions.clockDriftFactor || 0.01,
|
|
143
|
+
maxRetries: methodOptions?.maxRetries || globalOptions.maxRetries || 3,
|
|
144
|
+
retryDelayMs: methodOptions?.retryDelayMs || globalOptions.retryDelayMs || 200
|
|
143
145
|
};
|
|
144
146
|
}
|
|
145
147
|
|
|
@@ -207,9 +209,9 @@ function RedLock(lockName, options) {
|
|
|
207
209
|
validateRedLockMethodOptions(options);
|
|
208
210
|
}
|
|
209
211
|
// 保存类到IOC容器
|
|
210
|
-
IOCContainer.saveClass(
|
|
212
|
+
IOCContainer.saveClass(componentType, targetClass, targetClass.name);
|
|
211
213
|
// 保存RedLock元数据到 IOC 容器(lockName已确定)
|
|
212
|
-
IOCContainer.attachClassMetadata(
|
|
214
|
+
IOCContainer.attachClassMetadata(COMPONENT_REDLOCK, DecoratorType.REDLOCK, {
|
|
213
215
|
method: methodName,
|
|
214
216
|
name: lockName, // 确定的锁名称,不会为undefined
|
|
215
217
|
options
|
|
@@ -277,9 +279,9 @@ function Scheduled(cron, timezone) {
|
|
|
277
279
|
throw Error("@Scheduled decorator can only be applied to methods");
|
|
278
280
|
}
|
|
279
281
|
// 保存类到IOC容器
|
|
280
|
-
IOCContainer.saveClass(
|
|
282
|
+
IOCContainer.saveClass(componentType, targetClass, targetClass.name);
|
|
281
283
|
// 保存调度元数据到 IOC 容器
|
|
282
|
-
IOCContainer.attachClassMetadata(
|
|
284
|
+
IOCContainer.attachClassMetadata(COMPONENT_SCHEDULED, DecoratorType.SCHEDULED, {
|
|
283
285
|
method: methodName,
|
|
284
286
|
cron,
|
|
285
287
|
timezone // 保存用户指定的值,可能为undefined
|
|
@@ -323,12 +325,15 @@ const defaultRedLockConfig = {
|
|
|
323
325
|
* Implements singleton pattern for safe instance management
|
|
324
326
|
*/
|
|
325
327
|
class RedLocker {
|
|
328
|
+
static instance = null;
|
|
329
|
+
static instanceLock = Symbol('RedLocker.instanceLock');
|
|
330
|
+
redlock = null;
|
|
331
|
+
redis = null;
|
|
332
|
+
config;
|
|
333
|
+
isInitialized = false;
|
|
334
|
+
initializationPromise = null;
|
|
326
335
|
// 私有构造函数防止外部直接实例化
|
|
327
336
|
constructor(options) {
|
|
328
|
-
this.redlock = null;
|
|
329
|
-
this.redis = null;
|
|
330
|
-
this.isInitialized = false;
|
|
331
|
-
this.initializationPromise = null;
|
|
332
337
|
this.config = { ...defaultRedLockConfig, ...options };
|
|
333
338
|
// Register this instance in IOC container
|
|
334
339
|
this.registerInContainer();
|
|
@@ -620,10 +625,9 @@ class RedLocker {
|
|
|
620
625
|
* @returns Health status
|
|
621
626
|
*/
|
|
622
627
|
async healthCheck() {
|
|
623
|
-
var _a;
|
|
624
628
|
try {
|
|
625
629
|
await this.initialize();
|
|
626
|
-
const redisStatus =
|
|
630
|
+
const redisStatus = this.redis?.status || 'unknown';
|
|
627
631
|
const isReady = this.isReady();
|
|
628
632
|
return {
|
|
629
633
|
status: isReady ? 'healthy' : 'unhealthy',
|
|
@@ -646,15 +650,13 @@ class RedLocker {
|
|
|
646
650
|
}
|
|
647
651
|
}
|
|
648
652
|
}
|
|
649
|
-
RedLocker.instance = null;
|
|
650
|
-
RedLocker.instanceLock = Symbol('RedLocker.instanceLock');
|
|
651
653
|
|
|
652
654
|
/*
|
|
653
655
|
* @Description:
|
|
654
656
|
* @Usage:
|
|
655
657
|
* @Author: richen
|
|
656
658
|
* @Date: 2024-01-16 19:53:14
|
|
657
|
-
* @LastEditTime: 2024-
|
|
659
|
+
* @LastEditTime: 2024-11-07 16:47:58
|
|
658
660
|
* @License: BSD (3-Clause)
|
|
659
661
|
* @Copyright (c): <richenlin(at)gmail.com>
|
|
660
662
|
*/
|
|
@@ -715,9 +717,9 @@ async function initRedLock(options, app) {
|
|
|
715
717
|
async function injectRedLock(_options, _app) {
|
|
716
718
|
try {
|
|
717
719
|
DefaultLogger.Debug('Starting batch RedLock injection...');
|
|
718
|
-
const componentList = IOCContainer.listClass(
|
|
720
|
+
const componentList = IOCContainer.listClass(COMPONENT_REDLOCK);
|
|
719
721
|
for (const component of componentList) {
|
|
720
|
-
const classMetadata = IOCContainer.getClassMetadata(
|
|
722
|
+
const classMetadata = IOCContainer.getClassMetadata(COMPONENT_REDLOCK, DecoratorType.REDLOCK, component.target);
|
|
721
723
|
if (!classMetadata) {
|
|
722
724
|
continue;
|
|
723
725
|
}
|
|
@@ -730,7 +732,7 @@ async function injectRedLock(_options, _app) {
|
|
|
730
732
|
}
|
|
731
733
|
// 查找所有RedLock方法的元数据
|
|
732
734
|
for (const [key, value] of Object.entries(metadata)) {
|
|
733
|
-
if (key.startsWith('REDLOCK
|
|
735
|
+
if (key.startsWith('REDLOCK')) {
|
|
734
736
|
const redlockData = value;
|
|
735
737
|
const targetMethod = instance[redlockData.method];
|
|
736
738
|
if (!Helper.isFunction(targetMethod)) {
|
|
@@ -792,10 +794,10 @@ function redLockerDescriptor(descriptor, name, method, methodOptions) {
|
|
|
792
794
|
}
|
|
793
795
|
// 设置默认选项,合并方法级别的选项
|
|
794
796
|
const lockOptions = {
|
|
795
|
-
lockTimeOut:
|
|
796
|
-
clockDriftFactor:
|
|
797
|
-
maxRetries:
|
|
798
|
-
retryDelayMs:
|
|
797
|
+
lockTimeOut: methodOptions?.lockTimeOut,
|
|
798
|
+
clockDriftFactor: methodOptions?.clockDriftFactor,
|
|
799
|
+
maxRetries: methodOptions?.maxRetries,
|
|
800
|
+
retryDelayMs: methodOptions?.retryDelayMs
|
|
799
801
|
};
|
|
800
802
|
/**
|
|
801
803
|
* Enhanced function wrapper with proper lock renewal and safety
|
|
@@ -901,9 +903,9 @@ function redLockerDescriptor(descriptor, name, method, methodOptions) {
|
|
|
901
903
|
async function injectSchedule(_options, _app) {
|
|
902
904
|
try {
|
|
903
905
|
DefaultLogger.Debug('Starting batch schedule injection...');
|
|
904
|
-
const componentList = IOCContainer.listClass(
|
|
906
|
+
const componentList = IOCContainer.listClass(COMPONENT_SCHEDULED);
|
|
905
907
|
for (const component of componentList) {
|
|
906
|
-
const classMetadata = IOCContainer.getClassMetadata(
|
|
908
|
+
const classMetadata = IOCContainer.getClassMetadata(COMPONENT_SCHEDULED, DecoratorType.SCHEDULED, component.target);
|
|
907
909
|
if (!classMetadata) {
|
|
908
910
|
continue;
|
|
909
911
|
}
|
|
@@ -916,7 +918,7 @@ async function injectSchedule(_options, _app) {
|
|
|
916
918
|
}
|
|
917
919
|
// 查找所有调度方法的元数据
|
|
918
920
|
for (const [key, value] of Object.entries(metadata)) {
|
|
919
|
-
if (key.startsWith('SCHEDULED
|
|
921
|
+
if (key.startsWith('SCHEDULED')) {
|
|
920
922
|
const scheduleData = value;
|
|
921
923
|
const targetMethod = instance[scheduleData.method];
|
|
922
924
|
if (!Helper.isFunction(targetMethod)) {
|
package/dist/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koatty_schedule",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "Schedule for koatty.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "npm run build:js && npm run build:dts && npm run build:doc && npm run build:cp",
|
|
7
|
-
"build:cp": "node scripts/postBuild && copyfiles package.json LICENSE README.md dist/",
|
|
8
|
-
"build:js": "
|
|
9
|
-
"build:doc": "
|
|
10
|
-
"build:dts": "
|
|
7
|
+
"build:cp": "node scripts/postBuild && npx copyfiles package.json LICENSE README.md dist/",
|
|
8
|
+
"build:js": "npx rollup --bundleConfigAsCjs -c .rollup.config.js",
|
|
9
|
+
"build:doc": "npx api-documenter markdown --input temp --output docs/api",
|
|
10
|
+
"build:dts": "npx tsc && npx api-extractor run --local --verbose",
|
|
11
11
|
"eslint": "eslint --ext .ts,.js ./",
|
|
12
12
|
"lock": "npm i --package-lock-only",
|
|
13
13
|
"prepublishOnly": "npm test && npm run build && git push --follow-tags origin master",
|
|
@@ -15,12 +15,16 @@
|
|
|
15
15
|
"release:minor": "npm run release -- --release-as minor",
|
|
16
16
|
"release:major": "npm run release -- --release-as major",
|
|
17
17
|
"release": "standard-version",
|
|
18
|
-
"
|
|
18
|
+
"release:pre": "npm run release -- --prerelease",
|
|
19
|
+
"test": "npm run eslint && jest --passWithNoTests",
|
|
20
|
+
"test:cov": "jest --collectCoverage --detectOpenHandles",
|
|
21
|
+
"version": "conventional-changelog -p angular -i CHANGELOG.md -s"
|
|
19
22
|
},
|
|
20
23
|
"main": "./dist/index.js",
|
|
21
24
|
"exports": {
|
|
22
25
|
"require": "./dist/index.js",
|
|
23
|
-
"import": "./dist/index.mjs"
|
|
26
|
+
"import": "./dist/index.mjs",
|
|
27
|
+
"types": "./dist/index.d.ts"
|
|
24
28
|
},
|
|
25
29
|
"repository": {
|
|
26
30
|
"type": "git",
|
|
@@ -54,7 +58,9 @@
|
|
|
54
58
|
"@commitlint/config-conventional": "^19.x.x",
|
|
55
59
|
"@microsoft/api-documenter": "^7.x.x",
|
|
56
60
|
"@microsoft/api-extractor": "^7.x.x",
|
|
61
|
+
"@rollup/plugin-commonjs": "^28.0.6",
|
|
57
62
|
"@rollup/plugin-json": "^6.x.x",
|
|
63
|
+
"@rollup/plugin-node-resolve": "^15.x.x",
|
|
58
64
|
"@types/jest": "^29.x.x",
|
|
59
65
|
"@types/koa": "^2.x.x",
|
|
60
66
|
"@types/lodash": "^4.17.17",
|
|
@@ -73,6 +79,7 @@
|
|
|
73
79
|
"jest-html-reporters": "^3.x.x",
|
|
74
80
|
"reflect-metadata": "^0.x.x",
|
|
75
81
|
"rollup": "^4.x.x",
|
|
82
|
+
"rollup-plugin-delete": "^2.x.x",
|
|
76
83
|
"rollup-plugin-typescript2": "^0.x.x",
|
|
77
84
|
"standard-version": "^9.x.x",
|
|
78
85
|
"ts-jest": "^29.x.x",
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koatty_schedule",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "Schedule for koatty.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "npm run build:js && npm run build:dts && npm run build:doc && npm run build:cp",
|
|
7
|
-
"build:cp": "node scripts/postBuild && copyfiles package.json LICENSE README.md dist/",
|
|
8
|
-
"build:js": "
|
|
9
|
-
"build:doc": "
|
|
10
|
-
"build:dts": "
|
|
7
|
+
"build:cp": "node scripts/postBuild && npx copyfiles package.json LICENSE README.md dist/",
|
|
8
|
+
"build:js": "npx rollup --bundleConfigAsCjs -c .rollup.config.js",
|
|
9
|
+
"build:doc": "npx api-documenter markdown --input temp --output docs/api",
|
|
10
|
+
"build:dts": "npx tsc && npx api-extractor run --local --verbose",
|
|
11
11
|
"eslint": "eslint --ext .ts,.js ./",
|
|
12
12
|
"lock": "npm i --package-lock-only",
|
|
13
13
|
"prepublishOnly": "npm test && npm run build && git push --follow-tags origin master",
|
|
@@ -15,12 +15,16 @@
|
|
|
15
15
|
"release:minor": "npm run release -- --release-as minor",
|
|
16
16
|
"release:major": "npm run release -- --release-as major",
|
|
17
17
|
"release": "standard-version",
|
|
18
|
-
"
|
|
18
|
+
"release:pre": "npm run release -- --prerelease",
|
|
19
|
+
"test": "npm run eslint && jest --passWithNoTests",
|
|
20
|
+
"test:cov": "jest --collectCoverage --detectOpenHandles",
|
|
21
|
+
"version": "conventional-changelog -p angular -i CHANGELOG.md -s"
|
|
19
22
|
},
|
|
20
23
|
"main": "./dist/index.js",
|
|
21
24
|
"exports": {
|
|
22
25
|
"require": "./dist/index.js",
|
|
23
|
-
"import": "./dist/index.mjs"
|
|
26
|
+
"import": "./dist/index.mjs",
|
|
27
|
+
"types": "./dist/index.d.ts"
|
|
24
28
|
},
|
|
25
29
|
"repository": {
|
|
26
30
|
"type": "git",
|
|
@@ -54,7 +58,9 @@
|
|
|
54
58
|
"@commitlint/config-conventional": "^19.x.x",
|
|
55
59
|
"@microsoft/api-documenter": "^7.x.x",
|
|
56
60
|
"@microsoft/api-extractor": "^7.x.x",
|
|
61
|
+
"@rollup/plugin-commonjs": "^28.0.6",
|
|
57
62
|
"@rollup/plugin-json": "^6.x.x",
|
|
63
|
+
"@rollup/plugin-node-resolve": "^15.x.x",
|
|
58
64
|
"@types/jest": "^29.x.x",
|
|
59
65
|
"@types/koa": "^2.x.x",
|
|
60
66
|
"@types/lodash": "^4.17.17",
|
|
@@ -73,6 +79,7 @@
|
|
|
73
79
|
"jest-html-reporters": "^3.x.x",
|
|
74
80
|
"reflect-metadata": "^0.x.x",
|
|
75
81
|
"rollup": "^4.x.x",
|
|
82
|
+
"rollup-plugin-delete": "^2.x.x",
|
|
76
83
|
"rollup-plugin-typescript2": "^0.x.x",
|
|
77
84
|
"standard-version": "^9.x.x",
|
|
78
85
|
"ts-jest": "^29.x.x",
|