handleTracerouteStream 同步阻塞,把 nodeapi.TracerouteHops 的每跳推回 server, event="traceroute_hop"。错误事件会作为终态错误返回(session 会回一条 Ok=false 响应)。
(ctx context.Context, req nodes.TracerouteRequest)
| 239 | // handleTracerouteStream 同步阻塞,把 nodeapi.TracerouteHops 的每跳推回 server, |
| 240 | // event="traceroute_hop"。错误事件会作为终态错误返回(session 会回一条 Ok=false 响应)。 |
| 241 | func (d *APIDispatcher) handleTracerouteStream(ctx context.Context, req nodes.TracerouteRequest) error { |
| 242 | if d.sender == nil { |
| 243 | return errors.New("nodeagent: sender not initialized for streaming") |
| 244 | } |
| 245 | reqID := ReqIDFromContext(ctx) |
| 246 | if reqID == "" { |
| 247 | return errors.New("nodeagent: TracerouteStream missing reqID in ctx") |
| 248 | } |
| 249 | apiReq := nodeapi.TracerouteRequest{ |
| 250 | Host: req.Host, |
| 251 | Method: req.Method, |
| 252 | Port: req.Port, |
| 253 | } |
| 254 | ch := d.api.TracerouteHops(ctx, apiReq) |
| 255 | for ev := range ch { |
| 256 | if ev.Err != "" { |
| 257 | // 把错误事件也作为帧推回(与 HTTP SSE 行为对齐:客户端能看到错误内容), |
| 258 | // 然后返回一个非 nil error 让 session 回 Ok=false 终态。 |
| 259 | body, _ := json.Marshal(map[string]string{"error": ev.Err}) |
| 260 | _ = d.sender.PushEvent(reqID, "traceroute_hop", body, 0) |
| 261 | return errors.New(ev.Err) |
| 262 | } |
| 263 | body, err := json.Marshal(ev.Hop) |
| 264 | if err != nil { |
| 265 | return fmt.Errorf("marshal hop frame: %w", err) |
| 266 | } |
| 267 | if err := d.sender.PushEvent(reqID, "traceroute_hop", body, 0); err != nil { |
| 268 | return err |
| 269 | } |
| 270 | if ctx.Err() != nil { |
| 271 | return nil |
| 272 | } |
| 273 | } |
| 274 | return nil |
| 275 | } |
| 276 | |
| 277 | // ── ConfigHasher ───────────────────────────────────────────────── |
| 278 |
no test coverage detected