重构任务执行逻辑

This commit is contained in:
whyour
2022-05-15 20:40:29 +08:00
parent bb47d67d0b
commit 9dcc547ac7
7 changed files with 204 additions and 190 deletions
+75 -68
View File
@@ -1,13 +1,14 @@
import { Service, Inject } from 'typedi';
import winston from 'winston';
import nodeSchedule from 'node-schedule';
import { exec } from 'child_process';
import { ChildProcessWithoutNullStreams, exec, spawn } from 'child_process';
import {
ToadScheduler,
LongIntervalJob,
AsyncTask,
SimpleIntervalSchedule,
} from 'toad-scheduler';
import dayjs from 'dayjs';
interface ScheduleTaskType {
id: number;
@@ -16,6 +17,19 @@ interface ScheduleTaskType {
schedule?: string;
}
export interface TaskCallbacks {
onStart?: (
cp: ChildProcessWithoutNullStreams,
startTime: dayjs.Dayjs,
) => void;
onEnd?: (
cp: ChildProcessWithoutNullStreams,
endTime: dayjs.Dayjs,
diff: number,
) => void;
onError?: (message: string) => void;
}
@Service()
export default class ScheduleService {
private scheduleStacks = new Map<string, nodeSchedule.Job>();
@@ -26,12 +40,63 @@ export default class ScheduleService {
constructor(@Inject('logger') private logger: winston.Logger) {}
async createCronTask({
id = 0,
command,
name,
schedule = '',
}: ScheduleTaskType) {
async runTask(command: string, callbacks: TaskCallbacks = {}) {
return new Promise(async (resolve, reject) => {
try {
const startTime = dayjs();
const cp = spawn(command, { shell: '/bin/bash' });
callbacks.onStart?.(cp, startTime);
cp.stderr.on('data', (data) => {
this.logger.error(
'执行任务%s失败,时间:%s, 错误信息:%j',
command,
new Date().toLocaleString(),
data.toString(),
);
callbacks.onError?.(data.toString());
});
cp.on('error', (err) => {
this.logger.error(
'执行任务%s失败,时间:%s, 错误信息:%j',
command,
new Date().toLocaleString(),
err,
);
callbacks.onError?.(JSON.stringify(err));
});
cp.on('exit', async (code, signal) => {
this.logger.info(
`${command} pid: ${cp.pid} exit ${code} signal ${signal}`,
);
});
cp.on('close', async (code) => {
const endTime = dayjs();
this.logger.info(`${command} pid: ${cp.pid} closed ${code}`);
callbacks.onEnd?.(cp, endTime, endTime.diff(startTime, 'seconds'));
resolve(null);
});
} catch (error) {
await this.logger.error(
'执行任务%s失败,时间:%s, 错误信息:%j',
command,
new Date().toLocaleString(),
error,
);
callbacks.onError?.(JSON.stringify(error));
resolve(null);
}
});
}
async createCronTask(
{ id = 0, command, name, schedule = '' }: ScheduleTaskType,
callbacks?: TaskCallbacks,
) {
const _id = this.formatId(id);
this.logger.info(
'[创建cron任务],任务ID: %scron: %s,任务名: %s,执行命令: %s',
@@ -44,39 +109,7 @@ export default class ScheduleService {
this.scheduleStacks.set(
_id,
nodeSchedule.scheduleJob(_id, schedule, async () => {
try {
exec(
command,
{ maxBuffer: this.maxBuffer },
async (error, stdout, stderr) => {
if (error) {
await this.logger.error(
'执行任务%s失败,时间:%s, 错误信息:%j',
command,
new Date().toLocaleString(),
error,
);
}
if (stderr) {
await this.logger.error(
'执行任务%s失败,时间:%s, 错误信息:%j',
command,
new Date().toLocaleString(),
stderr,
);
}
},
);
} catch (error) {
await this.logger.error(
'执行任务%s失败,时间:%s, 错误信息:%j',
command,
new Date().toLocaleString(),
error,
);
} finally {
}
await this.runTask(command, callbacks);
}),
);
}
@@ -91,6 +124,7 @@ export default class ScheduleService {
{ id = 0, command, name = '' }: ScheduleTaskType,
schedule: SimpleIntervalSchedule,
runImmediately = true,
callbacks?: TaskCallbacks,
) {
const _id = this.formatId(id);
this.logger.info(
@@ -103,34 +137,7 @@ export default class ScheduleService {
name,
async () => {
return new Promise(async (resolve, reject) => {
try {
exec(
command,
{ maxBuffer: this.maxBuffer },
async (error, stdout, stderr) => {
if (error) {
await this.logger.error(
'执行任务%s失败,时间:%s, 错误信息:%j',
command,
new Date().toLocaleString(),
error,
);
}
if (stderr) {
await this.logger.error(
'执行任务%s失败,时间:%s, 错误信息:%j',
command,
new Date().toLocaleString(),
stderr,
);
}
resolve();
},
);
} catch (error) {
reject(error);
}
await this.runTask(command, callbacks);
});
},
(err) => {