From 7208139816fddc0bcb7a142ed928581e30cf3bc3 Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Tue, 17 Dec 2024 15:24:32 +0800 Subject: [PATCH] fix test --- .github/workflows/nodejs.yml | 2 + README.md | 3 +- package.json | 14 ++++-- src/agent.ts | 4 ++ src/app.ts | 5 ++ src/app/extend/agent.ts | 2 +- src/lib/load_schedule.ts | 2 +- src/lib/strategy/base.ts | 11 +++-- test/fixtures/customType/agent.js | 20 ++++---- test/fixtures/customTypeWithoutStart/agent.js | 2 - test/fixtures/plugin/config/config.default.js | 3 ++ test/fixtures/worker/app/schedule/interval.js | 2 - test/fixtures/worker/app/schedule/sub/cron.js | 2 - test/fixtures/worker/config/config.default.js | 8 ++++ test/fixtures/worker/config/plugin.js | 12 ++++- test/schedule.test.ts | 46 +++++++++---------- 16 files changed, 86 insertions(+), 52 deletions(-) create mode 100644 test/fixtures/plugin/config/config.default.js create mode 100644 test/fixtures/worker/config/config.default.js diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index dc5563d..5a2a289 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -13,3 +13,5 @@ jobs: with: os: 'ubuntu-latest' version: '18, 20, 22' + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/README.md b/README.md index b680ed9..37ee3d2 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,13 @@ [![Test coverage][codecov-image]][codecov-url] [![Known Vulnerabilities][snyk-image]][snyk-url] [![npm download][download-image]][download-url] +[![Node.js Version](https://img.shields.io/node/v/@eggjs/schedule.svg?style=flat)](https://nodejs.org/en/download/) [npm-image]: https://img.shields.io/npm/v/@eggjs/schedule.svg?style=flat-square [npm-url]: https://npmjs.org/package/@eggjs/schedule [codecov-image]: https://codecov.io/github/eggjs/egg-schedule/coverage.svg?branch=master [codecov-url]: https://codecov.io/github/eggjs/egg-schedule?branch=master -[snyk-image]: https://snyk.io/test/npm/egg-schedule/badge.svg?style=flat-square +[snyk-image]: https://snyk.io/test/npm/@eggjs/schedule/badge.svg?style=flat-square [snyk-url]: https://snyk.io/test/npm/@eggjs/schedule [download-image]: https://img.shields.io/npm/dm/@eggjs/schedule.svg?style=flat-square [download-url]: https://npmjs.org/package/@eggjs/schedule diff --git a/package.json b/package.json index f2c6f38..939ab6d 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,11 @@ }, "description": "schedule plugin for egg, support corn job.", "eggPlugin": { - "name": "schedule" + "name": "schedule", + "exports": { + "import": "./dist/esm", + "require": "./dist/commonjs" + } }, "repository": { "type": "git", @@ -34,7 +38,7 @@ "@types/safe-timers": "^1.1.2", "egg": "beta", "egg-bin": "6", - "egg-mock": "^5.15.1", + "egg-mock": "beta", "egg-tracer": "2", "eslint": "8", "eslint-config-egg": "14", @@ -44,8 +48,10 @@ }, "scripts": { "lint": "eslint --cache src test --ext .ts", - "test": "npm run lint -- --fix && egg-bin test", - "ci": "npm run lint && egg-bin cov && npm run prepublishOnly && attw --pack", + "pretest": "npm run lint -- --fix && npm run prepublishOnly", + "test": "egg-bin test", + "preci": "npm run lint && npm run prepublishOnly", + "ci": "egg-bin cov && attw --pack", "prepublishOnly": "tshy && tshy-after" }, "author": "dead_horse", diff --git a/src/agent.ts b/src/agent.ts index f561da2..a3e01e3 100644 --- a/src/agent.ts +++ b/src/agent.ts @@ -1,8 +1,11 @@ +import { debuglog } from 'node:util'; import type { Agent, ILifecycleBoot } from 'egg'; import { WorkerStrategy } from './lib/strategy/worker.js'; import { AllStrategy } from './lib/strategy/all.js'; import { ScheduleJobInfo } from './lib/types.js'; +const debug = debuglog('@eggjs/schedule/agent'); + export default class Boot implements ILifecycleBoot { #agent: Agent; constructor(agent: Agent) { @@ -26,6 +29,7 @@ export default class Boot implements ILifecycleBoot { this.#agent.messenger.once('egg-ready', () => { // start schedule after worker ready this.#agent.schedule.start(); + debug('got egg-ready event, schedule start'); }); } } diff --git a/src/app.ts b/src/app.ts index 2ef8c66..d2a3c77 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,9 +1,12 @@ +import { debuglog } from 'node:util'; import path from 'node:path'; import type { Application, ILifecycleBoot, EggLogger, } from 'egg'; import { ScheduleItem, ScheduleJobInfo } from './lib/types.js'; +const debug = debuglog('@eggjs/schedule/app'); + export default class Boot implements ILifecycleBoot { #app: Application; #logger: EggLogger; @@ -13,6 +16,7 @@ export default class Boot implements ILifecycleBoot { } async didLoad(): Promise { + debug('didLoad'); const scheduleWorker = this.#app.scheduleWorker; await scheduleWorker.init(); @@ -26,6 +30,7 @@ export default class Boot implements ILifecycleBoot { // register schedule event this.#app.messenger.on('egg-schedule', async info => { + debug('app got "egg-schedule" message: %o', info); const { id, key } = info; this.#logger.debug(`[Job#${id}] ${key} await app ready`); await this.#app.ready(); diff --git a/src/app/extend/agent.ts b/src/app/extend/agent.ts index e519689..81dd508 100644 --- a/src/app/extend/agent.ts +++ b/src/app/extend/agent.ts @@ -21,7 +21,7 @@ export default { get schedule() { if (!this[SCHEDULE]) { this[SCHEDULE] = new Schedule(this); - this.beforeClose(() => { + this.lifecycle.registerBeforeClose(() => { return this[SCHEDULE].close(); }); } diff --git a/src/lib/load_schedule.ts b/src/lib/load_schedule.ts index 0f011f6..160515d 100644 --- a/src/lib/load_schedule.ts +++ b/src/lib/load_schedule.ts @@ -53,7 +53,7 @@ function getScheduleLoader(app: EggApplicationCore) { export async function loadSchedule(app: EggApplicationCore) { const dirs = [ - app.loader.getLoadUnits().map(unit => path.join(unit.path, 'app/schedule')), + ...app.loader.getLoadUnits().map(unit => path.join(unit.path, 'app/schedule')), ...app.config.schedule.directory, ]; diff --git a/src/lib/strategy/base.ts b/src/lib/strategy/base.ts index 19b5832..5b48b23 100644 --- a/src/lib/strategy/base.ts +++ b/src/lib/strategy/base.ts @@ -16,8 +16,13 @@ export class BaseStrategy { this.logger = this.agent.getLogger('scheduleLogger'); } + /** keep compatibility */ + get schedule(): ScheduleConfig { + return this.scheduleConfig; + } + start() { - throw new TypeError(`[egg-schedule] ${this.key} strategy should override \`start()\` method`); + // empty loop by default } close() { @@ -50,7 +55,7 @@ export class BaseStrategy { args, } as ScheduleJobInfo; - this.logger.debug(`[Job#${info.id}] ${info.key} triggered, send random by agent`); + this.logger.info(`[Job#${info.id}] ${info.key} triggered, send random by agent`); this.agent.messenger.sendRandom('egg-schedule', info); this.onJobStart(info); } @@ -74,7 +79,7 @@ export class BaseStrategy { id: this.getSeqId(), args, } as ScheduleJobInfo; - this.logger.debug(`[Job#${info.id}] ${info.key} triggered, send all by agent`); + this.logger.info(`[Job#${info.id}] ${info.key} triggered, send all by agent`); // send to all workers this.agent.messenger.send('egg-schedule', info); this.onJobStart(info); diff --git a/test/fixtures/customType/agent.js b/test/fixtures/customType/agent.js index 73e8604..49a5025 100644 --- a/test/fixtures/customType/agent.js +++ b/test/fixtures/customType/agent.js @@ -1,12 +1,12 @@ -'use strict'; - -module.exports = function(agent) { - class ClusterStrategy extends agent.ScheduleStrategy { - start() { - this.interval = setInterval(() => { - this.sendOne(); - }, this.schedule.interval); +module.exports = class Boot { + constructor(agent) { + class ClusterStrategy extends agent.ScheduleStrategy { + start() { + this.interval = setInterval(() => { + this.sendOne(); + }, this.schedule.interval); + } } + agent.schedule.use('cluster', ClusterStrategy); } - agent.schedule.use('cluster', ClusterStrategy); -}; +} diff --git a/test/fixtures/customTypeWithoutStart/agent.js b/test/fixtures/customTypeWithoutStart/agent.js index 316b287..ce87a08 100644 --- a/test/fixtures/customTypeWithoutStart/agent.js +++ b/test/fixtures/customTypeWithoutStart/agent.js @@ -1,5 +1,3 @@ -'use strict'; - module.exports = function(agent) { class ClusterStrategy extends agent.ScheduleStrategy { constructor(...args) { diff --git a/test/fixtures/plugin/config/config.default.js b/test/fixtures/plugin/config/config.default.js new file mode 100644 index 0000000..fbd44f6 --- /dev/null +++ b/test/fixtures/plugin/config/config.default.js @@ -0,0 +1,3 @@ +exports.logger = { + level: 'debug', +}; diff --git a/test/fixtures/worker/app/schedule/interval.js b/test/fixtures/worker/app/schedule/interval.js index 2157971..29efc16 100644 --- a/test/fixtures/worker/app/schedule/interval.js +++ b/test/fixtures/worker/app/schedule/interval.js @@ -1,5 +1,3 @@ -'use strict'; - exports.schedule = { type: 'worker', interval: '4s', diff --git a/test/fixtures/worker/app/schedule/sub/cron.js b/test/fixtures/worker/app/schedule/sub/cron.js index 282d36b..6b3df7b 100644 --- a/test/fixtures/worker/app/schedule/sub/cron.js +++ b/test/fixtures/worker/app/schedule/sub/cron.js @@ -1,5 +1,3 @@ -'use strict'; - exports.schedule = { type: 'worker', cron: '*/5 * * * * *', diff --git a/test/fixtures/worker/config/config.default.js b/test/fixtures/worker/config/config.default.js new file mode 100644 index 0000000..8b3e0dd --- /dev/null +++ b/test/fixtures/worker/config/config.default.js @@ -0,0 +1,8 @@ +exports.logger = { + level: 'DEBUG', + consoleLevel: 'DEBUG', + coreLogger: { + level: 'DEBUG', + consoleLevel: 'DEBUG', + }, +}; diff --git a/test/fixtures/worker/config/plugin.js b/test/fixtures/worker/config/plugin.js index e54d182..08a0b9c 100644 --- a/test/fixtures/worker/config/plugin.js +++ b/test/fixtures/worker/config/plugin.js @@ -1,3 +1,11 @@ -'use strict'; - exports.logrotator = true; +exports.onerror = false; +exports.session = false; +exports.i18n = false; +exports.watcher = false; +exports.multipart = false; +exports.security = false; +exports.development = false; +exports.static = false; +exports.jsonp = false; +exports.view = false; diff --git a/test/schedule.test.ts b/test/schedule.test.ts index 34630de..d343a4e 100644 --- a/test/schedule.test.ts +++ b/test/schedule.test.ts @@ -1,11 +1,13 @@ import { strict as assert } from 'node:assert'; import path from 'node:path'; import fs from 'node:fs'; +import { fileURLToPath } from 'node:url'; import { setTimeout as sleep } from 'node:timers/promises'; import { MockApplication } from 'egg-mock'; -import _mm from 'egg-mock'; +import { mm } from 'egg-mock'; -const mm = _mm.default; +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); describe('test/schedule.test.ts', () => { let app: MockApplication; @@ -14,19 +16,20 @@ describe('test/schedule.test.ts', () => { describe('schedule type worker', () => { it.only('should support interval and cron', async () => { app = mm.cluster({ baseDir: 'worker', workers: 2, cache: false }); - // app.debug(); + app.debug(); await app.ready(); await sleep(5000); const log = getLogContent('worker'); - // console.log(log); - assert(contains(log, 'interval') === 1); - assert(contains(log, 'cron') === 1); + console.log(log); + assert.equal(contains(log, 'interval'), 1); + assert.equal(contains(log, 'cron'), 1); const scheduleLog = getScheduleLogContent('worker'); - assert(contains(scheduleLog, 'cron.js executing by app') === 1); - assert(contains(scheduleLog, 'cron.js execute succeed') === 1); - assert(contains(scheduleLog, 'interval.js executing by app') === 1); - assert(contains(scheduleLog, 'interval.js execute succeed') === 1); + console.log(scheduleLog); + assert.equal(contains(scheduleLog, 'cron.js executing by app'), 1); + assert.equal(contains(scheduleLog, 'cron.js execute succeed'), 1); + assert.equal(contains(scheduleLog, 'interval.js executing by app'), 1); + assert.equal(contains(scheduleLog, 'interval.js execute succeed'), 1); }); it('should support ctxStorage', async () => { @@ -177,7 +180,7 @@ describe('test/schedule.test.ts', () => { await sleep(5000); const log = getLogContent('customTypeWithoutStart'); // console.log(log); - assert(contains(log, 'cluster_log') === 1); + assert.equal(contains(log, 'cluster_log'), 1); }); it('should handler error', async () => { @@ -185,8 +188,8 @@ describe('test/schedule.test.ts', () => { // app.debug(); await app.ready(); await sleep(1000); - // app.expect('code', 1); - // app.expect('stderr', /should provide clusterId/); + app.expect('code', 1); + app.expect('stderr', /should provide clusterId/); }); }); @@ -196,7 +199,7 @@ describe('test/schedule.test.ts', () => { // app.debug(); await app.ready(); await sleep(3000); - // app.expect('stderr', /schedule\.interval or schedule\.cron or schedule\.immediate must be present/); + app.expect('stderr', /schedule\.interval or schedule\.cron or schedule\.immediate must be present/); }); }); @@ -205,7 +208,7 @@ describe('test/schedule.test.ts', () => { app = mm.cluster({ baseDir: 'typeUndefined', workers: 2 }); await app.ready(); await sleep(3000); - // app.expect('stderr', /schedule type \[undefined\] is not defined/); + app.expect('stderr', /schedule type \[undefined\] is not defined/); }); }); @@ -215,7 +218,7 @@ describe('test/schedule.test.ts', () => { // app.debug(); await app.ready(); await sleep(1000); - // app.expect('stderr', /parse cron instruction\(invalid instruction\) error/); + app.expect('stderr', /parse cron instruction\(invalid instruction\) error/); }); }); @@ -257,7 +260,7 @@ describe('test/schedule.test.ts', () => { interval: 4000, }, }; - // app.agent.schedule.registerSchedule(schedule); + (app as any).agent.schedule.registerSchedule(schedule); app.scheduleWorker.registerSchedule(schedule as any); await app.runSchedule(key); @@ -282,10 +285,10 @@ describe('test/schedule.test.ts', () => { interval: 4000, }, }; - // app.agent.schedule.registerSchedule(schedule); + (app as any).agent.schedule.registerSchedule(schedule); app.scheduleWorker.registerSchedule(schedule as any); - // app.agent.schedule.unregisterSchedule(schedule.key); + (app as any).agent.schedule.unregisterSchedule(schedule.key); app.scheduleWorker.unregisterSchedule(schedule.key); let err: any; @@ -575,11 +578,6 @@ function getLogContent(name: string) { return fs.readFileSync(logPath, 'utf8'); } -// function getErrorLogContent(name) { -// const logPath = path.join(__dirname, 'fixtures', name, 'logs', name, 'common-error.log'); -// return fs.readFileSync(logPath, 'utf8'); -// } - function getAgentLogContent(name: string) { const logPath = path.join(__dirname, 'fixtures', name, 'logs', name, 'egg-agent.log'); return fs.readFileSync(logPath, 'utf8');