@eggjs/schedule 5.0.2 → 6.0.0-beta.15
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 -12
- package/dist/agent.d.ts +13 -0
- package/dist/agent.js +32 -0
- package/dist/app/extend/agent.d.ts +22 -0
- package/dist/app/extend/agent.js +32 -0
- package/dist/app/extend/application.d.ts +16 -0
- package/dist/app/extend/application.js +18 -0
- package/dist/app/extend/application.unittest.d.ts +13 -0
- package/dist/app/extend/application.unittest.js +46 -0
- package/dist/app.d.ts +11 -0
- package/dist/app.js +69 -0
- package/dist/config/config.default.d.ts +6 -0
- package/dist/config/config.default.js +13 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +7 -0
- package/dist/lib/load_schedule.d.ts +7 -0
- package/dist/lib/load_schedule.js +61 -0
- package/dist/lib/schedule.d.ts +35 -0
- package/dist/lib/schedule.js +77 -0
- package/dist/lib/schedule_worker.d.ts +14 -0
- package/dist/lib/schedule_worker.js +22 -0
- package/dist/lib/strategy/all.d.ts +8 -0
- package/dist/lib/strategy/all.js +11 -0
- package/dist/lib/strategy/base.d.ts +35 -0
- package/dist/lib/strategy/base.js +73 -0
- package/dist/lib/strategy/timer.d.ts +24 -0
- package/dist/lib/strategy/timer.js +71 -0
- package/dist/lib/strategy/worker.d.ts +8 -0
- package/dist/lib/strategy/worker.js +11 -0
- package/dist/lib/types.d.ts +44 -0
- package/dist/lib/types.js +1 -0
- package/package.json +51 -55
- package/dist/commonjs/agent.d.ts +0 -7
- package/dist/commonjs/agent.js +0 -32
- package/dist/commonjs/app/extend/agent.d.ts +0 -2
- package/dist/commonjs/app/extend/agent.js +0 -29
- package/dist/commonjs/app/extend/application.d.ts +0 -2
- package/dist/commonjs/app/extend/application.js +0 -16
- package/dist/commonjs/app/extend/application.unittest.d.ts +0 -2
- package/dist/commonjs/app/extend/application.unittest.js +0 -58
- package/dist/commonjs/app.d.ts +0 -6
- package/dist/commonjs/app.js +0 -80
- package/dist/commonjs/config/config.default.d.ts +0 -2
- package/dist/commonjs/config/config.default.js +0 -17
- package/dist/commonjs/index.d.ts +0 -1
- package/dist/commonjs/index.js +0 -18
- package/dist/commonjs/lib/load_schedule.d.ts +0 -3
- package/dist/commonjs/lib/load_schedule.js +0 -71
- package/dist/commonjs/lib/schedule.d.ts +0 -31
- package/dist/commonjs/lib/schedule.js +0 -89
- package/dist/commonjs/lib/schedule_worker.d.ts +0 -10
- package/dist/commonjs/lib/schedule_worker.js +0 -22
- package/dist/commonjs/lib/strategy/all.d.ts +0 -4
- package/dist/commonjs/lib/strategy/all.js +0 -11
- package/dist/commonjs/lib/strategy/base.d.ts +0 -30
- package/dist/commonjs/lib/strategy/base.js +0 -79
- package/dist/commonjs/lib/strategy/timer.d.ts +0 -20
- package/dist/commonjs/lib/strategy/timer.js +0 -99
- package/dist/commonjs/lib/strategy/worker.d.ts +0 -4
- package/dist/commonjs/lib/strategy/worker.js +0 -11
- package/dist/commonjs/lib/types.d.ts +0 -53
- package/dist/commonjs/lib/types.js +0 -3
- package/dist/commonjs/package.json +0 -3
- package/dist/esm/agent.d.ts +0 -7
- package/dist/esm/agent.js +0 -29
- package/dist/esm/app/extend/agent.d.ts +0 -2
- package/dist/esm/app/extend/agent.js +0 -27
- package/dist/esm/app/extend/application.d.ts +0 -2
- package/dist/esm/app/extend/application.js +0 -14
- package/dist/esm/app/extend/application.unittest.d.ts +0 -2
- package/dist/esm/app/extend/application.unittest.js +0 -53
- package/dist/esm/app.d.ts +0 -6
- package/dist/esm/app.js +0 -77
- package/dist/esm/config/config.default.d.ts +0 -2
- package/dist/esm/config/config.default.js +0 -15
- package/dist/esm/index.d.ts +0 -1
- package/dist/esm/index.js +0 -2
- package/dist/esm/lib/load_schedule.d.ts +0 -3
- package/dist/esm/lib/load_schedule.js +0 -65
- package/dist/esm/lib/schedule.d.ts +0 -31
- package/dist/esm/lib/schedule.js +0 -85
- package/dist/esm/lib/schedule_worker.d.ts +0 -10
- package/dist/esm/lib/schedule_worker.js +0 -18
- package/dist/esm/lib/strategy/all.d.ts +0 -4
- package/dist/esm/lib/strategy/all.js +0 -7
- package/dist/esm/lib/strategy/base.d.ts +0 -30
- package/dist/esm/lib/strategy/base.js +0 -75
- package/dist/esm/lib/strategy/timer.d.ts +0 -20
- package/dist/esm/lib/strategy/timer.js +0 -92
- package/dist/esm/lib/strategy/worker.d.ts +0 -4
- package/dist/esm/lib/strategy/worker.js +0 -7
- package/dist/esm/lib/types.d.ts +0 -53
- package/dist/esm/lib/types.js +0 -2
- package/dist/esm/package.json +0 -3
- package/dist/package.json +0 -4
- package/src/agent.ts +0 -36
- package/src/app/extend/agent.ts +0 -30
- package/src/app/extend/application.ts +0 -16
- package/src/app/extend/application.unittest.ts +0 -57
- package/src/app.ts +0 -92
- package/src/config/config.default.ts +0 -17
- package/src/index.ts +0 -1
- package/src/lib/load_schedule.ts +0 -74
- package/src/lib/schedule.ts +0 -100
- package/src/lib/schedule_worker.ts +0 -24
- package/src/lib/strategy/all.ts +0 -7
- package/src/lib/strategy/base.ts +0 -91
- package/src/lib/strategy/timer.ts +0 -107
- package/src/lib/strategy/worker.ts +0 -7
- package/src/lib/types.ts +0 -58
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert';
|
|
2
|
-
import cronParser from 'cron-parser';
|
|
3
|
-
import { ms } from 'humanize-ms';
|
|
4
|
-
import safeTimers from 'safe-timers';
|
|
5
|
-
import { logDate } from 'utility';
|
|
6
|
-
import { BaseStrategy } from './base.js';
|
|
7
|
-
export class TimerStrategy extends BaseStrategy {
|
|
8
|
-
cronInstance;
|
|
9
|
-
constructor(scheduleConfig, agent, key) {
|
|
10
|
-
super(scheduleConfig, agent, key);
|
|
11
|
-
const { interval, cron, cronOptions, immediate } = this.scheduleConfig;
|
|
12
|
-
assert(interval || cron || immediate, `[@eggjs/schedule] ${this.key} \`schedule.interval\` or \`schedule.cron\` or \`schedule.immediate\` must be present`);
|
|
13
|
-
// init cron parser
|
|
14
|
-
if (cron) {
|
|
15
|
-
try {
|
|
16
|
-
this.cronInstance = cronParser.parseExpression(cron, cronOptions);
|
|
17
|
-
}
|
|
18
|
-
catch (err) {
|
|
19
|
-
throw new TypeError(`[@eggjs/schedule] ${this.key} parse cron instruction(${cron}) error: ${err.message}`, { cause: err });
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
handler() {
|
|
24
|
-
throw new TypeError(`[@eggjs/schedule] ${this.key} strategy should override \`handler()\` method`);
|
|
25
|
-
}
|
|
26
|
-
start() {
|
|
27
|
-
/* istanbul ignore next */
|
|
28
|
-
if (this.agent.schedule.closed)
|
|
29
|
-
return;
|
|
30
|
-
if (this.scheduleConfig.immediate) {
|
|
31
|
-
this.logger.info(`[Timer] ${this.key} next time will execute immediate`);
|
|
32
|
-
setImmediate(() => this.handler());
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
this.#scheduleNext();
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
#scheduleNext() {
|
|
39
|
-
/* istanbul ignore next */
|
|
40
|
-
if (this.agent.schedule.closed)
|
|
41
|
-
return;
|
|
42
|
-
// get next tick
|
|
43
|
-
const nextTick = this.getNextTick();
|
|
44
|
-
if (nextTick) {
|
|
45
|
-
this.logger.info(`[Timer] ${this.key} next time will execute after ${nextTick}ms at ${logDate(new Date(Date.now() + nextTick))}`);
|
|
46
|
-
this.safeTimeout(() => this.handler(), nextTick);
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
this.logger.info(`[Timer] ${this.key} reach endDate, will stop`);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
onJobStart() {
|
|
53
|
-
// Next execution will trigger task at a fix rate, regardless of its execution time.
|
|
54
|
-
this.#scheduleNext();
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* calculate next tick
|
|
58
|
-
*
|
|
59
|
-
* @return {Number|undefined} time interval, if out of range then return `undefined`
|
|
60
|
-
*/
|
|
61
|
-
getNextTick() {
|
|
62
|
-
// interval-style
|
|
63
|
-
if (this.scheduleConfig.interval) {
|
|
64
|
-
return ms(this.scheduleConfig.interval);
|
|
65
|
-
}
|
|
66
|
-
// cron-style
|
|
67
|
-
if (this.cronInstance) {
|
|
68
|
-
// calculate next cron tick
|
|
69
|
-
const now = Date.now();
|
|
70
|
-
let nextTick;
|
|
71
|
-
// loop to find next feature time
|
|
72
|
-
do {
|
|
73
|
-
try {
|
|
74
|
-
const nextInterval = this.cronInstance.next();
|
|
75
|
-
nextTick = nextInterval.getTime();
|
|
76
|
-
}
|
|
77
|
-
catch (err) {
|
|
78
|
-
// Error: Out of the timespan range
|
|
79
|
-
this.logger.info(`[Timer] ${this.key} cron out of the timespan range, error: %s`, err);
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
} while (now >= nextTick);
|
|
83
|
-
return nextTick - now;
|
|
84
|
-
}
|
|
85
|
-
// won\'t run here
|
|
86
|
-
}
|
|
87
|
-
safeTimeout(handler, delay, ...args) {
|
|
88
|
-
const fn = delay < safeTimers.maxInterval ? setTimeout : safeTimers.setTimeout;
|
|
89
|
-
return fn(handler, delay, ...args);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3N0cmF0ZWd5L3RpbWVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sTUFBTSxNQUFNLGFBQWEsQ0FBQztBQUVqQyxPQUFPLFVBQVUsTUFBTSxhQUFhLENBQUM7QUFDckMsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNqQyxPQUFPLFVBQVUsTUFBTSxhQUFhLENBQUM7QUFDckMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUdsQyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRXpDLE1BQU0sT0FBZ0IsYUFBYyxTQUFRLFlBQVk7SUFDNUMsWUFBWSxDQUFrQjtJQUV4QyxZQUFZLGNBQWlDLEVBQUUsS0FBWSxFQUFFLEdBQVc7UUFDdEUsS0FBSyxDQUFDLGNBQWMsRUFBRSxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFFbEMsTUFBTSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUM7UUFDdkUsTUFBTSxDQUFDLFFBQVEsSUFBSSxJQUFJLElBQUksU0FBUyxFQUNsQyxxQkFBcUIsSUFBSSxDQUFDLEdBQUcsdUZBQXVGLENBQUMsQ0FBQztRQUV4SCxtQkFBbUI7UUFDbkIsSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUNULElBQUksQ0FBQztnQkFDSCxJQUFJLENBQUMsWUFBWSxHQUFHLFVBQVUsQ0FBQyxlQUFlLENBQUMsSUFBSSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1lBQ3BFLENBQUM7WUFBQyxPQUFPLEdBQVEsRUFBRSxDQUFDO2dCQUNsQixNQUFNLElBQUksU0FBUyxDQUNqQixxQkFBcUIsSUFBSSxDQUFDLEdBQUcsMkJBQTJCLElBQUksWUFBWSxHQUFHLENBQUMsT0FBTyxFQUFFLEVBQ3JGLEVBQUUs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
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { TimerStrategy } from './timer.js';
|
|
2
|
-
export class WorkerStrategy extends TimerStrategy {
|
|
3
|
-
handler() {
|
|
4
|
-
this.sendOne();
|
|
5
|
-
}
|
|
6
|
-
}
|
|
7
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29ya2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9zdHJhdGVneS93b3JrZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUUzQyxNQUFNLE9BQU8sY0FBZSxTQUFRLGFBQWE7SUFDL0MsT0FBTztRQUNMLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNqQixDQUFDO0NBQ0YifQ==
|
package/dist/esm/lib/types.d.ts
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import type { ParserOptions as CronOptions } from 'cron-parser';
|
|
2
|
-
import type { Schedule } from './schedule.js';
|
|
3
|
-
import type { ScheduleWorker } from './schedule_worker.js';
|
|
4
|
-
/**
|
|
5
|
-
* Schedule Config
|
|
6
|
-
* @see https://www.eggjs.org/zh-CN/basics/schedule
|
|
7
|
-
*/
|
|
8
|
-
export interface EggScheduleConfig {
|
|
9
|
-
type?: 'worker' | 'all';
|
|
10
|
-
interval?: string | number;
|
|
11
|
-
cron?: string;
|
|
12
|
-
cronOptions?: CronOptions;
|
|
13
|
-
immediate?: boolean;
|
|
14
|
-
disable?: boolean;
|
|
15
|
-
env?: string[];
|
|
16
|
-
}
|
|
17
|
-
export type EggScheduleTask = (ctx: any, ...args: any[]) => Promise<void>;
|
|
18
|
-
export interface EggScheduleItem {
|
|
19
|
-
schedule: EggScheduleConfig;
|
|
20
|
-
scheduleQueryString: string;
|
|
21
|
-
task: EggScheduleTask;
|
|
22
|
-
key: string;
|
|
23
|
-
}
|
|
24
|
-
export interface EggScheduleJobInfo {
|
|
25
|
-
id: string;
|
|
26
|
-
key: string;
|
|
27
|
-
workerId: number;
|
|
28
|
-
args: any[];
|
|
29
|
-
success?: boolean;
|
|
30
|
-
message?: string;
|
|
31
|
-
rt?: number;
|
|
32
|
-
}
|
|
33
|
-
declare module 'egg' {
|
|
34
|
-
interface EggScheduleAgent {
|
|
35
|
-
schedule: Schedule;
|
|
36
|
-
}
|
|
37
|
-
interface Agent extends EggScheduleAgent {
|
|
38
|
-
}
|
|
39
|
-
interface EggScheduleApplication {
|
|
40
|
-
scheduleWorker: ScheduleWorker;
|
|
41
|
-
/** runSchedule in unittest */
|
|
42
|
-
runSchedule: (schedulePath: string, ...args: any[]) => Promise<void>;
|
|
43
|
-
}
|
|
44
|
-
interface Application extends EggScheduleApplication {
|
|
45
|
-
}
|
|
46
|
-
interface EggScheduleAppConfig {
|
|
47
|
-
schedule: {
|
|
48
|
-
directory: string[];
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
interface EggAppConfig extends EggScheduleAppConfig {
|
|
52
|
-
}
|
|
53
|
-
}
|
package/dist/esm/lib/types.js
DELETED
package/dist/esm/package.json
DELETED
package/dist/package.json
DELETED
package/src/agent.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { debuglog } from 'node:util';
|
|
2
|
-
import type { Agent, ILifecycleBoot } from 'egg';
|
|
3
|
-
import { WorkerStrategy } from './lib/strategy/worker.js';
|
|
4
|
-
import { AllStrategy } from './lib/strategy/all.js';
|
|
5
|
-
import { EggScheduleJobInfo } from './lib/types.js';
|
|
6
|
-
|
|
7
|
-
const debug = debuglog('@eggjs/schedule/agent');
|
|
8
|
-
|
|
9
|
-
export default class Boot implements ILifecycleBoot {
|
|
10
|
-
#agent: Agent;
|
|
11
|
-
constructor(agent: Agent) {
|
|
12
|
-
this.#agent = agent;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async configDidLoad(): Promise<void> {
|
|
16
|
-
// register built-in strategy
|
|
17
|
-
this.#agent.schedule.use('worker', WorkerStrategy);
|
|
18
|
-
this.#agent.schedule.use('all', AllStrategy);
|
|
19
|
-
|
|
20
|
-
// wait for other plugin to register custom strategy
|
|
21
|
-
await this.#agent.schedule.init();
|
|
22
|
-
|
|
23
|
-
// dispatch job finish event to strategy
|
|
24
|
-
this.#agent.messenger.on('egg-schedule', (info: EggScheduleJobInfo) => {
|
|
25
|
-
// get job info from worker
|
|
26
|
-
this.#agent.schedule.onJobFinish(info);
|
|
27
|
-
});
|
|
28
|
-
debug('configDidLoad');
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async serverDidReady(): Promise<void> {
|
|
32
|
-
// start schedule after worker ready
|
|
33
|
-
this.#agent.schedule.start();
|
|
34
|
-
debug('serverDidReady, schedule start');
|
|
35
|
-
}
|
|
36
|
-
}
|
package/src/app/extend/agent.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { BaseStrategy } from '../../lib/strategy/base.js';
|
|
2
|
-
import { TimerStrategy } from '../../lib/strategy/timer.js';
|
|
3
|
-
import { Schedule } from '../../lib/schedule.js';
|
|
4
|
-
|
|
5
|
-
const SCHEDULE = Symbol('agent#schedule');
|
|
6
|
-
|
|
7
|
-
export default {
|
|
8
|
-
/**
|
|
9
|
-
* @member agent#ScheduleStrategy
|
|
10
|
-
*/
|
|
11
|
-
ScheduleStrategy: BaseStrategy,
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* @member agent#TimerScheduleStrategy
|
|
15
|
-
*/
|
|
16
|
-
TimerScheduleStrategy: TimerStrategy,
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @member agent#schedule
|
|
20
|
-
*/
|
|
21
|
-
get schedule() {
|
|
22
|
-
if (!this[SCHEDULE]) {
|
|
23
|
-
this[SCHEDULE] = new Schedule(this);
|
|
24
|
-
this.lifecycle.registerBeforeClose(() => {
|
|
25
|
-
return this[SCHEDULE].close();
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
return this[SCHEDULE];
|
|
29
|
-
},
|
|
30
|
-
} as any;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { ScheduleWorker } from '../../lib/schedule_worker.js';
|
|
2
|
-
|
|
3
|
-
const SCHEDULE_WORKER = Symbol('application#scheduleWorker');
|
|
4
|
-
|
|
5
|
-
export default {
|
|
6
|
-
/**
|
|
7
|
-
* @member app#schedule
|
|
8
|
-
*/
|
|
9
|
-
get scheduleWorker() {
|
|
10
|
-
if (!this[SCHEDULE_WORKER]) {
|
|
11
|
-
this[SCHEDULE_WORKER] = new ScheduleWorker(this);
|
|
12
|
-
}
|
|
13
|
-
return this[SCHEDULE_WORKER];
|
|
14
|
-
},
|
|
15
|
-
} as any;
|
|
16
|
-
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { debuglog } from 'node:util';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import { importResolve } from '@eggjs/utils';
|
|
4
|
-
import type { ScheduleWorker } from '../../lib/schedule_worker.js';
|
|
5
|
-
import type { EggScheduleItem } from '../../lib/types.js';
|
|
6
|
-
|
|
7
|
-
const debug = debuglog('@eggjs/schedule/app');
|
|
8
|
-
|
|
9
|
-
export default {
|
|
10
|
-
async runSchedule(schedulePath: string, ...args: any[]) {
|
|
11
|
-
debug('[runSchedule] start schedulePath: %o, args: %o', schedulePath, args);
|
|
12
|
-
// for test purpose
|
|
13
|
-
const config = this.config;
|
|
14
|
-
const directory = [
|
|
15
|
-
path.join(config.baseDir, 'app/schedule'),
|
|
16
|
-
...config.schedule.directory,
|
|
17
|
-
];
|
|
18
|
-
|
|
19
|
-
// resolve real path
|
|
20
|
-
if (path.isAbsolute(schedulePath)) {
|
|
21
|
-
schedulePath = importResolve(schedulePath);
|
|
22
|
-
} else {
|
|
23
|
-
for (const dir of directory) {
|
|
24
|
-
const trySchedulePath = path.join(dir, schedulePath);
|
|
25
|
-
try {
|
|
26
|
-
schedulePath = importResolve(trySchedulePath);
|
|
27
|
-
break;
|
|
28
|
-
} catch (err) {
|
|
29
|
-
debug('[runSchedule] importResolve %o error: %s', trySchedulePath, err);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
debug('[runSchedule] resolve schedulePath: %o', schedulePath);
|
|
35
|
-
const scheduleWorker: ScheduleWorker = this.scheduleWorker;
|
|
36
|
-
let schedule: EggScheduleItem;
|
|
37
|
-
try {
|
|
38
|
-
schedule = scheduleWorker.scheduleItems[schedulePath];
|
|
39
|
-
if (!schedule) {
|
|
40
|
-
throw new TypeError(`Cannot find schedule ${schedulePath}`);
|
|
41
|
-
}
|
|
42
|
-
} catch (err: any) {
|
|
43
|
-
err.message = `[@eggjs/schedule] ${err.message}`;
|
|
44
|
-
throw err;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// run with anonymous context
|
|
48
|
-
const ctx = this.createAnonymousContext({
|
|
49
|
-
method: 'SCHEDULE',
|
|
50
|
-
url: `/__schedule?path=${schedulePath}&${schedule.scheduleQueryString}`,
|
|
51
|
-
});
|
|
52
|
-
return await this.ctxStorage.run(ctx, async () => {
|
|
53
|
-
return await schedule.task(ctx, ...args);
|
|
54
|
-
});
|
|
55
|
-
},
|
|
56
|
-
} as any;
|
|
57
|
-
|
package/src/app.ts
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { debuglog } from 'node:util';
|
|
2
|
-
import type {
|
|
3
|
-
Application, ILifecycleBoot, EggLogger,
|
|
4
|
-
} from 'egg';
|
|
5
|
-
import type { EggScheduleJobInfo } from './lib/types.js';
|
|
6
|
-
|
|
7
|
-
const debug = debuglog('@eggjs/schedule/app');
|
|
8
|
-
|
|
9
|
-
export default class Boot implements ILifecycleBoot {
|
|
10
|
-
#app: Application;
|
|
11
|
-
#logger: EggLogger;
|
|
12
|
-
constructor(app: Application) {
|
|
13
|
-
this.#app = app;
|
|
14
|
-
this.#logger = app.getLogger('scheduleLogger');
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async configDidLoad(): Promise<void> {
|
|
18
|
-
const scheduleWorker = this.#app.scheduleWorker;
|
|
19
|
-
await scheduleWorker.init();
|
|
20
|
-
|
|
21
|
-
// log schedule list
|
|
22
|
-
for (const s in scheduleWorker.scheduleItems) {
|
|
23
|
-
const schedule = scheduleWorker.scheduleItems[s];
|
|
24
|
-
if (!schedule.schedule.disable) {
|
|
25
|
-
this.#logger.info('[@eggjs/schedule]: register schedule %s', schedule.key);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// register schedule event
|
|
30
|
-
this.#app.messenger.on('egg-schedule', async info => {
|
|
31
|
-
debug('app got "egg-schedule" message: %o', info);
|
|
32
|
-
const { id, key } = info;
|
|
33
|
-
this.#logger.debug(`[Job#${id}] ${key} await app ready`);
|
|
34
|
-
await this.#app.ready();
|
|
35
|
-
const schedule = scheduleWorker.scheduleItems[key];
|
|
36
|
-
this.#logger.debug(`[Job#${id}] ${key} task received by app`);
|
|
37
|
-
|
|
38
|
-
if (!schedule) {
|
|
39
|
-
this.#logger.warn(`[Job#${id}] ${key} unknown task`);
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/* istanbul ignore next */
|
|
44
|
-
if (schedule.schedule.disable) {
|
|
45
|
-
this.#logger.warn(`[Job#${id}] ${key} disable`);
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
this.#logger.info(`[Job#${id}] ${key} executing by app`);
|
|
50
|
-
|
|
51
|
-
// run with anonymous context
|
|
52
|
-
const ctx = this.#app.createAnonymousContext({
|
|
53
|
-
method: 'SCHEDULE',
|
|
54
|
-
url: `/__schedule?path=${key}&${schedule.scheduleQueryString}`,
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
const start = Date.now();
|
|
58
|
-
|
|
59
|
-
let success: boolean;
|
|
60
|
-
let e: Error | undefined;
|
|
61
|
-
try {
|
|
62
|
-
// execute
|
|
63
|
-
await this.#app.ctxStorage.run(ctx, async () => {
|
|
64
|
-
return await schedule.task(ctx, ...info.args);
|
|
65
|
-
});
|
|
66
|
-
success = true;
|
|
67
|
-
} catch (err: any) {
|
|
68
|
-
success = false;
|
|
69
|
-
e = err;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const rt = Date.now() - start;
|
|
73
|
-
|
|
74
|
-
const msg = `[Job#${id}] ${key} execute ${success ? 'succeed' : 'failed'}, used ${rt}ms.`;
|
|
75
|
-
if (success) {
|
|
76
|
-
this.#logger.info(msg);
|
|
77
|
-
} else {
|
|
78
|
-
this.#logger.error(msg, e);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// notify agent job finish
|
|
82
|
-
this.#app.messenger.sendToAgent('egg-schedule', {
|
|
83
|
-
...info,
|
|
84
|
-
success,
|
|
85
|
-
workerId: process.pid,
|
|
86
|
-
rt,
|
|
87
|
-
message: e?.message,
|
|
88
|
-
} as EggScheduleJobInfo);
|
|
89
|
-
});
|
|
90
|
-
debug('configDidLoad');
|
|
91
|
-
}
|
|
92
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export default () => {
|
|
2
|
-
const config = {} as Record<string, any>;
|
|
3
|
-
|
|
4
|
-
config.customLogger = {
|
|
5
|
-
scheduleLogger: {
|
|
6
|
-
consoleLevel: 'NONE',
|
|
7
|
-
file: 'egg-schedule.log',
|
|
8
|
-
},
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
config.schedule = {
|
|
12
|
-
// custom additional directory, full path
|
|
13
|
-
directory: [],
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
return config;
|
|
17
|
-
};
|
package/src/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './lib/types.js';
|
package/src/lib/load_schedule.ts
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import assert from 'node:assert';
|
|
3
|
-
import { stringify } from 'node:querystring';
|
|
4
|
-
import { isClass, isFunction, isGeneratorFunction } from 'is-type-of';
|
|
5
|
-
import { importResolve } from '@eggjs/utils';
|
|
6
|
-
import type { EggApplicationCore, EggContext } from 'egg';
|
|
7
|
-
import type { EggScheduleConfig, EggScheduleTask, EggScheduleItem } from './types.js';
|
|
8
|
-
|
|
9
|
-
function getScheduleLoader(app: EggApplicationCore) {
|
|
10
|
-
return class ScheduleLoader extends app.loader.FileLoader {
|
|
11
|
-
async load() {
|
|
12
|
-
const target = this.options.target as Record<string, EggScheduleItem>;
|
|
13
|
-
const items = await this.parse();
|
|
14
|
-
for (const item of items) {
|
|
15
|
-
const schedule = item.exports as { schedule: EggScheduleConfig, task: EggScheduleTask };
|
|
16
|
-
const fullpath = item.fullpath;
|
|
17
|
-
const scheduleConfig = schedule.schedule;
|
|
18
|
-
assert(scheduleConfig, `schedule(${fullpath}): must have "schedule" and "task" properties`);
|
|
19
|
-
assert(isClass(schedule) || isFunction(schedule.task),
|
|
20
|
-
`schedule(${fullpath}: \`schedule.task\` should be function or \`schedule\` should be class`);
|
|
21
|
-
|
|
22
|
-
let task: EggScheduleTask;
|
|
23
|
-
if (isClass(schedule)) {
|
|
24
|
-
assert(!isGeneratorFunction(schedule.prototype.subscribe),
|
|
25
|
-
`schedule(${fullpath}): "schedule" generator function is not support, should use async function instead`);
|
|
26
|
-
task = async (ctx: EggContext, ...args: any[]) => {
|
|
27
|
-
const instance = new schedule(ctx);
|
|
28
|
-
// s.subscribe = app.toAsyncFunction(s.subscribe);
|
|
29
|
-
return instance.subscribe(...args);
|
|
30
|
-
};
|
|
31
|
-
} else {
|
|
32
|
-
assert(!isGeneratorFunction(schedule.task),
|
|
33
|
-
`schedule(${fullpath}): "task" generator function is not support, should use async function instead`);
|
|
34
|
-
task = schedule.task;
|
|
35
|
-
// task = app.toAsyncFunction(schedule.task);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const env = app.config.env;
|
|
39
|
-
const envList = schedule.schedule.env;
|
|
40
|
-
if (Array.isArray(envList) && !envList.includes(env)) {
|
|
41
|
-
app.coreLogger.info(`[@eggjs/schedule]: ignore schedule ${fullpath} due to \`schedule.env\` not match`);
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// handle symlink case
|
|
46
|
-
const realFullpath = importResolve(fullpath);
|
|
47
|
-
target[realFullpath] = {
|
|
48
|
-
schedule: scheduleConfig,
|
|
49
|
-
scheduleQueryString: stringify(scheduleConfig as any),
|
|
50
|
-
task,
|
|
51
|
-
key: realFullpath,
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
return target;
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export async function loadSchedule(app: EggApplicationCore) {
|
|
60
|
-
const dirs = [
|
|
61
|
-
...app.loader.getLoadUnits().map(unit => path.join(unit.path, 'app/schedule')),
|
|
62
|
-
...app.config.schedule.directory,
|
|
63
|
-
];
|
|
64
|
-
|
|
65
|
-
const Loader = getScheduleLoader(app);
|
|
66
|
-
const schedules = {} as Record<string, EggScheduleItem>;
|
|
67
|
-
await new Loader({
|
|
68
|
-
directory: dirs,
|
|
69
|
-
target: schedules,
|
|
70
|
-
inject: app,
|
|
71
|
-
}).load();
|
|
72
|
-
Reflect.set(app, 'schedules', schedules);
|
|
73
|
-
return schedules;
|
|
74
|
-
}
|
package/src/lib/schedule.ts
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { debuglog } from 'node:util';
|
|
2
|
-
import type { Agent, EggLogger } from 'egg';
|
|
3
|
-
import { loadSchedule } from './load_schedule.js';
|
|
4
|
-
import type { EggScheduleItem, EggScheduleJobInfo } from './types.js';
|
|
5
|
-
import type { BaseStrategy } from './strategy/base.js';
|
|
6
|
-
|
|
7
|
-
const debug = debuglog('@eggjs/schedule/lib/schedule');
|
|
8
|
-
|
|
9
|
-
export class Schedule {
|
|
10
|
-
closed = false;
|
|
11
|
-
|
|
12
|
-
#agent: Agent;
|
|
13
|
-
#logger: EggLogger;
|
|
14
|
-
#strategyClassMap = new Map<string, typeof BaseStrategy>();
|
|
15
|
-
#strategyInstanceMap = new Map<string, BaseStrategy>();
|
|
16
|
-
|
|
17
|
-
constructor(agent: Agent) {
|
|
18
|
-
this.#agent = agent;
|
|
19
|
-
this.#logger = agent.getLogger('scheduleLogger');
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* register a custom Schedule Strategy
|
|
24
|
-
* @param {String} type - strategy type
|
|
25
|
-
* @param {Strategy} clz - Strategy class
|
|
26
|
-
*/
|
|
27
|
-
use(type: string, clz: typeof BaseStrategy) {
|
|
28
|
-
this.#strategyClassMap.set(type, clz);
|
|
29
|
-
debug('use type: %o', type);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* load all schedule jobs, then initialize and register speical strategy
|
|
34
|
-
*/
|
|
35
|
-
async init() {
|
|
36
|
-
const scheduleItems = await loadSchedule(this.#agent);
|
|
37
|
-
for (const scheduleItem of Object.values(scheduleItems)) {
|
|
38
|
-
this.registerSchedule(scheduleItem);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
registerSchedule(scheduleItem: EggScheduleItem) {
|
|
43
|
-
const { key, schedule } = scheduleItem;
|
|
44
|
-
const type = schedule.type;
|
|
45
|
-
if (schedule.disable) {
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// find Strategy by type
|
|
50
|
-
const Strategy = this.#strategyClassMap.get(type!);
|
|
51
|
-
if (!Strategy) {
|
|
52
|
-
const err = new Error(`schedule type [${type}] is not defined`);
|
|
53
|
-
err.name = 'EggScheduleError';
|
|
54
|
-
throw err;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Initialize strategy and register
|
|
58
|
-
const instance = new Strategy(schedule, this.#agent, key);
|
|
59
|
-
this.#strategyInstanceMap.set(key, instance);
|
|
60
|
-
debug('registerSchedule type: %o, config: %o, key: %o', type, schedule, key);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
unregisterSchedule(key: string) {
|
|
64
|
-
debug('unregisterSchedule key: %o', key);
|
|
65
|
-
return this.#strategyInstanceMap.delete(key);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* job finish event handler
|
|
70
|
-
*
|
|
71
|
-
* @param {Object} info - { id, key, success, message, workerId }
|
|
72
|
-
*/
|
|
73
|
-
onJobFinish(info: EggScheduleJobInfo) {
|
|
74
|
-
this.#logger.debug(`[Job#${info.id}] ${info.key} finish event received by agent from worker#${info.workerId}`);
|
|
75
|
-
const instance = this.#strategyInstanceMap.get(info.key);
|
|
76
|
-
/* istanbul ignore else */
|
|
77
|
-
if (instance) {
|
|
78
|
-
instance.onJobFinish(info);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* start schedule
|
|
84
|
-
*/
|
|
85
|
-
start() {
|
|
86
|
-
debug('start');
|
|
87
|
-
this.closed = false;
|
|
88
|
-
for (const instance of this.#strategyInstanceMap.values()) {
|
|
89
|
-
instance.start();
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
close() {
|
|
94
|
-
this.closed = true;
|
|
95
|
-
for (const instance of this.#strategyInstanceMap.values()) {
|
|
96
|
-
instance.close();
|
|
97
|
-
}
|
|
98
|
-
debug('close');
|
|
99
|
-
}
|
|
100
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { Application } from 'egg';
|
|
2
|
-
import { loadSchedule } from './load_schedule.js';
|
|
3
|
-
import type { EggScheduleItem } from './types.js';
|
|
4
|
-
|
|
5
|
-
export class ScheduleWorker {
|
|
6
|
-
#app: Application;
|
|
7
|
-
scheduleItems: Record<string, EggScheduleItem> = {};
|
|
8
|
-
|
|
9
|
-
constructor(app: Application) {
|
|
10
|
-
this.#app = app;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
async init() {
|
|
14
|
-
this.scheduleItems = await loadSchedule(this.#app);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
registerSchedule(scheduleItem: EggScheduleItem) {
|
|
18
|
-
this.scheduleItems[scheduleItem.key] = scheduleItem;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
unregisterSchedule(key: string) {
|
|
22
|
-
delete this.scheduleItems[key];
|
|
23
|
-
}
|
|
24
|
-
}
|