fix(agent): 修复资产重复注册(每10s新建) + 批量删除400
agent 自动注册前按 hostname 显式查重(asset_servers.hostname 无 UNIQUE 索引,OnConflict 失效导致 Agent 每次上报都 INSERT 新记录,资产越来越多)。
批量删除 BatchDeleteServers 对齐前端 {ids} 格式(原期望裸 []uint 导致 ShouldBindJSON 解析失败 400)。
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
f820f0271f
commit
b7780c5a5a
2 files changed
+51
-33
No files matched your search
+45
-31
@@ -163,43 +163,57 @@ func (h *AgentHandler) ReceiveReport(c *gin.Context) {
|
||||
result = h.db.Exec(updateSQL2, args2...)
|
||||
}
|
||||
|
||||
// 如果还是没匹配到 —— 自动注册新服务器(UPSERT 防重复)
|
||||
// 如果还是没匹配到 —— 按 hostname 显式查重后再注册 // Logan.Li
|
||||
// asset_servers.hostname 无 UNIQUE 索引,OnConflict 不可靠,故先 First 查重,
|
||||
// 避免 Agent 每次上报(10s)都新建记录导致资产越来越多。
|
||||
if result.RowsAffected == 0 {
|
||||
osName := ""
|
||||
if req.System != nil {
|
||||
osName = req.System.OSVersion
|
||||
}
|
||||
newServer := model.Server{
|
||||
Hostname: req.Hostname,
|
||||
IP: matchIP,
|
||||
Port: 22,
|
||||
Username: "root",
|
||||
AuthType: "password",
|
||||
OS: osName,
|
||||
CPU: req.CPU.CoreCount,
|
||||
Memory: memMB,
|
||||
Disk: diskGB,
|
||||
Status: "running",
|
||||
AgentStatus: "online",
|
||||
AgentVersion: req.AgentVersion,
|
||||
CPUUsage: req.CPU.UsagePercent,
|
||||
MemoryUsage: req.Memory.UsagePercent,
|
||||
DiskUsage: diskAvg,
|
||||
}
|
||||
// ON DUPLICATE KEY UPDATE — 若 hostname 已存在则更新字段(防重复注册)
|
||||
if err := h.db.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "hostname"}},
|
||||
DoUpdates: clause.AssignmentColumns([]string{
|
||||
"ip", "os", "cpu", "memory", "disk",
|
||||
"status", "agent_status",
|
||||
"cpu_usage", "memory_usage", "disk_usage",
|
||||
"updated_at",
|
||||
}),
|
||||
}).Create(&newServer).Error; err != nil {
|
||||
fmt.Printf("[agent] 自动注册主机 %q (IP: %s) 失败: %v\n", req.Hostname, matchIP, err)
|
||||
var existing model.Server
|
||||
if h.db.Where("hostname = ?", req.Hostname).First(&existing).Error == nil {
|
||||
// 已自动注册过 → 仅更新实时指标,不重复创建
|
||||
h.db.Model(&existing).Updates(map[string]interface{}{
|
||||
"ip": matchIP, "os": osName, "cpu": req.CPU.CoreCount,
|
||||
"memory": memMB, "disk": diskGB, "status": "running",
|
||||
"agent_status": "online", "agent_version": req.AgentVersion,
|
||||
"cpu_usage": req.CPU.UsagePercent, "memory_usage": req.Memory.UsagePercent,
|
||||
"disk_usage": diskAvg,
|
||||
})
|
||||
} else {
|
||||
fmt.Printf("[agent] 自动注册新主机: %q (IP: %s, CPU=%d核, 内存=%dMB, 磁盘=%dGB, OS=%q)\n",
|
||||
req.Hostname, matchIP, req.CPU.CoreCount, memMB, diskGB, osName)
|
||||
// 真正的新主机 → 注册(OnConflict 作为并发双保险)
|
||||
newServer := model.Server{
|
||||
Hostname: req.Hostname,
|
||||
IP: matchIP,
|
||||
Port: 22,
|
||||
Username: "root",
|
||||
AuthType: "password",
|
||||
OS: osName,
|
||||
CPU: req.CPU.CoreCount,
|
||||
Memory: memMB,
|
||||
Disk: diskGB,
|
||||
Status: "running",
|
||||
AgentStatus: "online",
|
||||
AgentVersion: req.AgentVersion,
|
||||
CPUUsage: req.CPU.UsagePercent,
|
||||
MemoryUsage: req.Memory.UsagePercent,
|
||||
DiskUsage: diskAvg,
|
||||
}
|
||||
if err := h.db.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "hostname"}},
|
||||
DoUpdates: clause.AssignmentColumns([]string{
|
||||
"ip", "os", "cpu", "memory", "disk",
|
||||
"status", "agent_status",
|
||||
"cpu_usage", "memory_usage", "disk_usage",
|
||||
"updated_at",
|
||||
}),
|
||||
}).Create(&newServer).Error; err != nil {
|
||||
fmt.Printf("[agent] 自动注册主机 %q (IP: %s) 失败: %v\n", req.Hostname, matchIP, err)
|
||||
} else {
|
||||
fmt.Printf("[agent] 自动注册新主机: %q (IP: %s, CPU=%d核, 内存=%dMB, 磁盘=%dGB, OS=%q)\n",
|
||||
req.Hostname, matchIP, req.CPU.CoreCount, memMB, diskGB, osName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -169,11 +169,15 @@ func (h *ServerHandlerV2) BatchCreateServers(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *ServerHandlerV2) BatchDeleteServers(c *gin.Context) {
|
||||
var ids []uint
|
||||
if err := c.ShouldBindJSON(&ids); err != nil {
|
||||
// 前端发 { ids: [...] },对齐格式(原期望裸 []uint 导致解析失败 400) // Logan.Li
|
||||
var req struct {
|
||||
IDs []uint `json:"ids"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil || len(req.IDs) == 0 {
|
||||
utils.BadRequest(c, "请求参数错误")
|
||||
return
|
||||
}
|
||||
ids := req.IDs
|
||||
// 清理关联数据
|
||||
for _, id := range ids {
|
||||
var s model.Server
|
||||
|
||||
Reference in new issue
Block a user