Skip to content

Commit

Permalink
feat: init midway-schedule
Browse files Browse the repository at this point in the history
  • Loading branch information
Lellansin committed Nov 7, 2018
1 parent 9a9eb3f commit 82cc9e1
Show file tree
Hide file tree
Showing 15 changed files with 376 additions and 2 deletions.
11 changes: 11 additions & 0 deletions packages/midway-schedule/agent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const wrapped = require('egg-schedule/agent');

module.exports = (agent) => {
if (!agent.loggers.scheduleLogger) {
agent.loggers.scheduleLogger = {
unredirect: () => {},
warn: console.warn,
};
}
wrapped(agent);
};
100 changes: 100 additions & 0 deletions packages/midway-schedule/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
'use strict';

import * as qs from 'querystring';
import * as path from 'path';
import loadSchedule from './lib/load_schedule';

module.exports = (app) => {
// don't redirect scheduleLogger
// app.loggers.scheduleLogger.unredirect('error');

const schedules = loadSchedule(app);

// for test purpose
app.runSchedule = (schedulePath) => {
if (!path.isAbsolute(schedulePath)) {
schedulePath = path.join(
app.config.baseDir,
'app/schedule',
schedulePath,
);
}
schedulePath = require.resolve(schedulePath);
let schedule;

try {
schedule = schedules[schedulePath];
if (!schedule) {
throw new Error(`Cannot find schedule ${schedulePath}`);
}
} catch (err) {
err.message = `[egg-schedule] ${err.message}`;
return Promise.reject(err);
}

// run with anonymous context
const ctx = app.createAnonymousContext({
method: 'SCHEDULE',
url: `/__schedule?path=${schedulePath}&${qs.stringify(
schedule.schedule,
)}`,
});

return schedule.task(ctx);
};

// log schedule list
for (const s in schedules) {
const schedule = schedules[s];
if (!schedule.schedule.disable)
app.coreLogger.info('[egg-schedule]: register schedule %s', schedule.key);
}

// register schedule event
app.messenger.on('egg-schedule', (data) => {
throw new Error('hahaha');
const id = data.id;
const key = data.key;
const schedule = schedules[key];
const logger = app.loggers.scheduleLogger;
logger.info(`[${id}] ${key} task received by app`);

if (!schedule) {
logger.warn(`[${id}] ${key} unknown task`);
return;
}
/* istanbul ignore next */
if (schedule.schedule.disable) return;

// run with anonymous context
const ctx = app.createAnonymousContext({
method: 'SCHEDULE',
url: `/__schedule?path=${key}&${qs.stringify(schedule.schedule)}`,
});

const start = Date.now();
const task = schedule.task;
logger.info(`[${id}] ${key} executing by app`);
console.log('hi ctx', ctx);
console.log('hi ctx.logger', ctx.logger);
// execute
task(ctx, ...data.args)
.then(() => true) // succeed
.catch((err) => {
logger.error(`[${id}] ${key} execute error.`, err);
err.message = `[egg-schedule] ${key} execute error. ${err.message}`;
app.logger.error(err);
return false; // failed
})
.then((success) => {
const rt = Date.now() - start;
const status = success ? 'succeed' : 'failed';
ctx.coreLogger.info(
`[egg-schedule] ${key} execute ${status}, used ${rt}ms`,
);
logger[success ? 'info' : 'error'](
`[${id}] ${key} execute ${status}, used ${rt}ms`,
);
});
});
};
1 change: 1 addition & 0 deletions packages/midway-schedule/app/extend/agent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('egg-schedule/app/extend/agent');
69 changes: 69 additions & 0 deletions packages/midway-schedule/lib/load_schedule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import 'reflect-metadata';
import * as assert from 'assert';
import * as is from 'is-type-of';
import { SCHEDULE_CLASS } from './metaKeys';

interface SchedueOpts {
interval: number;
type: string;
env?: string[];
}

export default (app) => {
const dirs = app.loader
.getLoadUnits()
.map((unit) => require('path').join(unit.path, 'lib/schedule'));
const Loader = getScheduleLoader(app);
const schedules = (app.schedules = {});
new Loader({
directory: dirs,
target: schedules,
inject: app,
}).load();
return schedules;
};

