@lafken/schedule 0.7.0 → 0.8.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 +103 -41
- package/lib/main/schedule/schedule.d.ts +39 -0
- package/lib/main/schedule/schedule.js +39 -0
- package/lib/resolver/cron/cron.d.ts +1 -0
- package/package.json +13 -11
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @lafken/schedule
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Define Amazon EventBridge scheduled rules using TypeScript decorators. `@lafken/schedule` lets you declare cron-based tasks directly on class methods — each one becomes a Lambda function invoked automatically by EventBridge at the specified times.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -8,82 +8,144 @@
|
|
|
8
8
|
npm install @lafken/schedule
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Getting Started
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Define a schedule class with `@Schedule`, add `@Cron` methods, and register it through `ScheduleResolver`:
|
|
14
14
|
|
|
15
15
|
```typescript
|
|
16
|
+
import { createApp, createModule } from '@lafken/main';
|
|
16
17
|
import { ScheduleResolver } from '@lafken/schedule/resolver';
|
|
18
|
+
import { Schedule, Cron } from '@lafken/schedule/main';
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
name: 'awesome-app',
|
|
20
|
-
resolvers: [
|
|
21
|
-
new ScheduleResolver(),
|
|
22
|
-
],
|
|
23
|
-
...
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
// ...
|
|
27
|
-
|
|
20
|
+
// 1. Define scheduled tasks
|
|
28
21
|
@Schedule()
|
|
29
|
-
class
|
|
30
|
-
|
|
22
|
+
export class MaintenanceJobs {
|
|
23
|
+
@Cron({ schedule: 'cron(0 3 * * ? *)' })
|
|
24
|
+
cleanupExpiredSessions() {
|
|
25
|
+
// Runs every day at 3:00 AM UTC
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@Cron({ schedule: { hour: 0, minute: 0, weekDay: 'SUN' } })
|
|
29
|
+
generateWeeklyReport() {
|
|
30
|
+
// Runs every Sunday at midnight UTC
|
|
31
|
+
}
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
]
|
|
34
|
+
// 2. Register in a module
|
|
35
|
+
const maintenanceModule = createModule({
|
|
36
|
+
name: 'maintenance',
|
|
37
|
+
resources: [MaintenanceJobs],
|
|
38
38
|
});
|
|
39
39
|
|
|
40
|
+
// 3. Add the resolver to the app
|
|
41
|
+
createApp({
|
|
42
|
+
name: 'my-app',
|
|
43
|
+
resolvers: [new ScheduleResolver()],
|
|
44
|
+
modules: [maintenanceModule],
|
|
45
|
+
});
|
|
40
46
|
```
|
|
41
47
|
|
|
48
|
+
Each `@Cron` method becomes an independent Lambda function with its own EventBridge rule.
|
|
49
|
+
|
|
42
50
|
## Features
|
|
43
51
|
|
|
44
|
-
###
|
|
52
|
+
### Schedule Class
|
|
45
53
|
|
|
46
|
-
Use the `@Schedule` decorator to
|
|
54
|
+
Use the `@Schedule` decorator to group related cron tasks in a single class. The class itself holds no schedule logic — it acts as a container for `@Cron` handlers:
|
|
47
55
|
|
|
48
56
|
```typescript
|
|
49
|
-
import { Schedule, Cron } from '@lafken/schedule';
|
|
57
|
+
import { Schedule, Cron } from '@lafken/schedule/main';
|
|
50
58
|
|
|
51
59
|
@Schedule()
|
|
52
|
-
export class
|
|
53
|
-
|
|
60
|
+
export class DataPipeline {
|
|
61
|
+
@Cron({ schedule: 'cron(0 6 * * ? *)' })
|
|
62
|
+
ingestData() { }
|
|
63
|
+
|
|
64
|
+
@Cron({ schedule: 'cron(30 6 * * ? *)' })
|
|
65
|
+
transformData() { }
|
|
54
66
|
}
|
|
55
67
|
```
|
|
56
68
|
|
|
57
|
-
###
|
|
58
|
-
|
|
59
|
-
Use the `@Cron` decorator to define a method as a scheduled task. You can configure the schedule using a standard cron string or a structured object.
|
|
69
|
+
### Cron Expression (String)
|
|
60
70
|
|
|
61
|
-
|
|
71
|
+
Pass a standard AWS cron expression as a string. The format follows:
|
|
62
72
|
|
|
63
|
-
|
|
73
|
+
```
|
|
74
|
+
cron(Minutes Hours Day-of-month Month Day-of-week Year)
|
|
75
|
+
```
|
|
64
76
|
|
|
65
77
|
```typescript
|
|
66
|
-
@Cron({
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
78
|
+
@Cron({ schedule: 'cron(0 12 * * ? *)' })
|
|
79
|
+
sendDailyDigest() {
|
|
80
|
+
// Every day at 12:00 PM UTC
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@Cron({ schedule: 'cron(0 9 1 * ? *)' })
|
|
84
|
+
generateMonthlyInvoice() {
|
|
85
|
+
// First day of every month at 9:00 AM UTC
|
|
71
86
|
}
|
|
72
87
|
```
|
|
73
88
|
|
|
74
|
-
|
|
89
|
+
> [!NOTE]
|
|
90
|
+
> AWS cron expressions require either the day-of-month or day-of-week field to be `?`. You cannot specify both simultaneously. When using a cron string, include the full `cron(...)` wrapper.
|
|
75
91
|
|
|
76
|
-
|
|
92
|
+
### Cron Expression (Object)
|
|
93
|
+
|
|
94
|
+
For a more readable alternative, use the `ScheduleTime` object format. Each field defaults to `'*'` when omitted:
|
|
77
95
|
|
|
78
96
|
```typescript
|
|
79
97
|
@Cron({
|
|
80
98
|
schedule: {
|
|
81
|
-
minute:
|
|
82
|
-
hour:
|
|
99
|
+
minute: 0,
|
|
100
|
+
hour: 8,
|
|
83
101
|
weekDay: 'MON-FRI',
|
|
84
102
|
},
|
|
85
103
|
})
|
|
86
|
-
|
|
87
|
-
|
|
104
|
+
startBusinessHours() {
|
|
105
|
+
// Every weekday at 8:00 AM UTC
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@Cron({
|
|
109
|
+
schedule: {
|
|
110
|
+
minute: 30,
|
|
111
|
+
hour: 22,
|
|
112
|
+
day: 15,
|
|
113
|
+
},
|
|
114
|
+
})
|
|
115
|
+
midMonthAudit() {
|
|
116
|
+
// 15th of every month at 10:30 PM UTC
|
|
88
117
|
}
|
|
89
118
|
```
|
|
119
|
+
|
|
120
|
+
#### ScheduleTime Fields
|
|
121
|
+
|
|
122
|
+
| Field | Type | Default | Description |
|
|
123
|
+
| --------- | --------------------------- | ------- | -------------------- |
|
|
124
|
+
| `minute` | `number \| '*' \| '?'` | `'*'` | Minute (0–59) |
|
|
125
|
+
| `hour` | `number \| '*' \| '?'` | `'*'` | Hour (0–23) |
|
|
126
|
+
| `day` | `number \| '*' \| '?'` | `'*'` | Day of month (1–31) |
|
|
127
|
+
| `month` | `number \| '*' \| '?'` | `'*'` | Month (1–12) |
|
|
128
|
+
| `weekDay` | `number \| string \| '?'` | `'*'` | Day of week (SUN–SAT or 1–7) |
|
|
129
|
+
| `year` | `number \| '*' \| '?'` | `'*'` | Year |
|
|
130
|
+
|
|
131
|
+
When `day` is set to a specific value, `weekDay` is automatically set to `'?'` and vice versa, following the AWS cron constraint.
|
|
132
|
+
|
|
133
|
+
### Retry Policy
|
|
134
|
+
|
|
135
|
+
Configure how EventBridge handles failed deliveries using `retryAttempts` and `maxEventAge`:
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
@Cron({
|
|
139
|
+
schedule: 'cron(0 0 * * ? *)',
|
|
140
|
+
retryAttempts: 3,
|
|
141
|
+
maxEventAge: 3600,
|
|
142
|
+
})
|
|
143
|
+
criticalNightlyJob() {
|
|
144
|
+
// Retries up to 3 times, discards events older than 1 hour
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
| Option | Type | Description |
|
|
149
|
+
| --------------- | -------- | ---------------------------------------------------------- |
|
|
150
|
+
| `retryAttempts` | `number` | Maximum retry attempts if the target invocation fails |
|
|
151
|
+
| `maxEventAge` | `number` | Maximum event age in seconds before the event is discarded |
|
|
@@ -1,4 +1,43 @@
|
|
|
1
1
|
import type { EventCronProps } from './schedule.types';
|
|
2
2
|
export declare const RESOURCE_TYPE: "CRON";
|
|
3
|
+
/**
|
|
4
|
+
* Class decorator that registers a class as a scheduled event resource.
|
|
5
|
+
*
|
|
6
|
+
* The decorated class groups one or more `@Cron` handler methods that
|
|
7
|
+
* are invoked on a time-based schedule via Amazon EventBridge.
|
|
8
|
+
*
|
|
9
|
+
* @param props - Optional resource configuration (e.g. a custom `name`).
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* @Schedule()
|
|
14
|
+
* export class MaintenanceJobs {
|
|
15
|
+
* @Cron({ schedule: { hour: 3, minute: 0 } })
|
|
16
|
+
* cleanup() { }
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
3
20
|
export declare const Schedule: (props?: import("@lafken/common").ResourceProps | undefined) => (constructor: Function) => void;
|
|
21
|
+
/**
|
|
22
|
+
* Method decorator that registers a handler to run on a cron schedule.
|
|
23
|
+
*
|
|
24
|
+
* The decorated method becomes a Lambda function invoked automatically
|
|
25
|
+
* by EventBridge at the times defined by the `schedule` option. The
|
|
26
|
+
* schedule can be a standard AWS cron string or a structured
|
|
27
|
+
* `ScheduleTime` object.
|
|
28
|
+
*
|
|
29
|
+
* @param props - Schedule configuration (schedule expression, maxEventAge,
|
|
30
|
+
* retryAttempts).
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* // Using a cron string (every day at midnight UTC)
|
|
35
|
+
* @Cron({ schedule: 'cron(0 0 * * ? *)' })
|
|
36
|
+
* dailyReport() { }
|
|
37
|
+
*
|
|
38
|
+
* // Using a ScheduleTime object (every Monday at 8:30 AM)
|
|
39
|
+
* @Cron({ schedule: { weekDay: 'MON', hour: 8, minute: 30 } })
|
|
40
|
+
* weeklyDigest() { }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
4
43
|
export declare const Cron: (props: EventCronProps) => (target: any, methodName: string, descriptor: PropertyDescriptor) => any;
|
|
@@ -3,10 +3,49 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Cron = exports.Schedule = exports.RESOURCE_TYPE = void 0;
|
|
4
4
|
const common_1 = require("@lafken/common");
|
|
5
5
|
exports.RESOURCE_TYPE = 'CRON';
|
|
6
|
+
/**
|
|
7
|
+
* Class decorator that registers a class as a scheduled event resource.
|
|
8
|
+
*
|
|
9
|
+
* The decorated class groups one or more `@Cron` handler methods that
|
|
10
|
+
* are invoked on a time-based schedule via Amazon EventBridge.
|
|
11
|
+
*
|
|
12
|
+
* @param props - Optional resource configuration (e.g. a custom `name`).
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* @Schedule()
|
|
17
|
+
* export class MaintenanceJobs {
|
|
18
|
+
* @Cron({ schedule: { hour: 3, minute: 0 } })
|
|
19
|
+
* cleanup() { }
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
6
23
|
exports.Schedule = (0, common_1.createResourceDecorator)({
|
|
7
24
|
type: exports.RESOURCE_TYPE,
|
|
8
25
|
callerFileIndex: 5,
|
|
9
26
|
});
|
|
27
|
+
/**
|
|
28
|
+
* Method decorator that registers a handler to run on a cron schedule.
|
|
29
|
+
*
|
|
30
|
+
* The decorated method becomes a Lambda function invoked automatically
|
|
31
|
+
* by EventBridge at the times defined by the `schedule` option. The
|
|
32
|
+
* schedule can be a standard AWS cron string or a structured
|
|
33
|
+
* `ScheduleTime` object.
|
|
34
|
+
*
|
|
35
|
+
* @param props - Schedule configuration (schedule expression, maxEventAge,
|
|
36
|
+
* retryAttempts).
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* // Using a cron string (every day at midnight UTC)
|
|
41
|
+
* @Cron({ schedule: 'cron(0 0 * * ? *)' })
|
|
42
|
+
* dailyReport() { }
|
|
43
|
+
*
|
|
44
|
+
* // Using a ScheduleTime object (every Monday at 8:30 AM)
|
|
45
|
+
* @Cron({ schedule: { weekDay: 'MON', hour: 8, minute: 30 } })
|
|
46
|
+
* weeklyDigest() { }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
10
49
|
const Cron = (props) => (0, common_1.createLambdaDecorator)({
|
|
11
50
|
getLambdaMetadata: (props, methodName) => ({
|
|
12
51
|
...props,
|
|
@@ -5,6 +5,7 @@ declare const Cron_base: (new (...args: any[]) => {
|
|
|
5
5
|
isGlobal(module: import("@lafken/common").ModuleGlobalReferenceNames | (string & {}), id: string): void;
|
|
6
6
|
isDependent(resolveDependency: () => void): void;
|
|
7
7
|
readonly node: import("constructs").Node;
|
|
8
|
+
with(...mixins: import("constructs").IMixin[]): import("constructs").IConstruct;
|
|
8
9
|
toString(): string;
|
|
9
10
|
}) & typeof CloudwatchEventRule;
|
|
10
11
|
export declare class Cron extends Cron_base {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lafken/schedule",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Define EventBridge scheduled rules and cron jobs using TypeScript decorators with Lafken",
|
|
6
6
|
"keywords": [
|
|
@@ -50,17 +50,19 @@
|
|
|
50
50
|
],
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"reflect-metadata": "^0.2.2",
|
|
53
|
-
"@lafken/resolver": "0.
|
|
53
|
+
"@lafken/resolver": "0.8.1"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@cdktn/provider-aws": "^23.
|
|
57
|
-
"@
|
|
56
|
+
"@cdktn/provider-aws": "^23.3.0",
|
|
57
|
+
"@swc/core": "^1.15.18",
|
|
58
|
+
"@swc/helpers": "^0.5.19",
|
|
59
|
+
"@vitest/runner": "^4.1.0",
|
|
58
60
|
"cdktn": "^0.22.0",
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"@lafken/common": "0.
|
|
61
|
+
"cdktn-vitest": "^1.0.0",
|
|
62
|
+
"constructs": "^10.5.1",
|
|
63
|
+
"unplugin-swc": "^1.5.9",
|
|
64
|
+
"vitest": "^4.1.0",
|
|
65
|
+
"@lafken/common": "0.8.1"
|
|
64
66
|
},
|
|
65
67
|
"peerDependencies": {
|
|
66
68
|
"@cdktn/provider-aws": "^23.0.0",
|
|
@@ -76,9 +78,9 @@
|
|
|
76
78
|
},
|
|
77
79
|
"scripts": {
|
|
78
80
|
"build": "pnpm clean && tsc -p ./tsconfig.build.json",
|
|
81
|
+
"check-types": "tsc --noEmit -p ./tsconfig.build.json",
|
|
79
82
|
"clean": "rm -rf ./lib",
|
|
80
83
|
"dev": "tsc -w",
|
|
81
|
-
"test": "
|
|
82
|
-
"test:coverage": "jest --coverage"
|
|
84
|
+
"test": "vitest"
|
|
83
85
|
}
|
|
84
86
|
}
|