index.ts
3.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/**
* XXL-JOB 执行器配置项
*/
interface XxlJobConfig {
/** 执行器唯一标识(建议开发环境用不同名称避免冲突) */
executorKey: string;
/** 调度中心地址 */
scheduleCenterUrl?: string;
/** 认证令牌 */
accessToken?: string;
/** 任务日志存储路径 */
jobLogPath?: string;
/** 是否启用调试日志 */
enableDebugLog?: boolean;
}
/**
* 执行器全局配置
*/
interface JobExecutorOptions {
/** Express/Koa 'express' | 'koa' */
appType: string;
/** 应用对外访问的域名(用于回调) */
appDomain: string;
/** 应用监听端口 */
port: number;
/** XXL-JOB 核心配置 */
xxlJob: XxlJobConfig;
/** frpc 配置文件路径(可选) */
frpcConfigPath?: string;
}
/**
* XXL-JOB 任务执行器
* 1. 注册任务处理器
* 2. 启动 HTTP 服务
* 3. 可选启动 frpc 内网穿透
*/
export class JobExecutor {
private jobHandlers = new Map<string, Function>();
constructor(opts: JobExecutorOptions) {
// 初始化 frpc 内网穿透(如果配置存在)
if (opts.frpcConfigPath) {
require("./xxl-job/frpc").createFrpc(opts.frpcConfigPath);
}
// 连接 XXL-JOB 调度中心
const app = new (require("./xxl-job/index").XxlJobExecutor)(
opts.xxlJob,
this.jobHandlers
).applyMiddleware({
appType: opts.appType,
domain: opts.appDomain
});
// 启动 HTTP 服务
app.listen(opts.port, () => {
console.log(`[XXL-JOB] Executor ${opts.appType} "${opts.xxlJob.executorKey}" is running`);
console.log(`- Local: http://localhost:${opts.port}`);
console.log(`- Public: ${opts.appDomain}`);
});
}
/**
* 注册任务
* @param jobName 任务名称(需与调度中心配置一致)
* @param handler 任务处理函数,需返回 Promise
* @throws 如果任务已注册或 handler 不是函数
*/
public register(jobName: string, handler: Function) {
if (this.jobHandlers.has(jobName)) {
throw new Error(`Job handler "${jobName}" is already registered`);
}
if (typeof handler !== 'function') {
throw new Error(`Job handler "${jobName}" must be a function`);
}
console.log(`[XXL-JOB] Job "${jobName}" registered`);
// 包装 handler
this.jobHandlers.set(jobName, async (...args: any[]) => {
try {
return await handler(...args);
} catch (error) {
console.error(`[XXL-JOB] Job "${jobName}" failed:`, error);
return { error };
}
});
}
/**
* 批量注册任务
* @param handlers Array<[string, Function]> 任务处理函数,需返回 Promise
*
*/
public registerBatch(handlers: any[]) {
handlers.forEach((handler) => this.register(handler[0], handler[1]));
}
/**
* 获取任务
* @param jobName 任务名称(需与调度中心配置一致)
*/
public getJobHandler(jobName: string) {
return this.jobHandlers.get(jobName);
}
}