diff --git a/src/agent.ts b/src/agent.ts index f151241..3b7ed9f 100644 --- a/src/agent.ts +++ b/src/agent.ts @@ -1,8 +1,9 @@ import { debuglog } from 'node:util'; -import type { Agent, ILifecycleBoot } from 'egg'; +import type { ILifecycleBoot } from 'egg'; import { WorkerStrategy } from './lib/strategy/worker.js'; import { AllStrategy } from './lib/strategy/all.js'; import { EggScheduleJobInfo } from './lib/types.js'; +import type Agent from './app/extend/agent.js'; const debug = debuglog('@eggjs/schedule/agent'); @@ -30,7 +31,13 @@ export default class Boot implements ILifecycleBoot { async serverDidReady(): Promise { // start schedule after worker ready - this.#agent.schedule.start(); + await this.#agent.schedule.start(); debug('serverDidReady, schedule start'); } + + async beforeClose(): Promise { + // stop schedule before app close + await this.#agent.schedule.close(); + debug('beforeClose, schedule close'); + } } diff --git a/src/app.ts b/src/app.ts index 8912897..337d36b 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,8 +1,9 @@ import { debuglog } from 'node:util'; import type { - Application, ILifecycleBoot, EggLogger, + ILifecycleBoot, EggLogger, } from 'egg'; import type { EggScheduleJobInfo } from './lib/types.js'; +import type Application from './app/extend/application.js'; const debug = debuglog('@eggjs/schedule/app'); diff --git a/src/app/extend/agent.ts b/src/app/extend/agent.ts index 81dd508..4c14902 100644 --- a/src/app/extend/agent.ts +++ b/src/app/extend/agent.ts @@ -1,30 +1,33 @@ +import { Agent as EggAgent } from 'egg'; import { BaseStrategy } from '../../lib/strategy/base.js'; import { TimerStrategy } from '../../lib/strategy/timer.js'; import { Schedule } from '../../lib/schedule.js'; -const SCHEDULE = Symbol('agent#schedule'); +const SCHEDULE = Symbol('agent schedule'); -export default { +export default class Agent extends EggAgent { /** * @member agent#ScheduleStrategy */ - ScheduleStrategy: BaseStrategy, + get ScheduleStrategy() { + return BaseStrategy; + } /** * @member agent#TimerScheduleStrategy */ - TimerScheduleStrategy: TimerStrategy, + get TimerScheduleStrategy() { + return TimerStrategy; + } /** * @member agent#schedule */ get schedule() { - if (!this[SCHEDULE]) { - this[SCHEDULE] = new Schedule(this); - this.lifecycle.registerBeforeClose(() => { - return this[SCHEDULE].close(); - }); + let schedule = this[SCHEDULE] as Schedule; + if (!schedule) { + this[SCHEDULE] = schedule = new Schedule(this); } - return this[SCHEDULE]; - }, -} as any; + return schedule; + } +} diff --git a/src/app/extend/application.ts b/src/app/extend/application.ts index 0003596..87cd72b 100644 --- a/src/app/extend/application.ts +++ b/src/app/extend/application.ts @@ -1,16 +1,18 @@ +import { Application as EggApplication } from 'egg'; import { ScheduleWorker } from '../../lib/schedule_worker.js'; -const SCHEDULE_WORKER = Symbol('application#scheduleWorker'); +const SCHEDULE_WORKER = Symbol('application scheduleWorker'); -export default { +export default class Application extends EggApplication { /** * @member app#schedule */ get scheduleWorker() { - if (!this[SCHEDULE_WORKER]) { - this[SCHEDULE_WORKER] = new ScheduleWorker(this); + let scheduleWorker = this[SCHEDULE_WORKER] as ScheduleWorker; + if (!scheduleWorker) { + this[SCHEDULE_WORKER] = scheduleWorker = new ScheduleWorker(this); } - return this[SCHEDULE_WORKER]; - }, -} as any; + return scheduleWorker; + } +} diff --git a/src/app/extend/application.unittest.ts b/src/app/extend/application.unittest.ts index ca6604c..85a535e 100644 --- a/src/app/extend/application.unittest.ts +++ b/src/app/extend/application.unittest.ts @@ -1,12 +1,12 @@ import { debuglog } from 'node:util'; import path from 'node:path'; import { importResolve } from '@eggjs/utils'; -import type { ScheduleWorker } from '../../lib/schedule_worker.js'; import type { EggScheduleItem } from '../../lib/types.js'; +import Application from './application.js'; const debug = debuglog('@eggjs/schedule/app'); -export default { +export default class ApplicationUnittest extends Application { async runSchedule(schedulePath: string, ...args: any[]) { debug('[runSchedule] start schedulePath: %o, args: %o', schedulePath, args); // for test purpose @@ -32,10 +32,9 @@ export default { } debug('[runSchedule] resolve schedulePath: %o', schedulePath); - const scheduleWorker: ScheduleWorker = this.scheduleWorker; let schedule: EggScheduleItem; try { - schedule = scheduleWorker.scheduleItems[schedulePath]; + schedule = this.scheduleWorker.scheduleItems[schedulePath]; if (!schedule) { throw new TypeError(`Cannot find schedule ${schedulePath}`); } @@ -52,6 +51,6 @@ export default { return await this.ctxStorage.run(ctx, async () => { return await schedule.task(ctx, ...args); }); - }, -} as any; + } +} diff --git a/src/index.ts b/src/index.ts index f6ebe91..d6bd499 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1 +1,9 @@ +import Agent from './app/extend/agent.js'; +import Application from './app/extend/application.js'; +import ApplicationUnittest from './app/extend/application.unittest.js'; + +export { Agent, Application, ApplicationUnittest }; +export { ScheduleWorker } from './lib/schedule_worker.js'; +export { Schedule } from './lib/schedule.js'; + export * from './lib/types.js'; diff --git a/src/lib/schedule.ts b/src/lib/schedule.ts index 3c28d18..0628762 100644 --- a/src/lib/schedule.ts +++ b/src/lib/schedule.ts @@ -1,8 +1,9 @@ import { debuglog } from 'node:util'; -import type { Agent, EggLogger } from 'egg'; +import type { EggLogger } from 'egg'; import { loadSchedule } from './load_schedule.js'; import type { EggScheduleItem, EggScheduleJobInfo } from './types.js'; import type { BaseStrategy } from './strategy/base.js'; +import type Agent from '../app/extend/agent.js'; const debug = debuglog('@eggjs/schedule/lib/schedule'); @@ -30,7 +31,7 @@ export class Schedule { } /** - * load all schedule jobs, then initialize and register speical strategy + * load all schedule jobs, then initialize and register special strategy */ async init() { const scheduleItems = await loadSchedule(this.#agent); @@ -82,7 +83,7 @@ export class Schedule { /** * start schedule */ - start() { + async start() { debug('start'); this.closed = false; for (const instance of this.#strategyInstanceMap.values()) { @@ -90,10 +91,10 @@ export class Schedule { } } - close() { + async close() { this.closed = true; for (const instance of this.#strategyInstanceMap.values()) { - instance.close(); + await instance.close(); } debug('close'); } diff --git a/src/lib/schedule_worker.ts b/src/lib/schedule_worker.ts index 415ea20..3467262 100644 --- a/src/lib/schedule_worker.ts +++ b/src/lib/schedule_worker.ts @@ -1,6 +1,6 @@ -import type { Application } from 'egg'; import { loadSchedule } from './load_schedule.js'; import type { EggScheduleItem } from './types.js'; +import type Application from '../app/extend/application.js'; export class ScheduleWorker { #app: Application; diff --git a/src/lib/strategy/base.ts b/src/lib/strategy/base.ts index 8b83834..3e70541 100644 --- a/src/lib/strategy/base.ts +++ b/src/lib/strategy/base.ts @@ -1,5 +1,6 @@ -import type { Agent, EggLogger } from 'egg'; +import type { EggLogger } from 'egg'; import type { EggScheduleConfig, EggScheduleJobInfo } from '../types.js'; +import type Agent from '../../app/extend/agent.js'; export class BaseStrategy { protected agent: Agent; @@ -21,11 +22,11 @@ export class BaseStrategy { return this.scheduleConfig; } - start() { + async start() { // empty loop by default } - close() { + async close() { this.closed = true; } diff --git a/src/lib/strategy/timer.ts b/src/lib/strategy/timer.ts index 99b024d..7114a82 100644 --- a/src/lib/strategy/timer.ts +++ b/src/lib/strategy/timer.ts @@ -4,9 +4,9 @@ import cronParser from 'cron-parser'; import { ms } from 'humanize-ms'; import safeTimers from 'safe-timers'; import { logDate } from 'utility'; -import type { Agent } from 'egg'; import type { EggScheduleConfig } from '../types.js'; import { BaseStrategy } from './base.js'; +import type Agent from '../../app/extend/agent.js'; export abstract class TimerStrategy extends BaseStrategy { protected cronInstance?: CronExpression; @@ -34,8 +34,7 @@ export abstract class TimerStrategy extends BaseStrategy { throw new TypeError(`[@eggjs/schedule] ${this.key} strategy should override \`handler()\` method`); } - - start() { + async start() { /* istanbul ignore next */ if (this.agent.schedule.closed) return; diff --git a/src/lib/types.ts b/src/lib/types.ts index 36d8e38..d2eb19c 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -1,6 +1,4 @@ import type { ParserOptions as CronOptions } from 'cron-parser'; -import type { Schedule } from './schedule.js'; -import type { ScheduleWorker } from './schedule_worker.js'; /** * Schedule Config @@ -34,25 +32,3 @@ export interface EggScheduleJobInfo { message?: string; rt?: number; } - -declare module 'egg' { - export interface EggScheduleAgent { - schedule: Schedule; - } - export interface Agent extends EggScheduleAgent {} - - export interface EggScheduleApplication { - scheduleWorker: ScheduleWorker; - /** runSchedule in unittest */ - runSchedule: (schedulePath: string, ...args: any[]) => Promise; - } - export interface Application extends EggScheduleApplication {} - - export interface EggScheduleAppConfig { - schedule: { - directory: string[]; - }; - } - - export interface EggAppConfig extends EggScheduleAppConfig {} -}