function getScheduleLoader(app) {
return class ScheduleLoader extends app.loader.FileLoader {
constructor(...args) {
super(...args);
}

load() {
const target = this.options.target;
const items = this.parse();
for (const item of items) {
const schedule = item.exports;
const fullpath = item.fullpath;

assert(is.class(schedule), `schedule(${fullpath}: should be class`);
const opts: SchedueOpts | string = Reflect.getMetadata(
SCHEDULE_CLASS,
schedule,
);
assert(opts, `schedule(${fullpath}): must use @schedule to setup.`);

const task = (ctx, data) => {
const ins = ctx.getAsync(schedule);
ins.exec = app.toAsyncFunction(ins.exec);
return ins.exec(data);
};

const env = app.config.env;
const envList = (opts as SchedueOpts).env;
if (is.array(envList) && !envList.includes(env)) {
app.coreLogger.info(
`[egg-schedule]: ignore schedule ${fullpath} due to \`schedule.env\` not match`,
);
continue;
}

target[fullpath] = {
schedule: opts,
task,
key: fullpath,
};
}
}
};
}
4 changes: 4 additions & 0 deletions packages/midway-schedule/lib/metaKeys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/**
* for @schedule
*/
export const SCHEDULE_CLASS = 'midway:schedule_class';
23 changes: 23 additions & 0 deletions packages/midway-schedule/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "midway-schedule",
"version": "0.1.1",
"description": "",
"main": "index.js",
"directories": {
"lib": "lib"
},
"eggPlugin": {
"name": "schedule"
},
"scripts": {
"lint": "../../node_modules/.bin/tslint --format prose -c ../../tslint.json src/**/*.ts test/**/*.ts",
"test": "npm run lint && midway-bin clean && NODE_ENV=test midway-bin test --ts"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"egg-schedule": "^3.4.0",
"reflect-metadata": "^0.1.12"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
'use strict';

exports.logrotator = true;
3 changes: 3 additions & 0 deletions packages/midway-schedule/test/fixtures/worker/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "worker"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
'use strict';

import { schedule } from '../../../../../../../midway/dist';
// import * as fs from 'fs';

@schedule({
type: 'worker',
interval: 200,
})
export default class IntervalCron {
async exec(ctx) {
throw new Error('hahaha');
// console.log(1234);
// ctx.logger.info('interval');
// ctx.app.coreLogger.info('hello world');
// fs.writeFileSync(
// require('path').join(__dirname, '../../logs/worker/hello.log'),
// 'hello world',
// );
}
}
94 changes: 94 additions & 0 deletions packages/midway-schedule/test/schedule.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
'use strict';

const { mm } = require('../../midway-mock/dist');
const path = require('path');
const fs = require('fs');
const assert = require('assert');

describe('test/schedule.test.js', () => {
let app;
// afterEach(() => app.close());

describe('schedule type worker', () => {
it('should support interval and cron', async () => {
app = mm.app({
baseDir: 'worker',
framework: path.join(__dirname, '../../midway'),
});
// app.debug();
await app.ready();
console.log(app.schedules);
});
});
});

function sleep(time) {
return new Promise((resolve) => {
setTimeout(resolve, time);
});
}

function getCoreLogContent(name) {
const logPath = path.join(
__dirname,
'fixtures',
name,
'logs',
name,
'egg-web.log',
);
return fs.readFileSync(logPath, 'utf8');
}

function getLogContent(name) {
const logPath = path.join(
__dirname,
'fixtures',
name,
'dist',
'logs',
name,
`midway-web.log`,
);
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) {
const logPath = path.join(
__dirname,
'fixtures',
name,
'logs',
name,
'egg-agent.log',
);
return fs.readFileSync(logPath, 'utf8');
}

function getScheduleLogContent(name) {
const logPath = path.join(
__dirname,
'fixtures',
name,
'logs',
name,
'egg-schedule.log',
);
return fs.readFileSync(logPath, 'utf8');
}

function contains(content, match) {
return content.split('\n').filter((line) => line.indexOf(match) >= 0).length;
}
21 changes: 21 additions & 0 deletions packages/midway-schedule/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"compilerOptions": {
"target": "ES2017",
"module": "commonjs",
"moduleResolution": "node",
"experimentalDecorators": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"stripInternal": true,
"pretty": true,
"declaration": true,
"outDir": "dist",
"lib": ["es2017", "dom"],
"sourceMap": true
},
"exclude": [
"dist",
"node_modules",
"test"
]
}
6 changes: 6 additions & 0 deletions packages/midway-web/config/plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
schedule: {
enable: true,
package: 'midway-schedule',
},
};
3 changes: 2 additions & 1 deletion packages/midway-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@
"inflection": "^1.12.0",
"injection": "^0.4.1",
"is-type-of": "^1.2.0",
"midway-core": "^0.4.4"
"midway-core": "^0.4.4",
"midway-schedule": "^0.1.0"
},
"author": "Harry Chen <czy88840616@gmail.com>",
"repository": {
Expand Down
Loading

0 comments on commit 82cc9e1

Please sign in to comment.