GetEventsSince returns events since a cursor
(c *gin.Context)
| 385 | |
| 386 | // GetEventsSince returns events since a cursor |
| 387 | func (h *DashboardHandler) GetEventsSince(c *gin.Context) { |
| 388 | ctx := c.Request.Context() |
| 389 | |
| 390 | // 检查 Registry 是否可用 |
| 391 | if h.registry == nil { |
| 392 | c.JSON(http.StatusOK, gin.H{ |
| 393 | "success": true, |
| 394 | "data": gin.H{ |
| 395 | "events": []gin.H{}, |
| 396 | "next_cursor": int64(0), |
| 397 | "message": "Registry not available, real-time events disabled", |
| 398 | }, |
| 399 | }) |
| 400 | return |
| 401 | } |
| 402 | |
| 403 | cursorStr := c.Param("cursor") |
| 404 | cursor, err := strconv.ParseInt(cursorStr, 10, 64) |
| 405 | if err != nil { |
| 406 | c.JSON(http.StatusBadRequest, gin.H{ |
| 407 | "success": false, |
| 408 | "error": gin.H{ |
| 409 | "code": "bad_request", |
| 410 | "message": "Invalid cursor", |
| 411 | }, |
| 412 | }) |
| 413 | return |
| 414 | } |
| 415 | |
| 416 | // 从所有 Agent 的 EventBus 聚合事件 |
| 417 | var allEvents []types.AgentEventEnvelope |
| 418 | maxCursor := cursor |
| 419 | for _, eb := range h.registry.GetEventBuses() { |
| 420 | if eb != nil { |
| 421 | evts := eb.GetTimelineSince(cursor) |
| 422 | allEvents = append(allEvents, evts...) |
| 423 | // 更新最大 cursor |
| 424 | if ebCursor := eb.GetCursor(); ebCursor > maxCursor { |
| 425 | maxCursor = ebCursor |
| 426 | } |
| 427 | } |
| 428 | } |
| 429 | |
| 430 | // 按时间戳排序(最新的在前) |
| 431 | sort.Slice(allEvents, func(i, j int) bool { |
| 432 | return allEvents[i].Bookmark.Timestamp > allEvents[j].Bookmark.Timestamp |
| 433 | }) |
| 434 | |
| 435 | // 转换为响应格式 |
| 436 | result := make([]gin.H, 0, len(allEvents)) |
| 437 | for _, env := range allEvents { |
| 438 | result = append(result, gin.H{ |
| 439 | "cursor": env.Cursor, |
| 440 | "timestamp": time.UnixMilli(env.Bookmark.Timestamp), |
| 441 | "event": env.Event, |
| 442 | }) |
| 443 | } |
| 444 |
nothing calls this directly
no test coverage detected