@azlib/scheduler 0.2.0 → 1.0.1
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.md +72 -91
- package/dist/index.cjs +375 -35
- package/dist/index.d.cts +48 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +48 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +375 -36
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -7
package/README.md
CHANGED
|
@@ -1,108 +1,89 @@
|
|
|
1
1
|
# @azlib/scheduler
|
|
2
2
|
|
|
3
|
-
Cron-style job
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
3
|
+
Cron-style job scheduler for Node.js, supporting timezone normalization, overlap prevention policies, missed run executions, and database persistence.
|
|
4
|
+
|
|
5
|
+
## Capabilities
|
|
6
|
+
|
|
7
|
+
- Schedule parsing and timezone normalization
|
|
8
|
+
- Job registration and lifecycle control (start, stop)
|
|
9
|
+
- Standalone runner execution or embedded hosting (e.g. Express)
|
|
10
|
+
- Host lifecycle bindings for graceful setups
|
|
11
|
+
- Queue-backed execution dispatch through `@azlib/queue`
|
|
12
|
+
- Cache coordination using `@azlib/cache`
|
|
13
|
+
- Structured database state persistence (SQL persistence)
|
|
14
|
+
|
|
15
|
+
## AI Agent Quick Reference
|
|
16
|
+
|
|
17
|
+
### Core Exports
|
|
18
|
+
|
|
19
|
+
| Export | Type | Description |
|
|
20
|
+
| --- | --- | --- |
|
|
21
|
+
| `createSchedulerService(options: SchedulerServiceOptions)` | Function | Instantiates a SchedulerService instance and a Handler Registry. |
|
|
22
|
+
| `createCronExpression(): CronExpressionBuilder` | Function | Fluent helper to construct standard 5-field cron strings. |
|
|
23
|
+
| `bindSchedulerToHost(service: SchedulerService, adapter: SchedulerHostAdapter)` | Function | Automatically starts/stops the scheduler based on custom server bindings. |
|
|
24
|
+
| `CronWeekday` | Enum | Monday through Sunday utility enum values. |
|
|
25
|
+
|
|
26
|
+
### Core Types & Signatures
|
|
27
|
+
|
|
28
|
+
- `SchedulerService`:
|
|
29
|
+
- `start(): Promise<void>`
|
|
30
|
+
- `stop(): Promise<void>`
|
|
31
|
+
- `registerJob(job: SchedulerJobDefinition): Promise<void>`
|
|
32
|
+
- `unregisterJob(jobName: string): Promise<void>`
|
|
33
|
+
- `SchedulerHandlerRegistry`:
|
|
34
|
+
- `register(key: string, handler: (config?: any) => Promise<void>): void`
|
|
35
|
+
- `SchedulerJobDefinition`:
|
|
36
|
+
- `name: string`
|
|
37
|
+
- `handlerKey: string`
|
|
38
|
+
- `schedule: SchedulerScheduleConfig`
|
|
39
|
+
- `config?: any` (JSON-serializable config injected into handler)
|
|
40
|
+
- `SchedulerScheduleConfig`:
|
|
41
|
+
- `scheduleType: "cron"`
|
|
42
|
+
- `expression: string`
|
|
43
|
+
- `timezone?: string` (e.g. `"UTC"`, `"Asia/Saigon"`)
|
|
44
|
+
- `overlapPolicy: "allow" | "skip" | "enqueue"`
|
|
45
|
+
- `missedRunPolicy: "run-immediately" | "skip"`
|
|
46
|
+
|
|
47
|
+
### Basic Usage
|
|
24
48
|
|
|
25
49
|
```ts
|
|
26
50
|
import { createQueueService } from "@azlib/queue";
|
|
27
|
-
import {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
createSchedulerService,
|
|
31
|
-
} from "@azlib/scheduler";
|
|
32
|
-
|
|
33
|
-
const queue = createQueueService({
|
|
34
|
-
provider: createProviderFromEnv({ QUEUE_PROVIDER: "memory" }),
|
|
35
|
-
defaultQueue: "scheduled-jobs",
|
|
36
|
-
retryPolicy: {
|
|
37
|
-
maxAttempts: 5,
|
|
38
|
-
backoffType: "exponential-jitter",
|
|
39
|
-
baseDelayMs: 1000,
|
|
40
|
-
maxDelayMs: 60000,
|
|
41
|
-
},
|
|
42
|
-
});
|
|
51
|
+
import { createSchedulerService, createCronExpression } from "@azlib/scheduler";
|
|
52
|
+
|
|
53
|
+
const queue = createQueueService({ /* ... */ });
|
|
43
54
|
|
|
44
55
|
const { service, handlers } = createSchedulerService({
|
|
45
|
-
|
|
46
|
-
|
|
56
|
+
mode: "standalone",
|
|
57
|
+
queueService: queue,
|
|
47
58
|
});
|
|
48
59
|
|
|
49
|
-
|
|
50
|
-
|
|
60
|
+
// 1. Register executor logic
|
|
61
|
+
handlers.register("purge-logs", async (config: { thresholdDays: number }) => {
|
|
62
|
+
await db.logs.deleteOlderThan(config.thresholdDays);
|
|
51
63
|
});
|
|
52
64
|
|
|
65
|
+
// 2. Register scheduled trigger
|
|
53
66
|
await service.registerJob({
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
67
|
+
name: "nightly-purge",
|
|
68
|
+
handlerKey: "purge-logs",
|
|
69
|
+
schedule: {
|
|
70
|
+
scheduleType: "cron",
|
|
71
|
+
expression: createCronExpression().dailyAt(2, 30).build(), // 02:30 AM
|
|
72
|
+
timezone: "UTC",
|
|
73
|
+
overlapPolicy: "skip",
|
|
74
|
+
missedRunPolicy: "run-immediately",
|
|
75
|
+
},
|
|
76
|
+
config: { thresholdDays: 30 },
|
|
64
77
|
});
|
|
65
78
|
|
|
79
|
+
// 3. Boot scheduler
|
|
66
80
|
await service.start();
|
|
67
81
|
```
|
|
68
82
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const everyFiveMinutes = createCronExpression().everyNMinutes(5).build();
|
|
77
|
-
const everyTwoHours = createCronExpression().atMinute(0).everyNHours(2).build();
|
|
78
|
-
const weekdayMorning = createCronExpression()
|
|
79
|
-
.weeklyOn(CronWeekday.Monday, 9, 0)
|
|
80
|
-
.build();
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
## Embedded Runtime Binding
|
|
84
|
-
|
|
85
|
-
```ts
|
|
86
|
-
import { bindSchedulerToHost } from "@azlib/scheduler";
|
|
87
|
-
|
|
88
|
-
bindSchedulerToHost(service, {
|
|
89
|
-
onStart(listener) {
|
|
90
|
-
app.listen(3000, () => {
|
|
91
|
-
void listener();
|
|
92
|
-
});
|
|
93
|
-
},
|
|
94
|
-
onStop(listener) {
|
|
95
|
-
process.on("SIGINT", () => {
|
|
96
|
-
void listener();
|
|
97
|
-
});
|
|
98
|
-
},
|
|
99
|
-
});
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## Validation
|
|
103
|
-
|
|
104
|
-
```bash
|
|
105
|
-
pnpm --filter @azlib/scheduler lint
|
|
106
|
-
pnpm --filter @azlib/scheduler test
|
|
107
|
-
pnpm --filter @azlib/scheduler build
|
|
108
|
-
```
|
|
83
|
+
### Behavioral Gotchas
|
|
84
|
+
- **Timezone Safety**: Always specify a `timezone` in job configs to prevent local developer clocks from altering trigger cycles.
|
|
85
|
+
- **Overlap Policies**:
|
|
86
|
+
- `skip`: If a previous job execution is still running, the new scheduled trigger is skipped.
|
|
87
|
+
- `enqueue`: Queues the new run to execute immediately after the active run completes.
|
|
88
|
+
- `allow`: Runs execution concurrent to existing instances (warning: potential race conditions).
|
|
89
|
+
- **Execution Engine**: Jobs are not run inside the scheduler thread directly. Instead, they are dispatched as tasks to the configured `@azlib/queue` provider to preserve single-thread event loop safety.
|