- agent 数据写入增加 10s 超时,写失败立即断连重连,消除无超时写卡死期间快照被覆盖的静默丢失 - 事件类消息(SSH登录/防篡改/指令响应/监控检测)改走内存 outbox:seq + 服务端累计 ack + 断线重放,上限 1024 条溢出丢最旧,重启清空(可接受) - 注册请求携带 BootID 会话标识:探针重启后 seq 从 1 重新分配,服务端据此重置确认位点,避免新消息被旧位点误判为重复而丢弃 - server 读循环与处理解耦(per-agent 有序队列 + 串行 worker),慢处理不再阻塞 TCP 读取,队列满断连由探针重放兜底 - 修复探针快速重连时旧连接误注销新连接的竞态(此前会闪断新连接) - IsAgentEnabled 加 3s TTL 缓存,禁用立即失效;pong 在线状态写库去抖(首次 + 5 分钟心跳刷新) - VM 写超时默认 30s -> 10s,快速失败配合重放兜底 新旧版本双向兼容:注册响应 Reliable 字段协商,旧 server 下探针自动降级直发
122 lines
4.1 KiB
Go
122 lines
4.1 KiB
Go
package handler
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/glebarez/sqlite"
|
|
"github.com/pika-monitor/pika/internal/models"
|
|
"github.com/pika-monitor/pika/internal/protocol"
|
|
"github.com/pika-monitor/pika/internal/repo"
|
|
"github.com/pika-monitor/pika/internal/service"
|
|
"go.uber.org/zap"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func TestHandleWebSocketMessageIgnoresDisabledAgent(t *testing.T) {
|
|
database, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatalf("open database: %v", err)
|
|
}
|
|
if err := database.AutoMigrate(&models.Agent{}); err != nil {
|
|
t.Fatalf("migrate agent: %v", err)
|
|
}
|
|
|
|
h := &AgentHandler{
|
|
logger: zap.NewNop(),
|
|
agentService: &service.AgentService{
|
|
AgentRepo: repo.NewAgentRepo(database),
|
|
},
|
|
}
|
|
|
|
agent := models.Agent{ID: "agent-disabled", Enabled: true}
|
|
if err := database.Create(&agent).Error; err != nil {
|
|
t.Fatalf("create agent: %v", err)
|
|
}
|
|
// 通过服务层切换启用状态,保证 IsAgentEnabled 的缓存被正确失效
|
|
if err := h.agentService.UpdateAgentEnabled(context.Background(), agent.ID, false); err != nil {
|
|
t.Fatalf("disable agent: %v", err)
|
|
}
|
|
|
|
invalidMetrics := json.RawMessage(`{`)
|
|
if err := h.handleWebSocketMessage(context.Background(), agent.ID, string(protocol.MessageTypeMetrics), invalidMetrics); err != nil {
|
|
t.Fatalf("disabled agent data should be ignored, got error: %v", err)
|
|
}
|
|
|
|
if err := h.agentService.UpdateAgentEnabled(context.Background(), agent.ID, true); err != nil {
|
|
t.Fatalf("enable agent: %v", err)
|
|
}
|
|
if err := h.handleWebSocketMessage(context.Background(), agent.ID, string(protocol.MessageTypeMetrics), invalidMetrics); err == nil {
|
|
t.Fatal("enabled agent data should reach the metrics parser")
|
|
}
|
|
}
|
|
|
|
func TestDisabledAgentStatusCannotBeRefreshed(t *testing.T) {
|
|
database, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatalf("open database: %v", err)
|
|
}
|
|
if err := database.AutoMigrate(&models.Agent{}); err != nil {
|
|
t.Fatalf("migrate agent: %v", err)
|
|
}
|
|
|
|
agent := models.Agent{ID: "agent-status", Enabled: true, Status: 1}
|
|
if err := database.Create(&agent).Error; err != nil {
|
|
t.Fatalf("create agent: %v", err)
|
|
}
|
|
agentService := &service.AgentService{AgentRepo: repo.NewAgentRepo(database)}
|
|
if err := agentService.UpdateAgentEnabled(context.Background(), agent.ID, false); err != nil {
|
|
t.Fatalf("disable agent: %v", err)
|
|
}
|
|
if err := agentService.UpdateAgentStatus(context.Background(), agent.ID, 1); err != nil {
|
|
t.Fatalf("refresh disabled agent status: %v", err)
|
|
}
|
|
|
|
var saved models.Agent
|
|
if err := database.First(&saved, "id = ?", agent.ID).Error; err != nil {
|
|
t.Fatalf("load agent: %v", err)
|
|
}
|
|
if saved.Enabled || saved.Status != 0 {
|
|
t.Fatalf("disabled agent status changed unexpectedly: enabled=%v status=%d", saved.Enabled, saved.Status)
|
|
}
|
|
}
|
|
|
|
func TestPublicAgentQueriesExcludeDisabledAgents(t *testing.T) {
|
|
database, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatalf("open database: %v", err)
|
|
}
|
|
if err := database.AutoMigrate(&models.Agent{}); err != nil {
|
|
t.Fatalf("migrate agent: %v", err)
|
|
}
|
|
|
|
agents := []models.Agent{
|
|
{ID: "public-enabled", Enabled: true, Visibility: "public"},
|
|
{ID: "public-disabled", Enabled: true, Visibility: "public"},
|
|
}
|
|
if err := database.Create(&agents).Error; err != nil {
|
|
t.Fatalf("create agents: %v", err)
|
|
}
|
|
if err := database.Model(&models.Agent{}).Where("id = ?", "public-disabled").Update("enabled", false).Error; err != nil {
|
|
t.Fatalf("disable agent: %v", err)
|
|
}
|
|
|
|
publicAgents, err := repo.NewAgentRepo(database).FindPublicAgents(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("query public agents: %v", err)
|
|
}
|
|
if len(publicAgents) != 1 || publicAgents[0].ID != "public-enabled" {
|
|
t.Fatalf("unexpected public agents: %+v", publicAgents)
|
|
}
|
|
|
|
authenticatedAgents, err := (&service.AgentService{AgentRepo: repo.NewAgentRepo(database)}).
|
|
ListByAuth(context.Background(), true)
|
|
if err != nil {
|
|
t.Fatalf("query authenticated agents: %v", err)
|
|
}
|
|
if len(authenticatedAgents) != 1 || authenticatedAgents[0].ID != "public-enabled" {
|
|
t.Fatalf("authenticated query returned disabled agents: %+v", authenticatedAgents)
|
|
}
|
|
}
|