@arikajs/scheduler 0.0.5
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 +21 -0
- package/LICENSE +21 -0
- package/README.md +167 -0
- package/dist/Contracts/Task.d.ts +14 -0
- package/dist/Contracts/Task.js +3 -0
- package/dist/Contracts/Task.js.map +1 -0
- package/dist/Event.d.ts +44 -0
- package/dist/Event.js +140 -0
- package/dist/Event.js.map +1 -0
- package/dist/Schedule.d.ts +24 -0
- package/dist/Schedule.js +48 -0
- package/dist/Schedule.js.map +1 -0
- package/dist/Scheduler.d.ts +27 -0
- package/dist/Scheduler.js +170 -0
- package/dist/Scheduler.js.map +1 -0
- package/dist/Worker.d.ts +11 -0
- package/dist/Worker.js +41 -0
- package/dist/Worker.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/package.json +38 -0
- package/src/Contracts/Task.ts +17 -0
- package/src/Event.ts +151 -0
- package/src/Schedule.ts +50 -0
- package/src/Scheduler.ts +189 -0
- package/src/Worker.ts +44 -0
- package/src/index.ts +6 -0
- package/tests/Scheduler.test.ts +105 -0
- package/tsconfig.json +26 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# @arikajs/scheduler
|
|
2
|
+
|
|
3
|
+
## 0.0.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- feat: implement CSRF protection and standardized middleware architecture
|
|
8
|
+
|
|
9
|
+
- Added session-based CSRF protection middleware.
|
|
10
|
+
- Refactored middleware into project-level stubs for better customization.
|
|
11
|
+
- Standardized auth controller stubs.
|
|
12
|
+
- Enhanced CLI project scaffolding.
|
|
13
|
+
- Added session and localization packages.
|
|
14
|
+
|
|
15
|
+
- Updated dependencies
|
|
16
|
+
- @arikajs/cache@0.0.5
|
|
17
|
+
- @arikajs/console@0.0.5
|
|
18
|
+
- @arikajs/events@0.0.5
|
|
19
|
+
- @arikajs/foundation@0.0.5
|
|
20
|
+
- @arikajs/logging@0.0.5
|
|
21
|
+
- @arikajs/queue@0.0.5
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ArikaJs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
|
|
2
|
+
## Arika Scheduler
|
|
3
|
+
|
|
4
|
+
`@arikajs/scheduler` provides a clean, expressive, and framework-integrated task scheduling system for the ArikaJS ecosystem.
|
|
5
|
+
|
|
6
|
+
It allows you to define scheduled jobs directly in code using a fluent API โ designed for elegance and clarity โ while remaining lightweight and Node.js-native.
|
|
7
|
+
|
|
8
|
+
The scheduler is designed to work seamlessly with `@arikajs/foundation`, `@arikajs/queue`, and `@arikajs/logging`.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## โจ Features
|
|
13
|
+
|
|
14
|
+
- **๐ Fluent scheduling API**: Expressive and readable schedule definitions
|
|
15
|
+
- **โก Parallel Execution**: Non-blocking task execution for high performance
|
|
16
|
+
- **๐ Cluster Safety**: Leader election prevents double-execution in distributed environments
|
|
17
|
+
- **๐ Cron-based scheduling**: Full support for standard cron expressions
|
|
18
|
+
- **โฑ Human-readable intervals**: Preset methods like `everyMinute()`, `hourly()`, `daily()`
|
|
19
|
+
- **๐งต Queue integration**: Dispatch jobs directly to the background instead of blocking
|
|
20
|
+
- **๐ชต Logging integration**: Automatically logs task starts, completions, and failures
|
|
21
|
+
- **๐ก๏ธ Task Control**: Built-in support for timeouts and automatic retries
|
|
22
|
+
- **๐ก Lifecycle Events**: Real-time monitoring via `@arikajs/events`
|
|
23
|
+
- **๐ Timezone support**: Run tasks relative to your preferred global or local timezone
|
|
24
|
+
- **๐ Graceful Shutdown**: Safe worker termination without dropping tasks
|
|
25
|
+
- **๐ฆ TypeScript-first**: Full type safety for all scheduling operations
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## ๐ฆ Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install @arikajs/scheduler
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Requires:**
|
|
36
|
+
- `@arikajs/foundation`
|
|
37
|
+
- `@arikajs/logging`
|
|
38
|
+
- `@arikajs/cache` (recommended for overlapping & cluster locks)
|
|
39
|
+
- `@arikajs/events` (optional, for monitoring)
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## ๐ Quick Start
|
|
44
|
+
|
|
45
|
+
### 1๏ธโฃ Define Scheduled Tasks
|
|
46
|
+
|
|
47
|
+
Create a scheduler definition file (e.g., `app/Console/Kernel.ts`):
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import { Schedule } from '@arikajs/scheduler';
|
|
51
|
+
|
|
52
|
+
export default (schedule: Schedule) => {
|
|
53
|
+
// Run a closure every minute with a name
|
|
54
|
+
schedule.call(() => {
|
|
55
|
+
console.log('Running every minute');
|
|
56
|
+
}).everyMinute().name('important-sync');
|
|
57
|
+
|
|
58
|
+
// Run a CLI command daily with timeout and retries
|
|
59
|
+
schedule.command('app:cleanup')
|
|
60
|
+
.daily()
|
|
61
|
+
.timeout(60) // 1 minute timeout
|
|
62
|
+
.retry(3, 10); // retry 3 times with 10s delay
|
|
63
|
+
|
|
64
|
+
// Dispatch a job to the queue hourly
|
|
65
|
+
schedule.job(CleanupJob).hourly();
|
|
66
|
+
};
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 2๏ธโฃ Run the Scheduler
|
|
70
|
+
|
|
71
|
+
You can run the scheduler in two modes:
|
|
72
|
+
|
|
73
|
+
**Long-running Daemon (Recommended for Production)**
|
|
74
|
+
```bash
|
|
75
|
+
arika schedule:work
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Single Run (For Cron Jobs)**
|
|
79
|
+
```bash
|
|
80
|
+
* * * * * cd /path-to-your-project && node artisan schedule:run >> /dev/null 2>&1
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## ๐
Defining Tasks
|
|
86
|
+
|
|
87
|
+
### ๐ Run a Closure
|
|
88
|
+
```ts
|
|
89
|
+
schedule.call(async () => {
|
|
90
|
+
await db.table('users').where('active', false).delete();
|
|
91
|
+
}).everyMinute();
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### ๐งพ Run a Command
|
|
95
|
+
```ts
|
|
96
|
+
schedule.command('cache:clear').dailyAt('02:00');
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## ๐ก Advanced Usage
|
|
102
|
+
|
|
103
|
+
### Parallel Execution & Leader Election
|
|
104
|
+
The scheduler automatically runs all due tasks in parallel so complex tasks don't block simple ones.
|
|
105
|
+
|
|
106
|
+
In a clustered environment (multiple servers/containers), the scheduler uses `@arikajs/cache` to perform **Leader Election**. Only one server will process the schedule for any given minute, ensuring safety without extra configuration.
|
|
107
|
+
|
|
108
|
+
### Preventing Overlaps
|
|
109
|
+
If a specific task should not start if its previous instance is still active:
|
|
110
|
+
```ts
|
|
111
|
+
schedule
|
|
112
|
+
.command('report:generate')
|
|
113
|
+
.everyMinute()
|
|
114
|
+
.withoutOverlapping();
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Timezone & Retries
|
|
118
|
+
```ts
|
|
119
|
+
schedule
|
|
120
|
+
.command('backup:run')
|
|
121
|
+
.dailyAt('01:00')
|
|
122
|
+
.timezone('Asia/Kolkata')
|
|
123
|
+
.retry(3, 30); // Retry 3 times with 30s delay between attempts
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Monitoring via Events
|
|
127
|
+
The scheduler emits events that you can listen to in your `EventsServiceProvider`:
|
|
128
|
+
- `scheduler.TaskStarting`
|
|
129
|
+
- `scheduler.TaskFinished
|
|
130
|
+
- `scheduler.TaskFailed`
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
Event.listen('scheduler.TaskFailed', (data) => {
|
|
134
|
+
Log.error(`CRITICAL: Task ${data.task} failed! Error: ${data.err.message}`);
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## ๐ Architecture
|
|
141
|
+
|
|
142
|
+
```text
|
|
143
|
+
scheduler/
|
|
144
|
+
โโโ src/
|
|
145
|
+
โ โโโ Contracts
|
|
146
|
+
โ โ โโโ Task.ts
|
|
147
|
+
โ โโโ Mutex
|
|
148
|
+
โ โโโ Event.ts
|
|
149
|
+
โ โโโ index.ts
|
|
150
|
+
โ โโโ Schedule.ts
|
|
151
|
+
โ โโโ Scheduler.ts
|
|
152
|
+
โ โโโ Worker.ts
|
|
153
|
+
โโโ tests/
|
|
154
|
+
โโโ package.json
|
|
155
|
+
โโโ tsconfig.json
|
|
156
|
+
โโโ README.md
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## ๐ License
|
|
160
|
+
|
|
161
|
+
`@arikajs/scheduler` is open-source software licensed under the **MIT License**.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## ๐งญ Philosophy
|
|
166
|
+
|
|
167
|
+
> "If it must run, it must run reliably."
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface Task {
|
|
2
|
+
/**
|
|
3
|
+
* Run the scheduled task.
|
|
4
|
+
*/
|
|
5
|
+
run(): Promise<void> | void;
|
|
6
|
+
/**
|
|
7
|
+
* Get the cron expression for the task.
|
|
8
|
+
*/
|
|
9
|
+
expression(): string;
|
|
10
|
+
/**
|
|
11
|
+
* Determine if the task is due to run.
|
|
12
|
+
*/
|
|
13
|
+
isDue(date: Date, timezone?: string): boolean;
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Task.js","sourceRoot":"","sources":["../../src/Contracts/Task.ts"],"names":[],"mappings":""}
|
package/dist/Event.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Task } from './Contracts/Task';
|
|
2
|
+
export declare class Event implements Task {
|
|
3
|
+
readonly command: string | Function;
|
|
4
|
+
protected cronExpression: string;
|
|
5
|
+
protected timezoneVal?: string;
|
|
6
|
+
protected withoutOverlappingVal: boolean;
|
|
7
|
+
protected expiresAt: number;
|
|
8
|
+
protected successCallbacks: Function[];
|
|
9
|
+
protected failureCallbacks: (Function)[];
|
|
10
|
+
protected timeoutVal: number;
|
|
11
|
+
protected retriesVal: number;
|
|
12
|
+
protected retryDelayVal: number;
|
|
13
|
+
protected descriptionVal: string;
|
|
14
|
+
constructor(command: string | Function);
|
|
15
|
+
name(description: string): this;
|
|
16
|
+
timeout(seconds: number): this;
|
|
17
|
+
retry(times: number, delay?: number): this;
|
|
18
|
+
cron(expression: string): this;
|
|
19
|
+
timezone(timezone: string): this;
|
|
20
|
+
withoutOverlapping(expiresAt?: number): this;
|
|
21
|
+
onSuccess(callback: Function): this;
|
|
22
|
+
onFailure(callback: Function): this;
|
|
23
|
+
everySecond(): this;
|
|
24
|
+
everyMinute(): this;
|
|
25
|
+
everyFiveMinutes(): this;
|
|
26
|
+
everyTenMinutes(): this;
|
|
27
|
+
hourly(): this;
|
|
28
|
+
hourlyAt(minute: number): this;
|
|
29
|
+
daily(): this;
|
|
30
|
+
dailyAt(time: string): this;
|
|
31
|
+
weekly(): this;
|
|
32
|
+
weeklyOn(day: number, time?: string): this;
|
|
33
|
+
monthly(): this;
|
|
34
|
+
monthlyOn(day: number, time?: string): this;
|
|
35
|
+
expression(): string;
|
|
36
|
+
isDue(date: Date, timezone?: string): boolean;
|
|
37
|
+
run(): Promise<void>;
|
|
38
|
+
shouldSkipOverlapping(): boolean;
|
|
39
|
+
mutexExpiration(): number;
|
|
40
|
+
getTimeout(): number;
|
|
41
|
+
getRetries(): number;
|
|
42
|
+
getRetryDelay(): number;
|
|
43
|
+
getDescription(): string;
|
|
44
|
+
}
|
package/dist/Event.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Event = void 0;
|
|
7
|
+
const cron_parser_1 = __importDefault(require("cron-parser"));
|
|
8
|
+
class Event {
|
|
9
|
+
command;
|
|
10
|
+
cronExpression = '* * * * *';
|
|
11
|
+
timezoneVal;
|
|
12
|
+
withoutOverlappingVal = false;
|
|
13
|
+
expiresAt = 1440; // 24 hours default for overlap lock
|
|
14
|
+
successCallbacks = [];
|
|
15
|
+
failureCallbacks = [];
|
|
16
|
+
timeoutVal = 0;
|
|
17
|
+
retriesVal = 0;
|
|
18
|
+
retryDelayVal = 0;
|
|
19
|
+
descriptionVal = '';
|
|
20
|
+
constructor(command) {
|
|
21
|
+
this.command = command;
|
|
22
|
+
}
|
|
23
|
+
name(description) {
|
|
24
|
+
this.descriptionVal = description;
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
timeout(seconds) {
|
|
28
|
+
this.timeoutVal = seconds;
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
retry(times, delay = 0) {
|
|
32
|
+
this.retriesVal = times;
|
|
33
|
+
this.retryDelayVal = delay;
|
|
34
|
+
return this;
|
|
35
|
+
}
|
|
36
|
+
cron(expression) {
|
|
37
|
+
this.cronExpression = expression;
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
40
|
+
timezone(timezone) {
|
|
41
|
+
this.timezoneVal = timezone;
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
withoutOverlapping(expiresAt = 1440) {
|
|
45
|
+
this.withoutOverlappingVal = true;
|
|
46
|
+
this.expiresAt = expiresAt;
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
onSuccess(callback) {
|
|
50
|
+
this.successCallbacks.push(callback);
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
onFailure(callback) {
|
|
54
|
+
this.failureCallbacks.push(callback);
|
|
55
|
+
return this;
|
|
56
|
+
}
|
|
57
|
+
// Frequencies
|
|
58
|
+
everySecond() { return this.cron('* * * * * *'); }
|
|
59
|
+
everyMinute() { return this.cron('* * * * *'); }
|
|
60
|
+
everyFiveMinutes() { return this.cron('*/5 * * * *'); }
|
|
61
|
+
everyTenMinutes() { return this.cron('*/10 * * * *'); }
|
|
62
|
+
hourly() { return this.cron('0 * * * *'); }
|
|
63
|
+
hourlyAt(minute) { return this.cron(`${minute} * * * *`); }
|
|
64
|
+
daily() { return this.cron('0 0 * * *'); }
|
|
65
|
+
dailyAt(time) {
|
|
66
|
+
const [hour, minute] = time.split(':');
|
|
67
|
+
return this.cron(`${minute} ${hour} * * *`);
|
|
68
|
+
}
|
|
69
|
+
weekly() { return this.cron('0 0 * * 0'); }
|
|
70
|
+
weeklyOn(day, time = '00:00') {
|
|
71
|
+
const [hour, minute] = time.split(':');
|
|
72
|
+
return this.cron(`${minute} ${hour} * * ${day}`);
|
|
73
|
+
}
|
|
74
|
+
monthly() { return this.cron('0 0 1 * *'); }
|
|
75
|
+
monthlyOn(day, time = '00:00') {
|
|
76
|
+
const [hour, minute] = time.split(':');
|
|
77
|
+
return this.cron(`${minute} ${hour} ${day} * *`);
|
|
78
|
+
}
|
|
79
|
+
expression() {
|
|
80
|
+
return this.cronExpression;
|
|
81
|
+
}
|
|
82
|
+
isDue(date, timezone) {
|
|
83
|
+
const options = {
|
|
84
|
+
currentDate: new Date(date.getTime() - 1000),
|
|
85
|
+
tz: this.timezoneVal || timezone
|
|
86
|
+
};
|
|
87
|
+
try {
|
|
88
|
+
const interval = cron_parser_1.default.parseExpression(this.cronExpression, options);
|
|
89
|
+
const next = interval.next().toDate();
|
|
90
|
+
return next.getMinutes() === date.getMinutes() &&
|
|
91
|
+
next.getHours() === date.getHours() &&
|
|
92
|
+
next.getDate() === date.getDate() &&
|
|
93
|
+
next.getMonth() === date.getMonth() &&
|
|
94
|
+
next.getFullYear() === date.getFullYear();
|
|
95
|
+
}
|
|
96
|
+
catch (e) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async run() {
|
|
101
|
+
try {
|
|
102
|
+
if (typeof this.command === 'function') {
|
|
103
|
+
await this.command();
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
// For commands, we would usually use the CommandRegistry
|
|
107
|
+
// But this will be handled by the Scheduler runner
|
|
108
|
+
}
|
|
109
|
+
for (const callback of this.successCallbacks) {
|
|
110
|
+
await callback();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
for (const callback of this.failureCallbacks) {
|
|
115
|
+
await callback(e);
|
|
116
|
+
}
|
|
117
|
+
throw e;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
shouldSkipOverlapping() {
|
|
121
|
+
return this.withoutOverlappingVal;
|
|
122
|
+
}
|
|
123
|
+
mutexExpiration() {
|
|
124
|
+
return this.expiresAt;
|
|
125
|
+
}
|
|
126
|
+
getTimeout() {
|
|
127
|
+
return this.timeoutVal;
|
|
128
|
+
}
|
|
129
|
+
getRetries() {
|
|
130
|
+
return this.retriesVal;
|
|
131
|
+
}
|
|
132
|
+
getRetryDelay() {
|
|
133
|
+
return this.retryDelayVal;
|
|
134
|
+
}
|
|
135
|
+
getDescription() {
|
|
136
|
+
return this.descriptionVal;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
exports.Event = Event;
|
|
140
|
+
//# sourceMappingURL=Event.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Event.js","sourceRoot":"","sources":["../src/Event.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Event } from './Event';
|
|
2
|
+
export declare class Schedule {
|
|
3
|
+
protected events: Event[];
|
|
4
|
+
/**
|
|
5
|
+
* Add a new callback event to the schedule.
|
|
6
|
+
*/
|
|
7
|
+
call(callback: Function): Event;
|
|
8
|
+
/**
|
|
9
|
+
* Add a new command event to the schedule.
|
|
10
|
+
*/
|
|
11
|
+
command(command: string): Event;
|
|
12
|
+
/**
|
|
13
|
+
* Add a new job event to the schedule.
|
|
14
|
+
*/
|
|
15
|
+
job(job: any): Event;
|
|
16
|
+
/**
|
|
17
|
+
* Get all events.
|
|
18
|
+
*/
|
|
19
|
+
allEvents(): Event[];
|
|
20
|
+
/**
|
|
21
|
+
* Get due events.
|
|
22
|
+
*/
|
|
23
|
+
dueEvents(date: Date, timezone?: string): Event[];
|
|
24
|
+
}
|
package/dist/Schedule.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Schedule = void 0;
|
|
4
|
+
const Event_1 = require("./Event");
|
|
5
|
+
class Schedule {
|
|
6
|
+
events = [];
|
|
7
|
+
/**
|
|
8
|
+
* Add a new callback event to the schedule.
|
|
9
|
+
*/
|
|
10
|
+
call(callback) {
|
|
11
|
+
const event = new Event_1.Event(callback);
|
|
12
|
+
this.events.push(event);
|
|
13
|
+
return event;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Add a new command event to the schedule.
|
|
17
|
+
*/
|
|
18
|
+
command(command) {
|
|
19
|
+
const event = new Event_1.Event(command);
|
|
20
|
+
this.events.push(event);
|
|
21
|
+
return event;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Add a new job event to the schedule.
|
|
25
|
+
*/
|
|
26
|
+
job(job) {
|
|
27
|
+
const event = new Event_1.Event(async () => {
|
|
28
|
+
const { Queue } = await import('@arikajs/queue');
|
|
29
|
+
await Queue.dispatch(job);
|
|
30
|
+
});
|
|
31
|
+
this.events.push(event);
|
|
32
|
+
return event;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Get all events.
|
|
36
|
+
*/
|
|
37
|
+
allEvents() {
|
|
38
|
+
return this.events;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get due events.
|
|
42
|
+
*/
|
|
43
|
+
dueEvents(date, timezone) {
|
|
44
|
+
return this.events.filter(event => event.isDue(date, timezone));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.Schedule = Schedule;
|
|
48
|
+
//# sourceMappingURL=Schedule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Schedule.js","sourceRoot":"","sources":["../src/Schedule.ts"],"names":[],"mappings":";;;AACA,mCAAgC;AAEhC,MAAa,QAAQ;IACP,MAAM,GAAY,EAAE,CAAC;IAE/B;;OAEG;IACI,IAAI,CAAC,QAAkB;QAC1B,MAAM,KAAK,GAAG,IAAI,aAAK,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO,KAAK,CAAC;IACjB,CAAC;IAED;;OAEG;IACI,OAAO,CAAC,OAAe;QAC1B,MAAM,KAAK,GAAG,IAAI,aAAK,CAAC,OAAO,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO,KAAK,CAAC;IACjB,CAAC;IAED;;OAEG;IACI,GAAG,CAAC,GAAQ;QACf,MAAM,KAAK,GAAG,IAAI,aAAK,CAAC,KAAK,IAAI,EAAE;YAC/B,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;YACjD,MAAM,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO,KAAK,CAAC;IACjB,CAAC;IAED;;OAEG;IACI,SAAS;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAED;;OAEG;IACI,SAAS,CAAC,IAAU,EAAE,QAAiB;QAC1C,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IACpE,CAAC;CACJ;AA9CD,4BA8CC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Container } from '@arikajs/foundation';
|
|
2
|
+
import { Schedule } from './Schedule';
|
|
3
|
+
import { Event } from './Event';
|
|
4
|
+
export declare class Scheduler {
|
|
5
|
+
protected container: Container;
|
|
6
|
+
protected schedule: Schedule;
|
|
7
|
+
constructor(container: Container);
|
|
8
|
+
/**
|
|
9
|
+
* Define the schedule.
|
|
10
|
+
*/
|
|
11
|
+
define(callback: (schedule: Schedule) => void): this;
|
|
12
|
+
/**
|
|
13
|
+
* Run the scheduled tasks.
|
|
14
|
+
*/
|
|
15
|
+
run(date?: Date): Promise<void>;
|
|
16
|
+
protected shouldSkipBecauseAnotherInstanceIsRunning(): Promise<boolean>;
|
|
17
|
+
protected runEvent(event: Event): Promise<void>;
|
|
18
|
+
protected executeWithRetries(event: Event): Promise<void>;
|
|
19
|
+
protected executeWithTimeout(event: Event): Promise<void>;
|
|
20
|
+
protected actuallyRun(event: Event): Promise<void>;
|
|
21
|
+
protected dispatchLifecycleEvent(type: string, event: Event, extra?: any): Promise<void>;
|
|
22
|
+
protected getEventName(event: Event): string;
|
|
23
|
+
protected isLocked(event: Event): Promise<boolean>;
|
|
24
|
+
protected lock(event: Event): Promise<void>;
|
|
25
|
+
protected unlock(event: Event): Promise<void>;
|
|
26
|
+
protected getMutexName(event: Event): string;
|
|
27
|
+
}
|