package workflow import ( "context" "fmt" "time" "auto-check/pkg/config" "auto-check/pkg/discovery" "auto-check/pkg/report" "auto-check/pkg/stress" ) // Workflow 固定工作流:扫描 → 压测 → 打印状态,按间隔循环 // 状态数据由各包自持(discovery/stress/report),workflow 直接调用其包级函数 type Workflow struct { cfg config.Config base context.Context cancel context.CancelFunc } // New 创建工作流 func New(cfg config.Config) *Workflow { base, cancel := context.WithCancel(context.Background()) return &Workflow{cfg: cfg, base: base, cancel: cancel} } // Start 启动固定工作流循环(永久运行,直至取消) func (w *Workflow) Start() error { interval := w.cfg.Workflow.Interval if interval <= 0 { interval = 10 * time.Second } fmt.Printf("══ 工作流启动(间隔 %v,设备以 IP 为 key)══\n\n", interval) w.round() // 首轮立即执行 ticker := time.NewTicker(interval) defer ticker.Stop() for { select { case <-w.base.Done(): fmt.Println("══ 工作流已停止 ══") return nil case <-ticker.C: w.round() } } } // Stop 停止工作流 func (w *Workflow) Stop() { w.cancel() } // round 单轮:扫描 → 压测 → 打印状态变化 func (w *Workflow) round() { fmt.Printf("════ 轮次开始 [%s] ════\n", time.Now().Format("15:04:05")) // 1. 扫描(discovery 包),更新设备表 cfg := w.cfg discovery.NewScanner(cfg.Scan.CIDR, cfg.Scan.Timeout, cfg.Scan.Concurrency).Discover() fmt.Printf(" [扫描] 设备 %d 台\n", len(discovery.Devices)) // 2. 压测未通过设备(stress.TestDevice 执行,report 保存+打印) for ip, dev := range discovery.Devices { if stress.IsPassed(stress.Results[ip]) { continue // 已通过,跳过 } fmt.Printf(" [测试] %s (%s) 开始压测...\n", ip, dev.MAC) rpt := stress.TestDevice(ip, w.cfg) stress.Results[ip] = rpt if stress.IsSSHFail(rpt) { fmt.Printf(" [测试] %s SSH 连接失败,跳过报告输出: %s\n", ip, rpt.Results[0].Error) continue } report.SaveAndPrintDeviceReport(&dev, rpt, cfg.Report.Path, cfg.Report.Print) } // 3. 打印状态变化(首次或与上次不一致) for ip, rpt := range stress.Results { dev, ok := discovery.Devices[ip] if !ok { continue // 设备本轮缺席,状态保留等它回来 } status := stress.Status(rpt) if prev, ok := report.Printed[ip]; !ok || prev != status { fmt.Printf(" [状态] %s %s → %s\n", dev.Label(), statusIcon(status), status) report.Printed[ip] = status } } } // statusIcon 图标 func statusIcon(s string) string { switch s { case "pass": return "✓" case "fail": return "✗" default: return "○" } }