Skip to content

Commit

Permalink
refactor: impl Application and Agent extend with Class (#65)
Browse files Browse the repository at this point in the history
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

- **New Features**
- Introduced new lifecycle method `beforeClose` to manage application
shutdown.
- Enhanced asynchronous handling in various classes, including
`Schedule`, `BaseStrategy`, and `TimerStrategy`.

- **Bug Fixes**
- Corrected documentation in the `init` method of the `Schedule` class.

- **Refactor**
- Updated class structures to use explicit class declarations instead of
object exports.
- Streamlined property access in several classes by transitioning to
getter methods.

- **Chores**
- Updated import paths for `Agent` and `Application` types across
multiple files.
  - Expanded exports in `src/index.ts` to include new modules.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • Loading branch information
fengmk2 authored Dec 20, 2024
1 parent af99159 commit 091c8d6
Show file tree
Hide file tree
Showing 11 changed files with 61 additions and 64 deletions.
11 changes: 9 additions & 2 deletions src/agent.ts
Original file line number Diff line number Diff line change
@@ -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');

Expand Down Expand Up @@ -30,7 +31,13 @@ export default class Boot implements ILifecycleBoot {

async serverDidReady(): Promise<void> {
// start schedule after worker ready
this.#agent.schedule.start();
await this.#agent.schedule.start();
debug('serverDidReady, schedule start');
}

async beforeClose(): Promise<void> {
// stop schedule before app close
await this.#agent.schedule.close();
debug('beforeClose, schedule close');
}
}
3 changes: 2 additions & 1 deletion src/app.ts
Original file line number Diff line number Diff line change
@@ -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');

Expand Down
27 changes: 15 additions & 12 deletions src/app/extend/agent.ts
Original file line number Diff line number Diff line change
@@ -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;
}
}
16 changes: 9 additions & 7 deletions src/app/extend/application.ts
Original file line number Diff line number Diff line change
@@ -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;
}
}

11 changes: 5 additions & 6 deletions src/app/extend/application.unittest.ts
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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}`);
}
Expand All @@ -52,6 +51,6 @@ export default {
return await this.ctxStorage.run(ctx, async () => {
return await schedule.task(ctx, ...args);
});
},
} as any;
}
}

8 changes: 8 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -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';
11 changes: 6 additions & 5 deletions src/lib/schedule.ts
Original file line number Diff line number Diff line change
@@ -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');

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -82,18 +83,18 @@ export class Schedule {
/**
* start schedule
*/
start() {
async start() {
debug('start');
this.closed = false;
for (const instance of this.#strategyInstanceMap.values()) {
instance.start();
}
}

close() {
async close() {
this.closed = true;
for (const instance of this.#strategyInstanceMap.values()) {
instance.close();
await instance.close();
}
debug('close');
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/schedule_worker.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
7 changes: 4 additions & 3 deletions src/lib/strategy/base.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -21,11 +22,11 @@ export class BaseStrategy {
return this.scheduleConfig;
}

start() {
async start() {
// empty loop by default
}

close() {
async close() {
this.closed = true;
}

Expand Down
5 changes: 2 additions & 3 deletions src/lib/strategy/timer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down
24 changes: 0 additions & 24 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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<void>;
}
export interface Application extends EggScheduleApplication {}

export interface EggScheduleAppConfig {
schedule: {
directory: string[];
};
}

export interface EggAppConfig extends EggScheduleAppConfig {}
}

0 comments on commit 091c8d6

Please sign in to comment.