koatty_schedule 3.3.2 → 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 +2 -0
- package/README.md +304 -5
- package/dist/README.md +304 -5
- package/dist/index.d.ts +323 -14
- package/dist/index.js +422 -67
- package/dist/index.mjs +420 -68
- package/dist/package.json +4 -4
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
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
|
+
|
|
5
7
|
### [3.3.2](https://github.com/thinkkoa/koatty_schedule/compare/v3.3.1...v3.3.2) (2025-06-22)
|
|
6
8
|
|
|
7
9
|
### [3.3.1](https://github.com/thinkkoa/koatty_schedule/compare/v3.3.0...v3.3.1) (2025-06-22)
|
package/README.md
CHANGED
|
@@ -11,12 +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
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
|
|
20
23
|
|
|
21
24
|
## Installation
|
|
22
25
|
|
|
@@ -53,6 +56,8 @@ export class Scheduled implements IPlugin {
|
|
|
53
56
|
Update `src/config/plugin.ts`:
|
|
54
57
|
|
|
55
58
|
```typescript
|
|
59
|
+
import { RedisMode } from "koatty_schedule";
|
|
60
|
+
|
|
56
61
|
export default {
|
|
57
62
|
list: ["Scheduled"], // Plugin loading order
|
|
58
63
|
config: {
|
|
@@ -62,6 +67,7 @@ export default {
|
|
|
62
67
|
maxRetries: 3,
|
|
63
68
|
retryDelayMs: 200,
|
|
64
69
|
redisConfig: {
|
|
70
|
+
mode: RedisMode.STANDALONE, // or SENTINEL, CLUSTER
|
|
65
71
|
host: "127.0.0.1",
|
|
66
72
|
port: 6379,
|
|
67
73
|
db: 0,
|
|
@@ -119,11 +125,96 @@ export class CriticalTaskService {
|
|
|
119
125
|
|
|
120
126
|
## Advanced Configuration
|
|
121
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
|
+
|
|
122
211
|
### Global Plugin Configuration
|
|
123
212
|
|
|
124
213
|
Configure global settings in `src/config/plugin.ts`:
|
|
125
214
|
|
|
126
215
|
```typescript
|
|
216
|
+
import { RedisMode } from "koatty_schedule";
|
|
217
|
+
|
|
127
218
|
export default {
|
|
128
219
|
list: ["Scheduled"],
|
|
129
220
|
config: {
|
|
@@ -139,6 +230,7 @@ export default {
|
|
|
139
230
|
|
|
140
231
|
// Redis configuration for distributed locks
|
|
141
232
|
redisConfig: {
|
|
233
|
+
mode: RedisMode.STANDALONE,
|
|
142
234
|
host: "redis.example.com",
|
|
143
235
|
port: 6379,
|
|
144
236
|
password: "your-password",
|
|
@@ -324,6 +416,10 @@ export class LongRunningTaskService {
|
|
|
324
416
|
|
|
325
417
|
## Cron Expression Examples
|
|
326
418
|
|
|
419
|
+
koatty_schedule supports both 5-part and 6-part (with seconds) cron expressions with comprehensive validation:
|
|
420
|
+
|
|
421
|
+
### Basic Examples
|
|
422
|
+
|
|
327
423
|
```typescript
|
|
328
424
|
export class CronExamplesService {
|
|
329
425
|
|
|
@@ -347,6 +443,90 @@ export class CronExamplesService {
|
|
|
347
443
|
}
|
|
348
444
|
```
|
|
349
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
|
+
|
|
350
530
|
## Troubleshooting
|
|
351
531
|
|
|
352
532
|
### Common Issues
|
|
@@ -391,32 +571,92 @@ DEBUG=koatty_schedule* npm start
|
|
|
391
571
|
### Decorators
|
|
392
572
|
|
|
393
573
|
#### `@Scheduled(cron: string, timezone?: string)`
|
|
394
|
-
- `cron`: Cron expression (6-part format with
|
|
574
|
+
- `cron`: Cron expression (5 or 6-part format, with comprehensive validation)
|
|
395
575
|
- `timezone`: Optional timezone override (defaults to 'Asia/Beijing')
|
|
396
576
|
- **Processing**: Records metadata in IOC container, CronJob created at `appReady`
|
|
577
|
+
- **Validation**: Full validation of all cron fields with bilingual error messages
|
|
397
578
|
|
|
398
579
|
#### `@RedLock(lockName?: string, options?: RedLockMethodOptions)`
|
|
399
580
|
- `lockName`: Unique lock identifier (auto-generated if not provided)
|
|
400
581
|
- `options`: Method-level lock configuration
|
|
582
|
+
- **Features**: Automatic lock renewal (up to 3 times), memory-leak-free implementation
|
|
401
583
|
|
|
402
584
|
### Configuration Types
|
|
403
585
|
|
|
404
586
|
```typescript
|
|
587
|
+
// Scheduled options with Redis mode support
|
|
405
588
|
interface ScheduledOptions {
|
|
406
589
|
timezone?: string;
|
|
407
590
|
lockTimeOut?: number;
|
|
408
591
|
maxRetries?: number;
|
|
409
592
|
retryDelayMs?: number;
|
|
410
593
|
clockDriftFactor?: number;
|
|
411
|
-
redisConfig?: RedisConfig;
|
|
594
|
+
redisConfig?: RedisConfig; // Supports Standalone, Sentinel, Cluster
|
|
412
595
|
}
|
|
413
596
|
|
|
597
|
+
// RedLock method-level options
|
|
414
598
|
interface RedLockMethodOptions {
|
|
415
599
|
lockTimeOut?: number;
|
|
416
600
|
maxRetries?: number;
|
|
417
601
|
retryDelayMs?: number;
|
|
418
602
|
clockDriftFactor?: number;
|
|
419
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
|
|
420
660
|
```
|
|
421
661
|
|
|
422
662
|
## Version Compatibility
|
|
@@ -424,6 +664,59 @@ interface RedLockMethodOptions {
|
|
|
424
664
|
- **Koatty**: >= 2.0.0
|
|
425
665
|
- **Node.js**: >= 14.0.0
|
|
426
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
|
|
427
720
|
|
|
428
721
|
## License
|
|
429
722
|
|
|
@@ -437,4 +730,10 @@ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) f
|
|
|
437
730
|
|
|
438
731
|
- 📚 [Documentation](https://koatty.js.org/)
|
|
439
732
|
- 🐛 [Issues](https://github.com/koattyjs/koatty_schedule/issues)
|
|
440
|
-
- 💬 [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**
|