koatty_schedule 2.0.1 → 3.0.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/CHANGELOG.md CHANGED
@@ -2,6 +2,34 @@
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.0.0](https://github.com/thinkkoa/koatty_schedule/compare/v2.1.0...v3.0.0) (2025-06-21)
6
+
7
+
8
+ ### Features
9
+
10
+ * enhance distributed locking and scheduling system with global configuration management and improved validation ([cf3924c](https://github.com/thinkkoa/koatty_schedule/commit/cf3924cf6bccf951f070c68e33483ae935828382))
11
+ * improve RedLock singleton management with thread-safe initialization and lock renewal enhancements ([4e381cd](https://github.com/thinkkoa/koatty_schedule/commit/4e381cd8eec6aa366a6db813918f213f07b02921))
12
+ * refactor RedLock configuration and remove deprecated ScheduleConfig ([bb10ac7](https://github.com/thinkkoa/koatty_schedule/commit/bb10ac7dab67d32ca75a43db92c587a662bc1b9f))
13
+
14
+ ## [2.1.0](https://github.com/thinkkoa/koatty_schedule/compare/v2.0.1...v2.1.0) (2025-06-09)
15
+
16
+
17
+ ### Features
18
+
19
+ * add schedule and redlock decorators with config management ([c1b5359](https://github.com/thinkkoa/koatty_schedule/commit/c1b535940df2b8a3403bf024137519246945870e))
20
+ * enhance ConfigManager with singleton pattern, environment config loading ([00db6eb](https://github.com/thinkkoa/koatty_schedule/commit/00db6eb97bdae226aaf433b23c770704b33d05e8))
21
+ * introduce DecoratorType enum, refactor decorator management system, ([e58e718](https://github.com/thinkkoa/koatty_schedule/commit/e58e718975e663820778352bedb6421e6852ba9f))
22
+
23
+
24
+ ### Bug Fixes
25
+
26
+ * simplify error handling in ConfigManager and RedLocker ([7be75fc](https://github.com/thinkkoa/koatty_schedule/commit/7be75fc7f4160094b57ca64905df4c81f77adb51))
27
+
28
+
29
+ ### Refactor
30
+
31
+ * use MethodDecoratorManager ([ff077c7](https://github.com/thinkkoa/koatty_schedule/commit/ff077c7211bb6cf258c6885e1d7dcbdacde90ef1))
32
+
5
33
  ### [2.0.1](https://github.com/thinkkoa/koatty_schedule/compare/v2.0.0...v2.0.1) (2024-01-17)
6
34
 
7
35
  ## [2.0.0](https://github.com/thinkkoa/koatty_schedule/compare/v1.6.0...v2.0.0) (2024-01-17)
package/README.md CHANGED
@@ -1,48 +1,440 @@
1
1
  # koatty_schedule
2
- Schedule for koatty.
3
2
 
4
- Koatty框架的 Scheduled, SchedulerLock, Lock 支持库
3
+ Powerful scheduled tasks and distributed locking solution for Koatty framework.
5
4
 
5
+ [![npm version](https://img.shields.io/npm/v/koatty_schedule.svg)](https://www.npmjs.com/package/koatty_schedule)
6
+ [![Build Status](https://img.shields.io/github/workflow/status/koattyjs/koatty_schedule/CI)](https://github.com/koattyjs/koatty_schedule)
7
+ [![License](https://img.shields.io/npm/l/koatty_schedule.svg)](https://github.com/koattyjs/koatty_schedule/blob/main/LICENSE)
6
8
 
7
- # Usage
9
+ ## Features
8
10
 
9
- db.ts in koatty project:
11
+ - 🕒 **Flexible Scheduling**: Support for cron expressions with timezone configuration
12
+ - 🔐 **Distributed Locking**: RedLock-based distributed locks with auto-extension
13
+ - 🏗️ **Plugin Architecture**: Native Koatty plugin integration
14
+ - ⚡ **Performance Optimized**: Singleton pattern, caching, and batch processing
15
+ - 🛡️ **Enhanced Safety**: Lock renewal logic with timeout protection
16
+ - 🌍 **Timezone Smart**: Three-tier priority system for timezone configuration
17
+ - 📊 **Health Monitoring**: Built-in health checks and detailed status reporting
18
+ - 🔧 **Easy Configuration**: Method-level and global configuration options
10
19
 
11
- ```js
20
+ ## Installation
21
+
22
+ ```bash
23
+ npm install koatty_schedule
24
+ ```
25
+
26
+ ## Quick Start
27
+
28
+ ### 1. Generate Plugin Template
29
+
30
+ Use Koatty CLI to generate the plugin template:
31
+
32
+ ```bash
33
+ kt plugin
34
+ ```
35
+
36
+ ### 2. Create Scheduled Plugin
37
+
38
+ Create `src/plugin/Scheduled.ts`:
39
+
40
+ ```typescript
41
+ import { Plugin, IPlugin, App } from "koatty";
42
+ import { KoattyScheduled } from "koatty_schedule";
43
+
44
+ @Plugin()
45
+ export class Scheduled implements IPlugin {
46
+ run(options: any, app: App) {
47
+ return KoattyScheduled(options, app);
48
+ }
49
+ }
50
+ ```
51
+
52
+ ### 3. Configure Plugin
53
+
54
+ Update `src/config/plugin.ts`:
55
+
56
+ ```typescript
57
+ export default {
58
+ list: ["Scheduled"], // Plugin loading order
59
+ config: {
60
+ Scheduled: {
61
+ timezone: "Asia/Shanghai",
62
+ lockTimeOut: 10000,
63
+ maxRetries: 3,
64
+ retryDelayMs: 200,
65
+ redisConfig: {
66
+ host: "127.0.0.1",
67
+ port: 6379,
68
+ db: 0,
69
+ keyPrefix: "koatty:schedule:"
70
+ }
71
+ }
72
+ }
73
+ };
74
+ ```
75
+
76
+ ## Usage
77
+
78
+ ### Basic Scheduling
79
+
80
+ ```typescript
81
+ import { Scheduled, RedLock } from "koatty_schedule";
82
+
83
+ export class TaskService {
84
+
85
+ @Scheduled("0 */5 * * * *") // Every 5 minutes
86
+ async processData() {
87
+ console.log("Processing data...");
88
+ // Your business logic here
89
+ }
90
+
91
+ @Scheduled("0 0 2 * * *", "UTC") // 2 AM UTC daily
92
+ async dailyCleanup() {
93
+ console.log("Running daily cleanup...");
94
+ }
95
+ }
96
+ ```
97
+
98
+ ### Distributed Locking
99
+
100
+ ```typescript
101
+ export class CriticalTaskService {
102
+
103
+ @Scheduled("0 */10 * * * *")
104
+ @RedLock("critical-task") // Prevents concurrent execution
105
+ async criticalTask() {
106
+ console.log("Running critical task with lock protection...");
107
+ // Only one instance can execute this at a time
108
+ }
109
+
110
+ @RedLock("user-sync", {
111
+ lockTimeOut: 30000, // 30 seconds
112
+ maxRetries: 5, // Retry 5 times
113
+ retryDelayMs: 500 // Wait 500ms between retries
114
+ })
115
+ async syncUsers() {
116
+ console.log("Syncing users with lock protection...");
117
+ }
118
+ }
119
+ ```
120
+
121
+ ## Advanced Configuration
122
+
123
+ ### Global Plugin Configuration
124
+
125
+ Configure global settings in `src/config/plugin.ts`:
126
+
127
+ ```typescript
12
128
  export default {
13
- ...
14
-
15
- "CacheStore": {
16
- type: "memory", // redis or memory, memory is default
17
- // key_prefix: "koatty",
18
- // host: '127.0.0.1',
19
- // port: 6379,
20
- // name: "",
21
- // username: "",
22
- // password: "",
23
- // db: 0,
24
- // timeout: 30,
25
- // pool_size: 10,
26
- // conn_timeout: 30
27
- },
28
-
29
- ...
129
+ list: ["Scheduled"],
130
+ config: {
131
+ Scheduled: {
132
+ // Global timezone (can be overridden per method)
133
+ timezone: "Asia/Shanghai",
134
+
135
+ // Default RedLock settings
136
+ lockTimeOut: 15000,
137
+ maxRetries: 3,
138
+ retryDelayMs: 200,
139
+ clockDriftFactor: 0.01,
140
+
141
+ // Redis configuration for distributed locks
142
+ redisConfig: {
143
+ host: "redis.example.com",
144
+ port: 6379,
145
+ password: "your-password",
146
+ db: 1,
147
+ keyPrefix: "myapp:locks:",
148
+ connectTimeout: 5000,
149
+ commandTimeout: 10000
150
+ }
151
+ }
152
+ }
30
153
  };
154
+ ```
155
+
156
+ ### Method-Level Overrides
157
+
158
+ ```typescript
159
+ export class AdvancedTaskService {
160
+
161
+ // Custom timezone override
162
+ @Scheduled('0 0 8 * * 1-5', 'America/New_York') // 8 AM EST, weekdays only
163
+ async businessHoursTask() {
164
+ console.log("Running during business hours...");
165
+ }
166
+
167
+ // Extended lock configuration for long-running tasks
168
+ @Scheduled('0 0 3 * * *')
169
+ @RedLock('heavy-processing', {
170
+ lockTimeOut: 300000, // 5 minutes
171
+ maxRetries: 1, // Don't retry if another instance is running
172
+ retryDelayMs: 1000
173
+ })
174
+ async heavyProcessing() {
175
+ console.log("Running heavy processing task...");
176
+ // Long-running task with extended timeout
177
+ }
178
+
179
+ // Custom lock name with timestamp
180
+ @RedLock() // Auto-generates unique lock name
181
+ async dynamicTask() {
182
+ console.log("Running with auto-generated lock name...");
183
+ }
184
+ }
185
+ ```
186
+
187
+ ## Configuration Priority System
188
+
189
+ The library uses a three-tier priority system for configuration:
190
+
191
+ 1. **Method-level** (highest priority)
192
+ 2. **Global plugin config**
193
+ 3. **Built-in defaults** (lowest priority)
194
+
195
+ ### Timezone Resolution
196
+
197
+ ```typescript
198
+ // Priority: Method > Global > Default ('Asia/Beijing')
199
+
200
+ @Scheduled('0 0 12 * * *', 'UTC') // Uses UTC (method-level)
201
+ async task1() { ... }
202
+
203
+ @Scheduled('0 0 12 * * *') // Uses global timezone from plugin config
204
+ async task2() { ... }
205
+ ```
206
+
207
+ ### RedLock Options Resolution
208
+
209
+ ```typescript
210
+ // Global config in plugin.ts
211
+ Scheduled: {
212
+ lockTimeOut: 10000,
213
+ maxRetries: 3
214
+ }
215
+
216
+ // Method-level override
217
+ @RedLock('my-lock', {
218
+ lockTimeOut: 20000 // Overrides global, keeps maxRetries: 3
219
+ })
220
+ async task() { ... }
221
+ ```
222
+
223
+ ## Monitoring and Health Checks
224
+
225
+ ### Health Status Check
226
+
227
+ ```typescript
228
+ import { RedLocker } from "koatty_schedule";
229
+
230
+ export class MonitoringService {
231
+
232
+ @Scheduled('*/30 * * * * *') // Every 30 seconds
233
+ async checkSystemHealth() {
234
+ const redLocker = RedLocker.getInstance();
235
+ const health = await redLocker.healthCheck();
236
+
237
+ console.log('RedLock Status:', health.status);
238
+ console.log('Connection Details:', health.details);
239
+
240
+ if (health.status === 'unhealthy') {
241
+ // Send alert or take corrective action
242
+ console.error('RedLock is unhealthy!', health.details);
243
+ }
244
+ }
245
+ }
246
+ ```
247
+
248
+ ### Performance Monitoring
31
249
 
250
+ ```typescript
251
+ export class PerformanceService {
252
+
253
+ @Scheduled('0 */15 * * * *')
254
+ async monitorPerformance() {
255
+ const redLocker = RedLocker.getInstance();
256
+ const config = redLocker.getConfig();
257
+
258
+ console.log('Current RedLock Configuration:', {
259
+ lockTimeOut: config.lockTimeOut,
260
+ retryCount: config.retryCount,
261
+ retryDelay: config.retryDelay
262
+ });
263
+ }
264
+ }
32
265
  ```
33
266
 
34
- used in service:
267
+ ## Error Handling and Best Practices
35
268
 
36
- ```js
37
- import { Scheduled, SchedulerLock } from "koatty_schedule";
269
+ ### Robust Error Handling
38
270
 
39
- export class TestService {
271
+ ```typescript
272
+ export class RobustTaskService {
273
+
274
+ @Scheduled('0 */5 * * * *')
275
+ @RedLock('robust-task', { maxRetries: 2 })
276
+ async robustTask() {
277
+ try {
278
+ // Your business logic
279
+ await this.processData();
280
+ } catch (error) {
281
+ // Handle business logic errors
282
+ console.error('Task failed:', error);
283
+
284
+ // Don't re-throw unless you want to stop the schedule
285
+ // The scheduler will continue with the next execution
286
+ }
287
+ }
40
288
 
41
- @Scheduled("0 * * * * *")
42
- @SchedulerLock("testCron") //locker
43
- Test(){
44
- //todo
289
+ private async processData() {
290
+ // Simulate work that might fail
291
+ if (Math.random() < 0.1) {
292
+ throw new Error('Random processing error');
45
293
  }
294
+ console.log('Data processed successfully');
295
+ }
296
+ }
297
+ ```
298
+
299
+ ### Lock Extension for Long Tasks
300
+
301
+ ```typescript
302
+ export class LongRunningTaskService {
303
+
304
+ @Scheduled('0 0 1 * * *') // Daily at 1 AM
305
+ @RedLock('daily-backup', {
306
+ lockTimeOut: 60000, // 1 minute initial lock
307
+ maxRetries: 1 // Don't wait if another instance is running
308
+ })
309
+ async dailyBackup() {
310
+ console.log('Starting daily backup...');
311
+
312
+ // The lock will automatically extend up to 3 times (configurable)
313
+ // if the task takes longer than the initial timeout
314
+ await this.performLongBackup(); // May take several minutes
315
+
316
+ console.log('Daily backup completed');
317
+ }
318
+
319
+ private async performLongBackup() {
320
+ // Simulate long-running backup process
321
+ await new Promise(resolve => setTimeout(resolve, 150000)); // 2.5 minutes
322
+ }
323
+ }
324
+ ```
325
+
326
+ ## Cron Expression Examples
327
+
328
+ ```typescript
329
+ export class CronExamplesService {
330
+
331
+ @Scheduled('0 0 * * * *') // Every hour
332
+ async hourlyTask() { }
333
+
334
+ @Scheduled('0 */30 * * * *') // Every 30 minutes
335
+ async halfHourlyTask() { }
336
+
337
+ @Scheduled('0 0 9 * * 1-5') // 9 AM, Monday to Friday
338
+ async weekdayMorningTask() { }
339
+
340
+ @Scheduled('0 0 0 1 * *') // First day of every month
341
+ async monthlyTask() { }
342
+
343
+ @Scheduled('0 0 0 * * 0') // Every Sunday
344
+ async weeklyTask() { }
345
+
346
+ @Scheduled('*/10 * * * * *') // Every 10 seconds
347
+ async frequentTask() { }
46
348
  }
349
+ ```
350
+
351
+ ## Troubleshooting
352
+
353
+ ### Common Issues
354
+
355
+ 1. **Redis Connection Failed**
356
+ ```typescript
357
+ // Check your CacheStore configuration
358
+ "CacheStore": {
359
+ type: "redis", // Must be "redis" for distributed locking
360
+ host: '127.0.0.1',
361
+ port: 6379,
362
+ // ... other settings
363
+ }
364
+ ```
365
+
366
+ 2. **Lock Acquisition Timeout**
367
+ ```typescript
368
+ // Increase timeout or reduce retries
369
+ @RedLock('my-lock', {
370
+ lockTimeOut: 30000, // Increase timeout
371
+ maxRetries: 1 // Reduce retries to fail fast
372
+ })
373
+ ```
374
+
375
+ 3. **Timezone Issues**
376
+ ```typescript
377
+ // Always specify timezone explicitly for critical tasks
378
+ @Scheduled('0 0 9 * * *', 'America/New_York')
379
+ async criticalMorningTask() { }
380
+ ```
381
+
382
+ ### Debug Mode
383
+
384
+ Enable debug logging by setting environment variable:
385
+
386
+ ```bash
387
+ DEBUG=koatty_schedule* npm start
388
+ ```
389
+
390
+ ## API Reference
391
+
392
+ ### Decorators
393
+
394
+ #### `@Scheduled(cron: string, timezone?: string)`
395
+ - `cron`: Cron expression (6-part format with seconds)
396
+ - `timezone`: Optional timezone override
397
+
398
+ #### `@RedLock(lockName?: string, options?: RedLockMethodOptions)`
399
+ - `lockName`: Unique lock identifier (auto-generated if not provided)
400
+ - `options`: Method-level lock configuration
401
+
402
+ ### Configuration Types
403
+
404
+ ```typescript
405
+ interface ScheduledOptions {
406
+ timezone?: string;
407
+ lockTimeOut?: number;
408
+ maxRetries?: number;
409
+ retryDelayMs?: number;
410
+ clockDriftFactor?: number;
411
+ redisConfig?: RedisConfig;
412
+ }
413
+
414
+ interface RedLockMethodOptions {
415
+ lockTimeOut?: number;
416
+ maxRetries?: number;
417
+ retryDelayMs?: number;
418
+ clockDriftFactor?: number;
419
+ }
420
+ ```
421
+
422
+ ## Version Compatibility
423
+
424
+ - **Koatty**: >= 2.0.0
425
+ - **Node.js**: >= 14.0.0
426
+ - **Redis**: >= 3.0.0
427
+
428
+ ## License
429
+
430
+ [BSD-3-Clause](LICENSE)
431
+
432
+ ## Contributing
433
+
434
+ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
435
+
436
+ ## Support
47
437
 
48
- ```
438
+ - 📚 [Documentation](https://koatty.js.org/)
439
+ - 🐛 [Issues](https://github.com/koattyjs/koatty_schedule/issues)
440
+ - 💬 [Discussions](https://github.com/koattyjs/koatty_schedule/discussions)