@outloud/adonis-scheduler 1.0.5 → 1.0.7
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 +6 -1
- package/build/{chunk-BBI2I5B5.js → chunk-6VW5PUDE.js} +36 -11
- package/build/{chunk-7P6J5U6O.js → chunk-OIXFFNQU.js} +4 -1
- package/build/{command.task-GUNK3QFY.js → command.task-GALKWNLQ.js} +1 -1
- package/build/commands/scheduler_run.d.ts +2 -1
- package/build/commands/scheduler_run.js +2 -1
- package/build/index.d.ts +3 -2
- package/build/index.js +2 -2
- package/build/providers/scheduler.provider.d.ts +4 -1
- package/build/providers/scheduler.provider.js +3 -2
- package/build/{scheduler-BWT0Iqko.d.ts → scheduler-vBDqaysB.d.ts} +15 -3
- package/build/services/main.d.ts +2 -1
- package/build/stubs/config/scheduler.stub +1 -0
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
- Cancellation support for long-running tasks.
|
|
24
24
|
- Graceful shutdown.
|
|
25
25
|
- Global and task-level error handling.
|
|
26
|
+
- Auto-discovery of tasks.
|
|
26
27
|
|
|
27
28
|
## Getting Started
|
|
28
29
|
|
|
@@ -57,8 +58,12 @@ export default class TestTask extends Task {
|
|
|
57
58
|
```
|
|
58
59
|
|
|
59
60
|
### Register a task
|
|
61
|
+
For task to run it must be registered in the scheduler.
|
|
60
62
|
|
|
61
|
-
|
|
63
|
+
> [!NOTE]
|
|
64
|
+
> By default tasks are auto-discovered using the locations defined in config.
|
|
65
|
+
|
|
66
|
+
If you want to register tasks manually, you can register tasks in two ways: using the `start/scheduler.ts` preloaded file or in a provider's `start` method.
|
|
62
67
|
|
|
63
68
|
Using `start/scheduler.ts` file.
|
|
64
69
|
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { Task } from './chunk-OIXFFNQU.js';
|
|
1
2
|
import { __name } from './chunk-SHUYVCID.js';
|
|
3
|
+
import { glob } from 'fs/promises';
|
|
4
|
+
import { resolve } from 'path';
|
|
2
5
|
import { Cron } from 'croner';
|
|
3
6
|
import timers from 'timers/promises';
|
|
4
7
|
|
|
@@ -17,14 +20,16 @@ var Scheduler = class {
|
|
|
17
20
|
config;
|
|
18
21
|
resolver;
|
|
19
22
|
logger;
|
|
23
|
+
emitter;
|
|
20
24
|
locks;
|
|
21
25
|
definitions = [];
|
|
22
26
|
state = "created";
|
|
23
27
|
errorHandler;
|
|
24
|
-
constructor(config, resolver, logger, locks) {
|
|
28
|
+
constructor(config, resolver, logger, emitter, locks) {
|
|
25
29
|
this.config = config;
|
|
26
30
|
this.resolver = resolver;
|
|
27
31
|
this.logger = logger;
|
|
32
|
+
this.emitter = emitter;
|
|
28
33
|
this.locks = locks;
|
|
29
34
|
}
|
|
30
35
|
register(options) {
|
|
@@ -38,15 +43,18 @@ var Scheduler = class {
|
|
|
38
43
|
options.command
|
|
39
44
|
];
|
|
40
45
|
Object.assign(definition, options);
|
|
41
|
-
definition.loader = () => import('./command.task-
|
|
46
|
+
definition.loader = () => import('./command.task-GALKWNLQ.js').then((module) => {
|
|
42
47
|
return class extends module.CommandTask {
|
|
43
48
|
static command = command;
|
|
44
49
|
};
|
|
45
50
|
});
|
|
51
|
+
} else if (Task.isTask(options)) {
|
|
52
|
+
definition.task = options;
|
|
53
|
+
Object.assign(definition, options.options ?? {});
|
|
46
54
|
} else {
|
|
47
55
|
definition.loader = options;
|
|
48
56
|
}
|
|
49
|
-
if (!definition.loader) {
|
|
57
|
+
if (!definition.task && !definition.loader) {
|
|
50
58
|
throw new Error("Task definition must have either a command or a task defined.");
|
|
51
59
|
}
|
|
52
60
|
this.definitions.push(definition);
|
|
@@ -67,6 +75,9 @@ var Scheduler = class {
|
|
|
67
75
|
return;
|
|
68
76
|
}
|
|
69
77
|
this.setState("starting");
|
|
78
|
+
if (this.config.locations) {
|
|
79
|
+
await Promise.all(this.config.locations.map((location) => this.registerFromGlob(location)));
|
|
80
|
+
}
|
|
70
81
|
await Promise.all(this.definitions.map((definition) => this.schedule(definition)));
|
|
71
82
|
if (!this.definitions.length) {
|
|
72
83
|
this.logger.warn("No tasks registered, scheduler will not run any jobs.");
|
|
@@ -92,6 +103,20 @@ var Scheduler = class {
|
|
|
92
103
|
this.errorHandler = callback;
|
|
93
104
|
return this;
|
|
94
105
|
}
|
|
106
|
+
async registerFromGlob(pattern) {
|
|
107
|
+
const normalizedPattern = pattern.replace(/\.(?:js|ts)$/, ".{js,ts}");
|
|
108
|
+
for await (const file of glob(normalizedPattern)) {
|
|
109
|
+
try {
|
|
110
|
+
const absolutePath = resolve(file);
|
|
111
|
+
const module = await import(`file://${absolutePath}`);
|
|
112
|
+
if (Task.isTask(module.default)) {
|
|
113
|
+
this.register(module.default);
|
|
114
|
+
}
|
|
115
|
+
} catch (error) {
|
|
116
|
+
console.warn(`Failed to load task from ${file}:`, error);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
95
120
|
async load(definition) {
|
|
96
121
|
if (definition.loader) {
|
|
97
122
|
const module = await definition.loader();
|
|
@@ -145,15 +170,15 @@ var Scheduler = class {
|
|
|
145
170
|
this.logger.info(`Scheduler: ${state}`);
|
|
146
171
|
}
|
|
147
172
|
async handleError(error, _, task) {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
173
|
+
await task.onError?.(error);
|
|
174
|
+
this.emitter.emit("scheduler:error", {
|
|
175
|
+
error,
|
|
176
|
+
task
|
|
177
|
+
});
|
|
178
|
+
await this.errorHandler?.(error, task);
|
|
179
|
+
if (!this.emitter.hasListeners("scheduler:error") && !this.errorHandler) {
|
|
180
|
+
throw error;
|
|
155
181
|
}
|
|
156
|
-
throw error;
|
|
157
182
|
}
|
|
158
183
|
async cancel(job) {
|
|
159
184
|
await job.$cancel();
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { __name } from './chunk-SHUYVCID.js';
|
|
2
2
|
|
|
3
3
|
// src/task.ts
|
|
4
|
-
var Task = class {
|
|
4
|
+
var Task = class _Task {
|
|
5
5
|
static {
|
|
6
6
|
__name(this, "Task");
|
|
7
7
|
}
|
|
8
8
|
isCanceled = false;
|
|
9
9
|
promise;
|
|
10
10
|
static options;
|
|
11
|
+
static isTask(obj) {
|
|
12
|
+
return typeof obj === "function" && obj.prototype instanceof _Task;
|
|
13
|
+
}
|
|
11
14
|
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
|
12
15
|
constructor(..._) {
|
|
13
16
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { BaseCommand } from '@adonisjs/core/ace';
|
|
2
2
|
import { CommandOptions } from '@adonisjs/core/types/ace';
|
|
3
|
-
import { a as Scheduler } from '../scheduler-
|
|
3
|
+
import { a as Scheduler } from '../scheduler-vBDqaysB.js';
|
|
4
4
|
import '@adonisjs/core/container';
|
|
5
5
|
import '@adonisjs/core/types';
|
|
6
6
|
import '@adonisjs/lock/types';
|
|
7
7
|
import '@adonisjs/core/logger';
|
|
8
|
+
import '@adonisjs/core/events';
|
|
8
9
|
|
|
9
10
|
declare class SchedulerRun extends BaseCommand {
|
|
10
11
|
static commandName: string;
|
package/build/index.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { S as SchedulerConfig } from './scheduler-
|
|
2
|
-
export { a as Scheduler, T as Task, b as TaskOptions } from './scheduler-
|
|
1
|
+
import { S as SchedulerConfig } from './scheduler-vBDqaysB.js';
|
|
2
|
+
export { a as Scheduler, T as Task, b as TaskOptions } from './scheduler-vBDqaysB.js';
|
|
3
3
|
import Configure from '@adonisjs/core/commands/configure';
|
|
4
4
|
import '@adonisjs/core/container';
|
|
5
5
|
import '@adonisjs/core/types';
|
|
6
6
|
import '@adonisjs/lock/types';
|
|
7
7
|
import '@adonisjs/core/logger';
|
|
8
|
+
import '@adonisjs/core/events';
|
|
8
9
|
|
|
9
10
|
declare function configure(command: Configure): Promise<void>;
|
|
10
11
|
|
package/build/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { ApplicationService } from '@adonisjs/core/types';
|
|
2
|
-
import { a as Scheduler } from '../scheduler-
|
|
2
|
+
import { a as Scheduler, c as SchedulerEvents } from '../scheduler-vBDqaysB.js';
|
|
3
3
|
import '@adonisjs/core/container';
|
|
4
4
|
import '@adonisjs/lock/types';
|
|
5
5
|
import '@adonisjs/core/logger';
|
|
6
|
+
import '@adonisjs/core/events';
|
|
6
7
|
|
|
7
8
|
declare class SchedulerProvider {
|
|
8
9
|
protected app: ApplicationService;
|
|
@@ -18,6 +19,8 @@ declare module '@adonisjs/core/types' {
|
|
|
18
19
|
interface ContainerBindings {
|
|
19
20
|
scheduler: Scheduler;
|
|
20
21
|
}
|
|
22
|
+
interface EventsList extends SchedulerEvents {
|
|
23
|
+
}
|
|
21
24
|
}
|
|
22
25
|
|
|
23
26
|
export { SchedulerProvider as default };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Scheduler } from '../chunk-
|
|
1
|
+
import { Scheduler } from '../chunk-6VW5PUDE.js';
|
|
2
|
+
import '../chunk-OIXFFNQU.js';
|
|
2
3
|
import { __name } from '../chunk-SHUYVCID.js';
|
|
3
4
|
|
|
4
5
|
// providers/scheduler.provider.ts
|
|
@@ -21,7 +22,7 @@ var SchedulerProvider = class {
|
|
|
21
22
|
}
|
|
22
23
|
register() {
|
|
23
24
|
this.app.container.singleton(Scheduler, async () => {
|
|
24
|
-
return new Scheduler(this.getConfig(), this.app.container.createResolver(), await this.app.container.make("logger"), await this.getLocks());
|
|
25
|
+
return new Scheduler(this.getConfig(), this.app.container.createResolver(), await this.app.container.make("logger"), await this.app.container.make("emitter"), await this.getLocks());
|
|
25
26
|
});
|
|
26
27
|
this.app.container.alias("scheduler", Scheduler);
|
|
27
28
|
}
|
|
@@ -2,6 +2,7 @@ import { ContainerResolver } from '@adonisjs/core/container';
|
|
|
2
2
|
import { ContainerBindings } from '@adonisjs/core/types';
|
|
3
3
|
import { LockService } from '@adonisjs/lock/types';
|
|
4
4
|
import { Logger } from '@adonisjs/core/logger';
|
|
5
|
+
import { Emitter } from '@adonisjs/core/events';
|
|
5
6
|
|
|
6
7
|
interface SchedulerConfig {
|
|
7
8
|
/**
|
|
@@ -16,6 +17,8 @@ interface SchedulerConfig {
|
|
|
16
17
|
* The default ttl for the lock.
|
|
17
18
|
*/
|
|
18
19
|
lockDuration: number | string;
|
|
20
|
+
/** Locations for task auto-discovery */
|
|
21
|
+
locations?: string[];
|
|
19
22
|
}
|
|
20
23
|
interface TaskOptions {
|
|
21
24
|
/**
|
|
@@ -45,6 +48,12 @@ interface TaskRegisterOptions extends TaskOptions {
|
|
|
45
48
|
command: string | string[];
|
|
46
49
|
}
|
|
47
50
|
type ErrorHandler = (error: Error, task: Task) => (void | Promise<void>);
|
|
51
|
+
interface SchedulerEvents {
|
|
52
|
+
'scheduler:error': {
|
|
53
|
+
error: Error;
|
|
54
|
+
task: Task;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
48
57
|
type MaybePromise<T> = T | Promise<T>;
|
|
49
58
|
type Factory<T> = () => MaybePromise<{
|
|
50
59
|
default: T;
|
|
@@ -54,6 +63,7 @@ declare abstract class Task {
|
|
|
54
63
|
isCanceled: boolean;
|
|
55
64
|
promise?: Promise<any>;
|
|
56
65
|
static options: TaskOptions;
|
|
66
|
+
static isTask(obj: unknown): obj is typeof Task;
|
|
57
67
|
constructor(..._: any[]);
|
|
58
68
|
get name(): string;
|
|
59
69
|
abstract run(...args: any[]): Promise<void>;
|
|
@@ -68,15 +78,17 @@ declare class Scheduler {
|
|
|
68
78
|
private config;
|
|
69
79
|
private resolver;
|
|
70
80
|
private logger;
|
|
81
|
+
private emitter;
|
|
71
82
|
private locks?;
|
|
72
83
|
private definitions;
|
|
73
84
|
private state;
|
|
74
85
|
private errorHandler?;
|
|
75
|
-
constructor(config: SchedulerConfig, resolver: ContainerResolver<ContainerBindings>, logger: Logger, locks?: LockService | undefined);
|
|
76
|
-
register(options: TaskRegisterOptions | Factory<typeof Task>): this;
|
|
86
|
+
constructor(config: SchedulerConfig, resolver: ContainerResolver<ContainerBindings>, logger: Logger, emitter: Emitter<any>, locks?: LockService | undefined);
|
|
87
|
+
register(options: TaskRegisterOptions | typeof Task | Factory<typeof Task>): this;
|
|
77
88
|
start(wait?: boolean): Promise<void>;
|
|
78
89
|
stop(): Promise<void>;
|
|
79
90
|
onError(callback: ErrorHandler): this;
|
|
91
|
+
private registerFromGlob;
|
|
80
92
|
private load;
|
|
81
93
|
private make;
|
|
82
94
|
private run;
|
|
@@ -88,4 +100,4 @@ declare class Scheduler {
|
|
|
88
100
|
private schedule;
|
|
89
101
|
}
|
|
90
102
|
|
|
91
|
-
export { type SchedulerConfig as S, Task as T, Scheduler as a, type TaskOptions as b };
|
|
103
|
+
export { type SchedulerConfig as S, Task as T, Scheduler as a, type TaskOptions as b, type SchedulerEvents as c };
|
package/build/services/main.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { a as Scheduler } from '../scheduler-
|
|
1
|
+
import { a as Scheduler } from '../scheduler-vBDqaysB.js';
|
|
2
2
|
import '@adonisjs/core/container';
|
|
3
3
|
import '@adonisjs/core/types';
|
|
4
4
|
import '@adonisjs/lock/types';
|
|
5
5
|
import '@adonisjs/core/logger';
|
|
6
|
+
import '@adonisjs/core/events';
|
|
6
7
|
|
|
7
8
|
declare let scheduler: Scheduler;
|
|
8
9
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@outloud/adonis-scheduler",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.7",
|
|
5
5
|
"description": "Schedule cron jobs in AdonisJS.",
|
|
6
6
|
"author": "Outloud <hello@outloud.co>",
|
|
7
7
|
"contributors": [
|
|
@@ -66,7 +66,6 @@
|
|
|
66
66
|
"postcompile": "pnpm run copy:templates && pnpm run index:commands",
|
|
67
67
|
"build": "rm -rf build && pnpm run compile",
|
|
68
68
|
"release": "release-it",
|
|
69
|
-
"index:commands": "adonis-kit index build/commands"
|
|
70
|
-
"version": "pnpm run build"
|
|
69
|
+
"index:commands": "adonis-kit index build/commands"
|
|
71
70
|
}
|
|
72
71
|
}
|