@fluojs/cron 1.0.0-beta.1 → 1.0.0-beta.2

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/README.ko.md CHANGED
@@ -141,7 +141,7 @@ class TaskManager {
141
141
 
142
142
  `CronModule`은 애플리케이션 종료 시 실행 중인 작업을 drain하지만, 이제는 제한된 타임아웃 안에서만 기다립니다. 따라서 하나의 hung task 때문에 프로세스 종료가 영원히 막히지 않습니다.
143
143
 
144
- 기본적으로 shutdown drain은 최대 `10_000ms` 동안 기다립니다. 이 시간이 지나면 스케줄러는 경고 로그를 남기고 hung task가 끝나기를 더 기다리지 않은 채 종료를 계속합니다.
144
+ 기본적으로 shutdown drain은 최대 `10_000ms` 동안 기다립니다. 이 시간이 지나면 스케줄러는 경고 로그를 남기고 hung task가 끝나기를 더 기다리지 않은 채 종료를 계속합니다. 분산 락을 사용하는 경우 아직 실행 중인 작업이 보유한 락은 timeout 시점에 즉시 해제하지 않습니다. 해당 작업이 정상적으로 끝날 때까지 락 소유권을 유지하거나, 프로세스가 종료된 뒤 Redis TTL로 만료되게 두어 원래 작업이 아직 실행 중인데 다른 노드가 같은 작업을 시작하지 않도록 합니다.
145
145
 
146
146
  ```typescript
147
147
  @Module({
package/README.md CHANGED
@@ -141,7 +141,7 @@ class TaskManager {
141
141
 
142
142
  `CronModule` drains active task executions during application shutdown, but it now does so with a bounded timeout so one hung task cannot block process termination forever.
143
143
 
144
- By default the shutdown drain waits up to `10_000ms`. If that timeout expires, the scheduler logs a warning and continues shutdown without waiting for the hung task to settle.
144
+ By default the shutdown drain waits up to `10_000ms`. If that timeout expires, the scheduler logs a warning and continues shutdown without waiting for the hung task to settle. When distributed locking is enabled, locks held by still-running tasks are not eagerly released on timeout; they remain owned by that task until it settles normally, or until Redis expires the lock after the process exits. This prevents another node from starting the same job while the original task is still running.
145
145
 
146
146
  ```typescript
147
147
  @Module({
@@ -1,14 +1,17 @@
1
1
  import type { Container } from '@fluojs/di';
2
2
  import type { ApplicationLogger } from '@fluojs/runtime';
3
3
  import type { CronTaskDescriptor, NormalizedCronModuleOptions } from './types.js';
4
+ /** Minimal Redis command surface required for distributed cron locks. */
4
5
  export interface RedisLockClient {
5
6
  eval(script: string, keysLength: number, ...keysAndArgs: string[]): Promise<unknown>;
6
7
  set(key: string, value: string, mode: 'PX', ttl: number, existence: 'NX'): Promise<'OK' | null | undefined>;
7
8
  }
9
+ /** Tracks renewal state for one acquired distributed cron lock. */
8
10
  export interface LockRenewalMonitor {
9
11
  getPostRunError(): Promise<Error | undefined>;
10
12
  stop(): void;
11
13
  }
14
+ /** Coordinates Redis lock acquisition, renewal, and release for scheduled cron tasks. */
12
15
  export declare class CronDistributedLockManager {
13
16
  private readonly options;
14
17
  private readonly runtimeContainer;
@@ -27,7 +30,7 @@ export declare class CronDistributedLockManager {
27
30
  tryAcquireLock(descriptor: CronTaskDescriptor): Promise<boolean>;
28
31
  startLockRenewalMonitor(descriptor: CronTaskDescriptor): LockRenewalMonitor;
29
32
  releaseLock(descriptor: CronTaskDescriptor): Promise<void>;
30
- releaseOwnedLocks(): Promise<void>;
33
+ releaseOwnedLocks(excludedLockKeys?: ReadonlySet<string>): Promise<void>;
31
34
  private createLockRenewalState;
32
35
  private queueDueLockRenewalAttempts;
33
36
  private runLockRenewalAttempt;
@@ -1 +1 @@
1
- {"version":3,"file":"distributed-lock-manager.d.ts","sourceRoot":"","sources":["../src/distributed-lock-manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAElF,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACrF,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;CAC7G;AAED,MAAM,WAAW,kBAAkB;IACjC,eAAe,IAAI,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC;IAC9C,IAAI,IAAI,IAAI,CAAC;CACd;AAiBD,qBAAa,0BAA0B;IAOnC,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM;IARzB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IACnD,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,mBAAmB,CAAK;IAChC,OAAO,CAAC,mBAAmB,CAAK;gBAGb,OAAO,EAAE,2BAA2B,EACpC,gBAAgB,EAAE,SAAS,EAC3B,MAAM,EAAE,iBAAiB;IAG5C,IAAI,cAAc,IAAI,eAAe,GAAG,SAAS,CAEhD;IAED,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,IAAI,eAAe,IAAI,MAAM,CAE5B;IAED,IAAI,eAAe,IAAI,MAAM,CAE5B;IAEK,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBpC,KAAK,IAAI,IAAI;IAIP,cAAc,CAAC,UAAU,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;IA+BtE,uBAAuB,CAAC,UAAU,EAAE,kBAAkB,GAAG,kBAAkB;IA8BrE,WAAW,CAAC,UAAU,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1D,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAcxC,OAAO,CAAC,sBAAsB;IAY9B,OAAO,CAAC,2BAA2B;YAcrB,qBAAqB;IAqBnC,OAAO,CAAC,kBAAkB;YAYZ,SAAS;YAwCT,cAAc;CAgC7B"}
1
+ {"version":3,"file":"distributed-lock-manager.d.ts","sourceRoot":"","sources":["../src/distributed-lock-manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAElF,yEAAyE;AACzE,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACrF,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;CAC7G;AAED,mEAAmE;AACnE,MAAM,WAAW,kBAAkB;IACjC,eAAe,IAAI,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC;IAC9C,IAAI,IAAI,IAAI,CAAC;CACd;AAiBD,yFAAyF;AACzF,qBAAa,0BAA0B;IAOnC,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM;IARzB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IACnD,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,mBAAmB,CAAK;IAChC,OAAO,CAAC,mBAAmB,CAAK;gBAGb,OAAO,EAAE,2BAA2B,EACpC,gBAAgB,EAAE,SAAS,EAC3B,MAAM,EAAE,iBAAiB;IAG5C,IAAI,cAAc,IAAI,eAAe,GAAG,SAAS,CAEhD;IAED,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,IAAI,eAAe,IAAI,MAAM,CAE5B;IAED,IAAI,eAAe,IAAI,MAAM,CAE5B;IAEK,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBpC,KAAK,IAAI,IAAI;IAIP,cAAc,CAAC,UAAU,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;IA+BtE,uBAAuB,CAAC,UAAU,EAAE,kBAAkB,GAAG,kBAAkB;IA8BrE,WAAW,CAAC,UAAU,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1D,iBAAiB,CAAC,gBAAgB,GAAE,WAAW,CAAC,MAAM,CAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBzF,OAAO,CAAC,sBAAsB;IAY9B,OAAO,CAAC,2BAA2B;YAcrB,qBAAqB;IAqBnC,OAAO,CAAC,kBAAkB;YAYZ,SAAS;YAwCT,cAAc;CAgC7B"}
@@ -1,6 +1,13 @@
1
1
  import { getRedisClientToken } from '@fluojs/redis';
2
+
3
+ /** Minimal Redis command surface required for distributed cron locks. */
4
+
5
+ /** Tracks renewal state for one acquired distributed cron lock. */
6
+
2
7
  const RELEASE_LOCK_SCRIPT = 'if redis.call("GET", KEYS[1]) == ARGV[1] then return redis.call("DEL", KEYS[1]) else return 0 end';
3
8
  const RENEW_LOCK_SCRIPT = 'if redis.call("GET", KEYS[1]) == ARGV[1] then return redis.call("PEXPIRE", KEYS[1], ARGV[2]) else return 0 end';
9
+
10
+ /** Coordinates Redis lock acquisition, renewal, and release for scheduled cron tasks. */
4
11
  export class CronDistributedLockManager {
5
12
  ownedLockKeys = new Set();
6
13
  redisClient;
@@ -85,11 +92,14 @@ export class CronDistributedLockManager {
85
92
  async releaseLock(descriptor) {
86
93
  await this.releaseLockKey(descriptor.lockKey, descriptor.taskName);
87
94
  }
88
- async releaseOwnedLocks() {
95
+ async releaseOwnedLocks(excludedLockKeys = new Set()) {
89
96
  if (!this.redisClient || this.ownedLockKeys.size === 0) {
90
97
  return;
91
98
  }
92
- const lockKeys = Array.from(this.ownedLockKeys);
99
+ const lockKeys = Array.from(this.ownedLockKeys).filter(lockKey => !excludedLockKeys.has(lockKey));
100
+ if (lockKeys.length === 0) {
101
+ return;
102
+ }
93
103
  await Promise.all(lockKeys.map(async lockKey => {
94
104
  await this.releaseLockKey(lockKey, lockKey);
95
105
  }));
package/dist/service.d.ts CHANGED
@@ -15,6 +15,7 @@ export declare class CronLifecycleService implements SchedulingRegistry, OnAppli
15
15
  private readonly logger;
16
16
  private readonly tasks;
17
17
  private readonly activeTasks;
18
+ private readonly runningDistributedLockKeys;
18
19
  private readonly distributedLocks;
19
20
  private readonly taskRunner;
20
21
  private lifecycleState;
@@ -99,6 +100,7 @@ export declare class CronLifecycleService implements SchedulingRegistry, OnAppli
99
100
  private validateDistributedLockConfiguration;
100
101
  private handleStartupFailure;
101
102
  private runShutdownLifecycle;
103
+ private getRunningDistributedLockKeys;
102
104
  private registerDecoratorTasks;
103
105
  private registerTask;
104
106
  private assertTaskNameAvailable;
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG5C,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACrB,MAAM,iBAAiB,CAAC;AAQzB,OAAO,KAAK,EAEV,eAAe,EACf,mBAAmB,EACnB,2BAA2B,EAC3B,kBAAkB,EAClB,sBAAsB,EACtB,wBAAwB,EACxB,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAwCpB;;;;;;GAMG;AACH,qBACa,oBACX,YAAW,kBAAkB,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,eAAe;IAY3F,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAbzB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuC;IAC7D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA4B;IACxD,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAAqB;IAChE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA6B;IAC9D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAiB;IAC5C,OAAO,CAAC,cAAc,CAAmF;IACzG,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,eAAe,CAA4B;gBAGhC,OAAO,EAAE,2BAA2B,EACpC,gBAAgB,EAAE,SAAS,EAC3B,eAAe,EAAE,SAAS,cAAc,EAAE,EAC1C,MAAM,EAAE,iBAAiB;IAM5C;;;;;;;OAOG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,sBAAsB,EAAE,OAAO,GAAE,eAAoB,GAAG,IAAI;IAuBhH;;;;;;;OAOG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,sBAAsB,EAAE,OAAO,GAAE,mBAAwB,GAAG,IAAI;IAsBhH;;;;;;;OAOG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,sBAAsB,EAAE,OAAO,GAAE,kBAAuB,GAAG,IAAI;IAsB9G;;;;;OAKG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAY7B;;;;;OAKG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAoB7B;;;;;OAKG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAgB9B;;;;;OAKG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,wBAAwB,GAAG,SAAS;IAMvD;;;;OAIG;IACH,MAAM,IAAI,wBAAwB,EAAE;IAIpC;;;;;OAKG;IACH,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAuBtD,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBvC,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAItC,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAItC,4BAA4B;IA6B5B,OAAO,CAAC,0BAA0B;YAkBpB,QAAQ;YAWR,cAAc;IAQ5B,OAAO,CAAC,oCAAoC;IAQ5C,OAAO,CAAC,oBAAoB;YAOd,oBAAoB;IAmBlC,OAAO,CAAC,6BAA6B;IAIrC,OAAO,CAAC,sBAAsB;IAQ9B,OAAO,CAAC,YAAY;IAsBpB,OAAO,CAAC,uBAAuB;IAM/B,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,YAAY;IA4DpB,OAAO,CAAC,mBAAmB;IAW3B,OAAO,CAAC,cAAc;YAcR,cAAc;YAmBd,WAAW;IASzB,OAAO,CAAC,6BAA6B;YAIvB,sBAAsB;YAsBtB,kBAAkB;YA2BlB,gBAAgB;YAMhB,WAAW;IAYzB,OAAO,CAAC,qBAAqB;CAK9B"}
package/dist/service.js CHANGED
@@ -52,6 +52,7 @@ class CronLifecycleService {
52
52
  }
53
53
  tasks = new Map();
54
54
  activeTasks = new Set();
55
+ runningDistributedLockKeys = new Set();
55
56
  distributedLocks;
56
57
  taskRunner;
57
58
  lifecycleState = 'created';
@@ -340,9 +341,12 @@ class CronLifecycleService {
340
341
  if (shutdownTimedOut) {
341
342
  this.logger.warn(`Cron shutdown timed out after ${String(this.options.shutdown.timeoutMs)}ms with ${String(this.activeTasks.size)} active task(s) still pending.`, 'CronLifecycleService');
342
343
  }
343
- await this.distributedLocks.releaseOwnedLocks();
344
+ await this.distributedLocks.releaseOwnedLocks(shutdownTimedOut ? this.getRunningDistributedLockKeys() : new Set());
344
345
  this.lifecycleState = 'stopped';
345
346
  }
347
+ getRunningDistributedLockKeys() {
348
+ return new Set(this.runningDistributedLockKeys);
349
+ }
346
350
  registerDecoratorTasks() {
347
351
  const descriptors = discoverCronTaskDescriptors(this.compiledModules, this.options, this.logger);
348
352
  for (const descriptor of descriptors) {
@@ -474,6 +478,7 @@ class CronLifecycleService {
474
478
  return;
475
479
  }
476
480
  const lockRenewalMonitor = this.distributedLocks.startLockRenewalMonitor(descriptor);
481
+ this.runningDistributedLockKeys.add(descriptor.lockKey);
477
482
  try {
478
483
  await this.executeTask(descriptor, taskState, async () => {
479
484
  lockRenewalMonitor.stop();
@@ -482,6 +487,7 @@ class CronLifecycleService {
482
487
  } finally {
483
488
  lockRenewalMonitor.stop();
484
489
  await this.distributedLocks.releaseLock(descriptor);
490
+ this.runningDistributedLockKeys.delete(descriptor.lockKey);
485
491
  }
486
492
  }
487
493
  async waitForActiveTasks() {
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "timeout",
10
10
  "distributed-lock"
11
11
  ],
12
- "version": "1.0.0-beta.1",
12
+ "version": "1.0.0-beta.2",
13
13
  "private": false,
14
14
  "license": "MIT",
15
15
  "repository": {
@@ -38,9 +38,9 @@
38
38
  "dependencies": {
39
39
  "croner": "^8.1.2",
40
40
  "@fluojs/core": "^1.0.0-beta.1",
41
- "@fluojs/redis": "^1.0.0-beta.1",
42
- "@fluojs/di": "^1.0.0-beta.1",
43
- "@fluojs/runtime": "^1.0.0-beta.1"
41
+ "@fluojs/di": "^1.0.0-beta.2",
42
+ "@fluojs/redis": "^1.0.0-beta.2",
43
+ "@fluojs/runtime": "^1.0.0-beta.2"
44
44
  },
45
45
  "devDependencies": {
46
46
  "vitest": "^3.2.4"