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}`); } } }