koatty_schedule 3.3.1 → 3.3.3
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/CHANGELOG.md +4 -0
- package/README.md +307 -6
- package/dist/README.md +307 -6
- package/dist/index.d.ts +323 -14
- package/dist/index.js +596 -274
- package/dist/index.mjs +594 -275
- package/dist/package.json +4 -4
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
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.3](https://github.com/thinkkoa/koatty_schedule/compare/v3.3.2...v3.3.3) (2025-10-31)
|
|
6
|
+
|
|
7
|
+
### [3.3.2](https://github.com/thinkkoa/koatty_schedule/compare/v3.3.1...v3.3.2) (2025-06-22)
|
|
8
|
+
|
|
5
9
|
### [3.3.1](https://github.com/thinkkoa/koatty_schedule/compare/v3.3.0...v3.3.1) (2025-06-22)
|
|
6
10
|
|
|
7
11
|
|
package/README.md
CHANGED
|
@@ -11,11 +11,15 @@ Powerful scheduled tasks and distributed locking solution for Koatty framework.
|
|
|
11
11
|
- 🕒 **Flexible Scheduling**: Support for cron expressions with timezone configuration
|
|
12
12
|
- 🔐 **Distributed Locking**: RedLock-based distributed locks with auto-extension
|
|
13
13
|
- 🏗️ **Plugin Architecture**: Native Koatty plugin integration
|
|
14
|
-
- ⚡ **Performance Optimized**: Singleton pattern, caching, and
|
|
15
|
-
- 🛡️ **Enhanced Safety**: Lock renewal logic with timeout protection
|
|
14
|
+
- ⚡ **Performance Optimized**: Singleton pattern, caching, and memory-leak-free design
|
|
15
|
+
- 🛡️ **Enhanced Safety**: Lock renewal logic with timeout protection and automatic cleanup
|
|
16
16
|
- 🌍 **Timezone Smart**: Three-tier priority system for timezone configuration
|
|
17
17
|
- 📊 **Health Monitoring**: Built-in health checks and detailed status reporting
|
|
18
18
|
- 🔧 **Easy Configuration**: Method-level and global configuration options
|
|
19
|
+
- 🚀 **Smart Initialization**: Unified initialization timing for optimal dependency resolution
|
|
20
|
+
- 🎯 **Advanced Validation**: Comprehensive cron expression validation with bilingual error messages
|
|
21
|
+
- 🔌 **Redis Multi-Mode**: Support for Standalone, Sentinel, and Cluster Redis deployments
|
|
22
|
+
- 🧩 **Extensible Architecture**: Abstract interfaces for easy customization and extension
|
|
19
23
|
|
|
20
24
|
## Installation
|
|
21
25
|
|
|
@@ -52,6 +56,8 @@ export class Scheduled implements IPlugin {
|
|
|
52
56
|
Update `src/config/plugin.ts`:
|
|
53
57
|
|
|
54
58
|
```typescript
|
|
59
|
+
import { RedisMode } from "koatty_schedule";
|
|
60
|
+
|
|
55
61
|
export default {
|
|
56
62
|
list: ["Scheduled"], // Plugin loading order
|
|
57
63
|
config: {
|
|
@@ -61,6 +67,7 @@ export default {
|
|
|
61
67
|
maxRetries: 3,
|
|
62
68
|
retryDelayMs: 200,
|
|
63
69
|
redisConfig: {
|
|
70
|
+
mode: RedisMode.STANDALONE, // or SENTINEL, CLUSTER
|
|
64
71
|
host: "127.0.0.1",
|
|
65
72
|
port: 6379,
|
|
66
73
|
db: 0,
|
|
@@ -118,11 +125,96 @@ export class CriticalTaskService {
|
|
|
118
125
|
|
|
119
126
|
## Advanced Configuration
|
|
120
127
|
|
|
128
|
+
### Redis Deployment Modes
|
|
129
|
+
|
|
130
|
+
koatty_schedule supports three Redis deployment modes:
|
|
131
|
+
|
|
132
|
+
#### Standalone Mode (Default)
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { RedisMode } from "koatty_schedule";
|
|
136
|
+
|
|
137
|
+
export default {
|
|
138
|
+
list: ["Scheduled"],
|
|
139
|
+
config: {
|
|
140
|
+
Scheduled: {
|
|
141
|
+
redisConfig: {
|
|
142
|
+
mode: RedisMode.STANDALONE, // or omit for default
|
|
143
|
+
host: "127.0.0.1",
|
|
144
|
+
port: 6379,
|
|
145
|
+
password: "your-password",
|
|
146
|
+
db: 0,
|
|
147
|
+
keyPrefix: "koatty:schedule:"
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
#### Sentinel Mode (High Availability)
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
import { RedisMode } from "koatty_schedule";
|
|
158
|
+
|
|
159
|
+
export default {
|
|
160
|
+
list: ["Scheduled"],
|
|
161
|
+
config: {
|
|
162
|
+
Scheduled: {
|
|
163
|
+
redisConfig: {
|
|
164
|
+
mode: RedisMode.SENTINEL,
|
|
165
|
+
sentinels: [
|
|
166
|
+
{ host: "192.168.1.10", port: 26379 },
|
|
167
|
+
{ host: "192.168.1.11", port: 26379 },
|
|
168
|
+
{ host: "192.168.1.12", port: 26379 }
|
|
169
|
+
],
|
|
170
|
+
name: "mymaster", // Sentinel master name
|
|
171
|
+
password: "your-password",
|
|
172
|
+
sentinelPassword: "sentinel-password", // Optional
|
|
173
|
+
db: 0,
|
|
174
|
+
keyPrefix: "koatty:schedule:"
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
#### Cluster Mode (Horizontal Scaling)
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
import { RedisMode } from "koatty_schedule";
|
|
185
|
+
|
|
186
|
+
export default {
|
|
187
|
+
list: ["Scheduled"],
|
|
188
|
+
config: {
|
|
189
|
+
Scheduled: {
|
|
190
|
+
redisConfig: {
|
|
191
|
+
mode: RedisMode.CLUSTER,
|
|
192
|
+
nodes: [
|
|
193
|
+
{ host: "192.168.1.10", port: 7000 },
|
|
194
|
+
{ host: "192.168.1.11", port: 7001 },
|
|
195
|
+
{ host: "192.168.1.12", port: 7002 },
|
|
196
|
+
{ host: "192.168.1.13", port: 7003 },
|
|
197
|
+
{ host: "192.168.1.14", port: 7004 },
|
|
198
|
+
{ host: "192.168.1.15", port: 7005 }
|
|
199
|
+
],
|
|
200
|
+
redisOptions: {
|
|
201
|
+
password: "your-password",
|
|
202
|
+
db: 0
|
|
203
|
+
},
|
|
204
|
+
keyPrefix: "koatty:schedule:"
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
```
|
|
210
|
+
|
|
121
211
|
### Global Plugin Configuration
|
|
122
212
|
|
|
123
213
|
Configure global settings in `src/config/plugin.ts`:
|
|
124
214
|
|
|
125
215
|
```typescript
|
|
216
|
+
import { RedisMode } from "koatty_schedule";
|
|
217
|
+
|
|
126
218
|
export default {
|
|
127
219
|
list: ["Scheduled"],
|
|
128
220
|
config: {
|
|
@@ -138,6 +230,7 @@ export default {
|
|
|
138
230
|
|
|
139
231
|
// Redis configuration for distributed locks
|
|
140
232
|
redisConfig: {
|
|
233
|
+
mode: RedisMode.STANDALONE,
|
|
141
234
|
host: "redis.example.com",
|
|
142
235
|
port: 6379,
|
|
143
236
|
password: "your-password",
|
|
@@ -323,6 +416,10 @@ export class LongRunningTaskService {
|
|
|
323
416
|
|
|
324
417
|
## Cron Expression Examples
|
|
325
418
|
|
|
419
|
+
koatty_schedule supports both 5-part and 6-part (with seconds) cron expressions with comprehensive validation:
|
|
420
|
+
|
|
421
|
+
### Basic Examples
|
|
422
|
+
|
|
326
423
|
```typescript
|
|
327
424
|
export class CronExamplesService {
|
|
328
425
|
|
|
@@ -346,6 +443,90 @@ export class CronExamplesService {
|
|
|
346
443
|
}
|
|
347
444
|
```
|
|
348
445
|
|
|
446
|
+
### Advanced Examples (NEW in v3.4.0)
|
|
447
|
+
|
|
448
|
+
```typescript
|
|
449
|
+
export class AdvancedCronService {
|
|
450
|
+
|
|
451
|
+
// Step values - Every 2 hours during business hours
|
|
452
|
+
@Scheduled('0 0 9-17/2 * * 1-5')
|
|
453
|
+
async businessHoursTask() { }
|
|
454
|
+
|
|
455
|
+
// List values - Run at 9 AM, 12 PM, and 6 PM
|
|
456
|
+
@Scheduled('0 0 9,12,18 * * *')
|
|
457
|
+
async specificHoursTask() { }
|
|
458
|
+
|
|
459
|
+
// Month names - Run on first day of Q1 months
|
|
460
|
+
@Scheduled('0 0 0 1 JAN,FEB,MAR *')
|
|
461
|
+
async quarterlyTask() { }
|
|
462
|
+
|
|
463
|
+
// Weekday names - Weekend morning task
|
|
464
|
+
@Scheduled('0 0 10 * * SAT,SUN')
|
|
465
|
+
async weekendTask() { }
|
|
466
|
+
|
|
467
|
+
// Complex expression - Every 15 minutes during working hours on weekdays
|
|
468
|
+
@Scheduled('0 */15 9-17 * * MON-FRI')
|
|
469
|
+
async frequentBusinessTask() { }
|
|
470
|
+
|
|
471
|
+
// Range with step - Every 3 days
|
|
472
|
+
@Scheduled('0 0 0 */3 * *')
|
|
473
|
+
async everyThreeDaysTask() { }
|
|
474
|
+
}
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### Cron Expression Format
|
|
478
|
+
|
|
479
|
+
**6-part format (with seconds):**
|
|
480
|
+
```
|
|
481
|
+
┌────────────── second (0-59)
|
|
482
|
+
│ ┌──────────── minute (0-59)
|
|
483
|
+
│ │ ┌────────── hour (0-23)
|
|
484
|
+
│ │ │ ┌──────── day of month (1-31)
|
|
485
|
+
│ │ │ │ ┌────── month (1-12 or JAN-DEC)
|
|
486
|
+
│ │ │ │ │ ┌──── day of week (0-7 or SUN-SAT, 0 and 7 are Sunday)
|
|
487
|
+
│ │ │ │ │ │
|
|
488
|
+
* * * * * *
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
**5-part format (without seconds):**
|
|
492
|
+
```
|
|
493
|
+
┌──────────── minute (0-59)
|
|
494
|
+
│ ┌────────── hour (0-23)
|
|
495
|
+
│ │ ┌──────── day of month (1-31)
|
|
496
|
+
│ │ │ ┌────── month (1-12 or JAN-DEC)
|
|
497
|
+
│ │ │ │ ┌──── day of week (0-7 or SUN-SAT)
|
|
498
|
+
│ │ │ │ │
|
|
499
|
+
* * * * *
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
### Special Characters
|
|
503
|
+
|
|
504
|
+
- `*` - Any value
|
|
505
|
+
- `,` - Value list separator (e.g., `1,3,5`)
|
|
506
|
+
- `-` - Range of values (e.g., `1-5`)
|
|
507
|
+
- `/` - Step values (e.g., `*/15` or `0-30/5`)
|
|
508
|
+
|
|
509
|
+
### Validation Features (NEW)
|
|
510
|
+
|
|
511
|
+
The enhanced validator will catch common errors:
|
|
512
|
+
|
|
513
|
+
```typescript
|
|
514
|
+
// ❌ Invalid - seconds out of range
|
|
515
|
+
@Scheduled('60 0 0 * * *') // Error: 秒字段的值无效: 60,必须在 0-59 之间
|
|
516
|
+
|
|
517
|
+
// ❌ Invalid - hours out of range
|
|
518
|
+
@Scheduled('0 0 25 * * *') // Error: 小时字段的值无效: 25,必须在 0-23 之间
|
|
519
|
+
|
|
520
|
+
// ❌ Invalid - invalid step value
|
|
521
|
+
@Scheduled('0 */0 * * * *') // Error: 分钟字段的步长值无效: 0
|
|
522
|
+
|
|
523
|
+
// ❌ Invalid - range start > end
|
|
524
|
+
@Scheduled('0 0 17-9 * * *') // Error: 小时字段的范围无效: 17-9
|
|
525
|
+
|
|
526
|
+
// ✅ Valid - all checks passed
|
|
527
|
+
@Scheduled('0 */15 9-17 * * 1-5') // Every 15 minutes, 9-5, weekdays
|
|
528
|
+
```
|
|
529
|
+
|
|
349
530
|
## Troubleshooting
|
|
350
531
|
|
|
351
532
|
### Common Issues
|
|
@@ -390,31 +571,92 @@ DEBUG=koatty_schedule* npm start
|
|
|
390
571
|
### Decorators
|
|
391
572
|
|
|
392
573
|
#### `@Scheduled(cron: string, timezone?: string)`
|
|
393
|
-
- `cron`: Cron expression (6-part format with
|
|
394
|
-
- `timezone`: Optional timezone override
|
|
574
|
+
- `cron`: Cron expression (5 or 6-part format, with comprehensive validation)
|
|
575
|
+
- `timezone`: Optional timezone override (defaults to 'Asia/Beijing')
|
|
576
|
+
- **Processing**: Records metadata in IOC container, CronJob created at `appReady`
|
|
577
|
+
- **Validation**: Full validation of all cron fields with bilingual error messages
|
|
395
578
|
|
|
396
579
|
#### `@RedLock(lockName?: string, options?: RedLockMethodOptions)`
|
|
397
580
|
- `lockName`: Unique lock identifier (auto-generated if not provided)
|
|
398
581
|
- `options`: Method-level lock configuration
|
|
582
|
+
- **Features**: Automatic lock renewal (up to 3 times), memory-leak-free implementation
|
|
399
583
|
|
|
400
584
|
### Configuration Types
|
|
401
585
|
|
|
402
586
|
```typescript
|
|
587
|
+
// Scheduled options with Redis mode support
|
|
403
588
|
interface ScheduledOptions {
|
|
404
589
|
timezone?: string;
|
|
405
590
|
lockTimeOut?: number;
|
|
406
591
|
maxRetries?: number;
|
|
407
592
|
retryDelayMs?: number;
|
|
408
593
|
clockDriftFactor?: number;
|
|
409
|
-
redisConfig?: RedisConfig;
|
|
594
|
+
redisConfig?: RedisConfig; // Supports Standalone, Sentinel, Cluster
|
|
410
595
|
}
|
|
411
596
|
|
|
597
|
+
// RedLock method-level options
|
|
412
598
|
interface RedLockMethodOptions {
|
|
413
599
|
lockTimeOut?: number;
|
|
414
600
|
maxRetries?: number;
|
|
415
601
|
retryDelayMs?: number;
|
|
416
602
|
clockDriftFactor?: number;
|
|
417
603
|
}
|
|
604
|
+
|
|
605
|
+
// Redis configuration (NEW in v3.4.0)
|
|
606
|
+
enum RedisMode {
|
|
607
|
+
STANDALONE = 'standalone',
|
|
608
|
+
SENTINEL = 'sentinel',
|
|
609
|
+
CLUSTER = 'cluster'
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
interface RedisStandaloneConfig {
|
|
613
|
+
mode?: RedisMode.STANDALONE;
|
|
614
|
+
host: string;
|
|
615
|
+
port: number;
|
|
616
|
+
password?: string;
|
|
617
|
+
db?: number;
|
|
618
|
+
keyPrefix?: string;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
interface RedisSentinelConfig {
|
|
622
|
+
mode: RedisMode.SENTINEL;
|
|
623
|
+
sentinels: Array<{ host: string; port: number }>;
|
|
624
|
+
name: string; // Master name
|
|
625
|
+
password?: string;
|
|
626
|
+
sentinelPassword?: string;
|
|
627
|
+
db?: number;
|
|
628
|
+
keyPrefix?: string;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
interface RedisClusterConfig {
|
|
632
|
+
mode: RedisMode.CLUSTER;
|
|
633
|
+
nodes: Array<{ host: string; port: number }>;
|
|
634
|
+
redisOptions?: {
|
|
635
|
+
password?: string;
|
|
636
|
+
db?: number;
|
|
637
|
+
};
|
|
638
|
+
keyPrefix?: string;
|
|
639
|
+
}
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
### Exported Interfaces (NEW in v3.4.0)
|
|
643
|
+
|
|
644
|
+
For advanced customization and extension:
|
|
645
|
+
|
|
646
|
+
```typescript
|
|
647
|
+
import {
|
|
648
|
+
IDistributedLock, // Abstract distributed lock interface
|
|
649
|
+
IRedisClient, // Abstract Redis client interface
|
|
650
|
+
RedisFactory, // Redis client factory
|
|
651
|
+
RedisClientAdapter, // Redis client adapter
|
|
652
|
+
RedLocker // RedLock implementation
|
|
653
|
+
} from "koatty_schedule";
|
|
654
|
+
|
|
655
|
+
// Example: Custom health check
|
|
656
|
+
const redLocker = RedLocker.getInstance();
|
|
657
|
+
const health = await redLocker.healthCheck();
|
|
658
|
+
console.log(health.status); // 'healthy' | 'unhealthy'
|
|
659
|
+
console.log(health.details); // Detailed status information
|
|
418
660
|
```
|
|
419
661
|
|
|
420
662
|
## Version Compatibility
|
|
@@ -422,6 +664,59 @@ interface RedLockMethodOptions {
|
|
|
422
664
|
- **Koatty**: >= 2.0.0
|
|
423
665
|
- **Node.js**: >= 14.0.0
|
|
424
666
|
- **Redis**: >= 3.0.0
|
|
667
|
+
- **Redis Sentinel**: >= 3.0.0 (for high availability)
|
|
668
|
+
- **Redis Cluster**: >= 3.0.0 (for horizontal scaling)
|
|
669
|
+
|
|
670
|
+
## What's New in v3.4.0 🎉
|
|
671
|
+
|
|
672
|
+
### 🐛 Bug Fixes
|
|
673
|
+
|
|
674
|
+
- **Fixed memory leak** in `timeoutPromise` - timers are now properly cleaned up
|
|
675
|
+
- **Improved initialization cleanup** - prevents state inconsistency on retry
|
|
676
|
+
|
|
677
|
+
### ✨ New Features
|
|
678
|
+
|
|
679
|
+
- **Redis Multi-Mode Support**: Standalone, Sentinel, and Cluster modes
|
|
680
|
+
- **Enhanced Cron Validation**: Complete validation of all fields with bilingual error messages
|
|
681
|
+
- **Abstract Interfaces**: `IDistributedLock` and `IRedisClient` for extensibility
|
|
682
|
+
- **Redis Factory**: `RedisFactory` for flexible Redis client creation
|
|
683
|
+
|
|
684
|
+
### 🚀 Improvements
|
|
685
|
+
|
|
686
|
+
- Memory-leak-free design for long-running applications
|
|
687
|
+
- Better error messages with Chinese and English support
|
|
688
|
+
- Comprehensive cron expression validation (steps, ranges, lists, month/weekday names)
|
|
689
|
+
- Health check now reports Redis mode information
|
|
690
|
+
|
|
691
|
+
### 📖 Documentation
|
|
692
|
+
|
|
693
|
+
- Added `UPGRADE_GUIDE.md` with migration instructions
|
|
694
|
+
- Added `IMPROVEMENTS_SUMMARY.md` with technical details
|
|
695
|
+
- Enhanced README with Redis multi-mode examples
|
|
696
|
+
|
|
697
|
+
## Migration from v3.3.x
|
|
698
|
+
|
|
699
|
+
Most code works without changes. To use new features:
|
|
700
|
+
|
|
701
|
+
```typescript
|
|
702
|
+
// Optional: Explicitly set Redis mode (defaults to STANDALONE)
|
|
703
|
+
import { RedisMode } from "koatty_schedule";
|
|
704
|
+
|
|
705
|
+
redisConfig: {
|
|
706
|
+
mode: RedisMode.STANDALONE, // or SENTINEL, CLUSTER
|
|
707
|
+
// ... rest of config
|
|
708
|
+
}
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
See [UPGRADE_GUIDE.md](UPGRADE_GUIDE.md) for details.
|
|
712
|
+
|
|
713
|
+
## Performance & Stability
|
|
714
|
+
|
|
715
|
+
- ✅ **Memory Stable**: No leaks in long-running applications
|
|
716
|
+
- ✅ **Production Ready**: Used in production environments
|
|
717
|
+
- ✅ **Well Tested**: Comprehensive test coverage
|
|
718
|
+
- ✅ **High Availability**: Sentinel mode support
|
|
719
|
+
- ✅ **Scalable**: Cluster mode for horizontal scaling
|
|
425
720
|
|
|
426
721
|
## License
|
|
427
722
|
|
|
@@ -435,4 +730,10 @@ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) f
|
|
|
435
730
|
|
|
436
731
|
- 📚 [Documentation](https://koatty.js.org/)
|
|
437
732
|
- 🐛 [Issues](https://github.com/koattyjs/koatty_schedule/issues)
|
|
438
|
-
- 💬 [Discussions](https://github.com/koattyjs/koatty_schedule/discussions)
|
|
733
|
+
- 💬 [Discussions](https://github.com/koattyjs/koatty_schedule/discussions)
|
|
734
|
+
- 📖 [Upgrade Guide](UPGRADE_GUIDE.md)
|
|
735
|
+
- 📝 [Changelog](CHANGELOG.md)
|
|
736
|
+
|
|
737
|
+
---
|
|
738
|
+
|
|
739
|
+
**Maintained with ❤️ by the Koatty Team**
|