feat: 初始化项目结构并添加核心功能模块
- 新增文档模板和导航结构 - 实现服务器基础API路由和控制器 - 添加扩展插件配置和前端框架 - 引入多租户和权限管理模块 - 集成日志和数据库配置 - 添加核心业务模型和类型定义
This commit is contained in:
124
node-agent/src/index.ts
Normal file
124
node-agent/src/index.ts
Normal file
@@ -0,0 +1,124 @@
|
||||
import axios from 'axios';
|
||||
import os from 'os';
|
||||
|
||||
export interface NodeTask {
|
||||
id: string;
|
||||
type: string;
|
||||
payload: any;
|
||||
shopId: string;
|
||||
traceId: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* [CORE_NODE_01] Win Node Agent
|
||||
* @description 运行在 Windows 环境下的自管代理,负责无 API 平台的执行动作
|
||||
*/
|
||||
export class NodeAgent {
|
||||
private hubUrl: string;
|
||||
private nodeId: string;
|
||||
private heartbeatInterval: number = 30000; // 30秒
|
||||
private pollInterval: number = 10000; // 10秒
|
||||
|
||||
constructor(hubUrl: string) {
|
||||
this.hubUrl = hubUrl;
|
||||
this.nodeId = `WIN-${os.hostname()}-${process.pid}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动代理
|
||||
*/
|
||||
async start() {
|
||||
console.log(`[Agent] Node ${this.nodeId} starting...`);
|
||||
|
||||
// 1. 注册节点
|
||||
await this.register();
|
||||
|
||||
// 2. 开启心跳
|
||||
const heartbeatTimer = setInterval(() => this.heartbeat(), this.heartbeatInterval);
|
||||
// @ts-ignore
|
||||
if (heartbeatTimer.unref) heartbeatTimer.unref();
|
||||
|
||||
// 3. 开启任务轮询
|
||||
const pollTimer = setInterval(() => this.pollTasks(), this.pollInterval);
|
||||
// @ts-ignore
|
||||
if (pollTimer.unref) pollTimer.unref();
|
||||
}
|
||||
|
||||
private async register() {
|
||||
try {
|
||||
console.log(`[Agent] Registering to Hub: ${this.hubUrl}`);
|
||||
await axios.post(`${this.hubUrl}/api/v1/nodes/register`, {
|
||||
nodeId: this.nodeId,
|
||||
version: '1.0.0',
|
||||
os: os.type(),
|
||||
hostname: os.hostname(),
|
||||
shops: [] // 实际应从本地配置加载
|
||||
}).catch(err => {
|
||||
// 如果 Hub 还没启动,忽略错误,仅打印
|
||||
console.warn(`[Agent] Registration failed (Hub might be offline): ${err.message}`);
|
||||
});
|
||||
} catch (err: any) {
|
||||
console.error(`[Agent] Registration error: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
private async heartbeat() {
|
||||
try {
|
||||
console.log(`[Agent] Heartbeat...`);
|
||||
await axios.post(`${this.hubUrl}/api/v1/nodes/heartbeat`, { nodeId: this.nodeId })
|
||||
.catch(() => {}); // 忽略心跳失败
|
||||
} catch (err: any) {
|
||||
console.error(`[Agent] Heartbeat error: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
private async pollTasks() {
|
||||
try {
|
||||
console.log(`[Agent] Polling for tasks...`);
|
||||
const response = await axios.get(`${this.hubUrl}/api/v1/nodes/pull-task?nodeId=${this.nodeId}`)
|
||||
.catch(() => ({ data: { task: null } }));
|
||||
|
||||
if (response.data && response.data.task) {
|
||||
await this.executeTask(response.data.task);
|
||||
}
|
||||
} catch (err: any) {
|
||||
console.error(`[Agent] Poll error: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
private async executeTask(task: NodeTask) {
|
||||
console.log(`[Agent] Executing task: ${task.id} (${task.type})`);
|
||||
|
||||
try {
|
||||
// 模拟执行耗时
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
// 实际应启动 Playwright 浏览器执行动作
|
||||
console.log(`[Agent] Task ${task.id} executed successfully.`);
|
||||
|
||||
await this.reportReceipt({
|
||||
taskId: task.id,
|
||||
traceId: task.traceId,
|
||||
status: 'success',
|
||||
resultData: { platform: 'TikTok', action: 'PUBLISH' }
|
||||
});
|
||||
} catch (err: any) {
|
||||
console.error(`[Agent] Task ${task.id} execution failed: ${err.message}`);
|
||||
await this.reportReceipt({
|
||||
taskId: task.id,
|
||||
traceId: task.traceId,
|
||||
status: 'failed',
|
||||
errorMessage: err.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async reportReceipt(receipt: any) {
|
||||
try {
|
||||
console.log(`[Agent] Reporting receipt for Task: ${receipt.taskId}`);
|
||||
await axios.post(`${this.hubUrl}/api/v1/publish/receipt`, receipt);
|
||||
} catch (err: any) {
|
||||
console.error(`[Agent] Failed to report receipt: ${err.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user