fix: agent exec log error

This commit is contained in:
engigu
2026-01-03 12:36:41 +08:00
parent 69da61b9a0
commit 6ffb65eebe
11 changed files with 103 additions and 43 deletions
+22 -6
View File
@@ -7,18 +7,18 @@ import (
"baihu/internal/constant" "baihu/internal/constant"
"baihu/internal/database" "baihu/internal/database"
"baihu/internal/models" "baihu/internal/models"
"baihu/internal/services" "baihu/internal/services/tasks"
"baihu/internal/utils" "baihu/internal/utils"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
type DashboardController struct { type DashboardController struct {
cronService *services.CronService cronService *tasks.CronService
executorService *services.ExecutorService executorService *tasks.ExecutorService
} }
func NewDashboardController(cronService *services.CronService, executorService *services.ExecutorService) *DashboardController { func NewDashboardController(cronService *tasks.CronService, executorService *tasks.ExecutorService) *DashboardController {
return &DashboardController{ return &DashboardController{
cronService: cronService, cronService: cronService,
executorService: executorService, executorService: executorService,
@@ -45,13 +45,29 @@ func (dc *DashboardController) GetStats(c *gin.Context) {
today := time.Now().Format("2006-01-02") today := time.Now().Format("2006-01-02")
database.DB.Model(&models.SendStats{}).Where("day = ?", today).Select("COALESCE(SUM(num), 0)").Scan(&todayExecs) database.DB.Model(&models.SendStats{}).Where("day = ?", today).Select("COALESCE(SUM(num), 0)").Scan(&todayExecs)
// 调度统计:本地调度 + Agent 调度
// 本地调度:agent_id 为 NULL 且 enabled = true 的任务
localScheduled := dc.cronService.GetScheduledCount()
// Agent 调度:agent_id 不为 NULL 且 enabled = true 的任务
var agentScheduled int64
database.DB.Model(&models.Task{}).
Where("agent_id IS NOT NULL AND enabled = ?", true).
Count(&agentScheduled)
totalScheduled := localScheduled + int(agentScheduled)
// 正在运行:目前只能统计本地运行的任务
// Agent 端的运行状态需要通过心跳上报(未来优化)
running := dc.executorService.GetRunningCount()
stats := StatsResponse{ stats := StatsResponse{
Tasks: taskCount, Tasks: taskCount,
TodayExecs: todayExecs, TodayExecs: todayExecs,
Envs: envCount, Envs: envCount,
Logs: logCount, Logs: logCount,
Scheduled: dc.cronService.GetScheduledCount(), Scheduled: totalScheduled,
Running: dc.executorService.GetRunningCount(), Running: running,
} }
utils.Success(c, stats) utils.Success(c, stats)
+3 -3
View File
@@ -3,17 +3,17 @@ package controllers
import ( import (
"strconv" "strconv"
"baihu/internal/services" "baihu/internal/services/tasks"
"baihu/internal/utils" "baihu/internal/utils"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
type ExecutorController struct { type ExecutorController struct {
executorService *services.ExecutorService executorService *tasks.ExecutorService
} }
func NewExecutorController(executorService *services.ExecutorService) *ExecutorController { func NewExecutorController(executorService *tasks.ExecutorService) *ExecutorController {
return &ExecutorController{executorService: executorService} return &ExecutorController{executorService: executorService}
} }
+3 -2
View File
@@ -9,6 +9,7 @@ import (
"baihu/internal/database" "baihu/internal/database"
"baihu/internal/models" "baihu/internal/models"
"baihu/internal/services" "baihu/internal/services"
"baihu/internal/services/tasks"
"baihu/internal/utils" "baihu/internal/utils"
"fmt" "fmt"
"os" "os"
@@ -23,10 +24,10 @@ type SettingsController struct {
settingsService *services.SettingsService settingsService *services.SettingsService
loginLogService *services.LoginLogService loginLogService *services.LoginLogService
backupService *services.BackupService backupService *services.BackupService
executorService *services.ExecutorService executorService *tasks.ExecutorService
} }
func NewSettingsController(userService *services.UserService, loginLogService *services.LoginLogService, executorService *services.ExecutorService) *SettingsController { func NewSettingsController(userService *services.UserService, loginLogService *services.LoginLogService, executorService *tasks.ExecutorService) *SettingsController {
return &SettingsController{ return &SettingsController{
userService: userService, userService: userService,
settingsService: services.NewSettingsService(), settingsService: services.NewSettingsService(),
+4 -3
View File
@@ -6,18 +6,19 @@ import (
"baihu/internal/constant" "baihu/internal/constant"
"baihu/internal/services" "baihu/internal/services"
"baihu/internal/services/tasks"
"baihu/internal/utils" "baihu/internal/utils"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
type TaskController struct { type TaskController struct {
taskService *services.TaskService taskService *tasks.TaskService
cronService *services.CronService cronService *tasks.CronService
agentWSManager *services.AgentWSManager agentWSManager *services.AgentWSManager
} }
func NewTaskController(taskService *services.TaskService, cronService *services.CronService) *TaskController { func NewTaskController(taskService *tasks.TaskService, cronService *tasks.CronService) *TaskController {
return &TaskController{ return &TaskController{
taskService: taskService, taskService: taskService,
cronService: cronService, cronService: cronService,
+10 -4
View File
@@ -4,9 +4,10 @@ import (
"baihu/internal/constant" "baihu/internal/constant"
"baihu/internal/controllers" "baihu/internal/controllers"
"baihu/internal/services" "baihu/internal/services"
"baihu/internal/services/tasks"
) )
var cronService *services.CronService var cronService *tasks.CronService
func RegisterControllers() *Controllers { func RegisterControllers() *Controllers {
// Initialize services // Initialize services
@@ -17,13 +18,18 @@ func RegisterControllers() *Controllers {
initService := services.NewInitService(settingsService) initService := services.NewInitService(settingsService)
userService := initService.Initialize() userService := initService.Initialize()
taskService := services.NewTaskService() taskService := tasks.NewTaskService()
envService := services.NewEnvService() envService := services.NewEnvService()
scriptService := services.NewScriptService() scriptService := services.NewScriptService()
executorService := services.NewExecutorService(taskService) sendStatsService := services.NewSendStatsService()
agentWSManager := services.GetAgentWSManager()
// 创建任务执行服务(需要依赖注入)
taskExecutionService := tasks.NewTaskExecutionService(agentWSManager, sendStatsService)
executorService := tasks.NewExecutorService(taskService, taskExecutionService, settingsService, envService)
// Initialize cron service // Initialize cron service
cronService = services.NewCronService(taskService, executorService) cronService = tasks.NewCronService(taskService, executorService)
cronService.Start() cronService.Start()
// Initialize and return controllers // Initialize and return controllers
+5 -1
View File
@@ -5,6 +5,7 @@ import (
"baihu/internal/database" "baihu/internal/database"
"baihu/internal/logger" "baihu/internal/logger"
"baihu/internal/models" "baihu/internal/models"
"baihu/internal/services/tasks"
"crypto/rand" "crypto/rand"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
@@ -350,7 +351,10 @@ func (s *AgentService) buildEnvVarsString(envIDs string) string {
// ReportResult Agent 上报执行结果 // ReportResult Agent 上报执行结果
func (s *AgentService) ReportResult(result *models.AgentTaskResult) error { func (s *AgentService) ReportResult(result *models.AgentTaskResult) error {
taskExecutionService := NewTaskExecutionService() // 获取依赖的服务
agentWSManager := GetAgentWSManager()
sendStatsService := NewSendStatsService()
taskExecutionService := tasks.NewTaskExecutionService(agentWSManager, sendStatsService)
// 使用统一的结果处理流程 // 使用统一的结果处理流程
return taskExecutionService.ProcessAgentResult(result) return taskExecutionService.ProcessAgentResult(result)
@@ -1,4 +1,4 @@
package services package tasks
import ( import (
"sync" "sync"
@@ -1,4 +1,4 @@
package services package tasks
import ( import (
"baihu/internal/constant" "baihu/internal/constant"
@@ -17,6 +17,16 @@ import (
"time" "time"
) )
// SettingsService 接口定义(避免循环依赖)
type SettingsService interface {
Get(section, key string) string
}
// EnvService 接口定义(避免循环依赖)
type EnvService interface {
GetEnvVarsByIDs(ids string) []string
}
// ExecutionResult represents the result of a task execution // ExecutionResult represents the result of a task execution
type ExecutionResult struct { type ExecutionResult struct {
TaskID int TaskID int
@@ -36,6 +46,8 @@ type taskJob struct {
type ExecutorService struct { type ExecutorService struct {
taskService *TaskService taskService *TaskService
taskExecutionService *TaskExecutionService taskExecutionService *TaskExecutionService
settingsService SettingsService
envService EnvService
results []ExecutionResult results []ExecutionResult
runningTasks map[int]bool runningTasks map[int]bool
mu sync.RWMutex mu sync.RWMutex
@@ -50,9 +62,8 @@ type ExecutorService struct {
} }
// NewExecutorService creates a new executor service // NewExecutorService creates a new executor service
func NewExecutorService(taskService *TaskService) *ExecutorService { func NewExecutorService(taskService *TaskService, taskExecutionService *TaskExecutionService, settingsService SettingsService, envService EnvService) *ExecutorService {
// 从设置中读取调度配置 // 从设置中读取调度配置
settingsService := NewSettingsService()
workerCount := getIntSetting(settingsService, constant.SectionScheduler, constant.KeyWorkerCount, 4) workerCount := getIntSetting(settingsService, constant.SectionScheduler, constant.KeyWorkerCount, 4)
queueSize := getIntSetting(settingsService, constant.SectionScheduler, constant.KeyQueueSize, 100) queueSize := getIntSetting(settingsService, constant.SectionScheduler, constant.KeyQueueSize, 100)
rateInterval := getIntSetting(settingsService, constant.SectionScheduler, constant.KeyRateInterval, 200) rateInterval := getIntSetting(settingsService, constant.SectionScheduler, constant.KeyRateInterval, 200)
@@ -61,7 +72,9 @@ func NewExecutorService(taskService *TaskService) *ExecutorService {
es := &ExecutorService{ es := &ExecutorService{
taskService: taskService, taskService: taskService,
taskExecutionService: NewTaskExecutionService(), taskExecutionService: taskExecutionService,
settingsService: settingsService,
envService: envService,
results: make([]ExecutionResult, 0, 100), results: make([]ExecutionResult, 0, 100),
runningTasks: make(map[int]bool), runningTasks: make(map[int]bool),
taskQueue: make(chan taskJob, queueSize), taskQueue: make(chan taskJob, queueSize),
@@ -77,7 +90,7 @@ func NewExecutorService(taskService *TaskService) *ExecutorService {
} }
// getIntSetting 从设置中获取整数值 // getIntSetting 从设置中获取整数值
func getIntSetting(s *SettingsService, section, key string, defaultVal int) int { func getIntSetting(s SettingsService, section, key string, defaultVal int) int {
val := s.Get(section, key) val := s.Get(section, key)
if val == "" { if val == "" {
return defaultVal return defaultVal
@@ -128,10 +141,9 @@ func (es *ExecutorService) Reload() {
logger.Info("[Executor] 已停止工作线程") logger.Info("[Executor] 已停止工作线程")
// 从设置中读取新配置 // 从设置中读取新配置
settingsService := NewSettingsService() workerCount := getIntSetting(es.settingsService, constant.SectionScheduler, constant.KeyWorkerCount, 4)
workerCount := getIntSetting(settingsService, constant.SectionScheduler, constant.KeyWorkerCount, 4) queueSize := getIntSetting(es.settingsService, constant.SectionScheduler, constant.KeyQueueSize, 100)
queueSize := getIntSetting(settingsService, constant.SectionScheduler, constant.KeyQueueSize, 100) rateInterval := getIntSetting(es.settingsService, constant.SectionScheduler, constant.KeyRateInterval, 200)
rateInterval := getIntSetting(settingsService, constant.SectionScheduler, constant.KeyRateInterval, 200)
// 重建 channel 和配置 // 重建 channel 和配置
es.mu.Lock() es.mu.Lock()
@@ -228,8 +240,7 @@ func (es *ExecutorService) executeNormalTask(task *models.Task) *ExecutionResult
} }
// 加载环境变量 // 加载环境变量
envService := NewEnvService() envVars := es.envService.GetEnvVarsByIDs(task.Envs)
envVars := envService.GetEnvVarsByIDs(task.Envs)
// 确定工作目录 // 确定工作目录
workDir := task.WorkDir workDir := task.WorkDir
@@ -1,4 +1,4 @@
package services package tasks
import ( import (
"baihu/internal/database" "baihu/internal/database"
@@ -15,15 +15,22 @@ import (
"time" "time"
) )
// AgentWSManager 接口定义(避免循环依赖)
type AgentWSManager interface {
SendToAgent(agentID uint, msgType string, data interface{}) error
}
// TaskExecutionService 统一的任务执行服务 // TaskExecutionService 统一的任务执行服务
type TaskExecutionService struct { type TaskExecutionService struct {
taskLogService *TaskLogService taskLogService *TaskLogService
agentWSManager AgentWSManager
} }
// NewTaskExecutionService 创建任务执行服务 // NewTaskExecutionService 创建任务执行服务
func NewTaskExecutionService() *TaskExecutionService { func NewTaskExecutionService(agentWSManager AgentWSManager, sendStatsService SendStatsService) *TaskExecutionService {
return &TaskExecutionService{ return &TaskExecutionService{
taskLogService: NewTaskLogService(), taskLogService: NewTaskLogService(sendStatsService),
agentWSManager: agentWSManager,
} }
} }
@@ -127,8 +134,10 @@ func (s *TaskExecutionService) executeRemote(req *TaskExecutionRequest) error {
} }
// 通过 WebSocket 发送立即执行命令给 Agent // 通过 WebSocket 发送立即执行命令给 Agent
manager := GetAgentWSManager() if s.agentWSManager == nil {
err := manager.SendToAgent(agentID, "execute", map[string]interface{}{ return fmt.Errorf("AgentWSManager 未初始化")
}
err := s.agentWSManager.SendToAgent(agentID, "execute", map[string]interface{}{
"task_id": task.ID, "task_id": task.ID,
}) })
if err != nil { if err != nil {
@@ -1,4 +1,4 @@
package services package tasks
import ( import (
"baihu/internal/database" "baihu/internal/database"
@@ -9,12 +9,21 @@ import (
"time" "time"
) )
// SendStatsService 接口定义(避免循环依赖)
type SendStatsService interface {
IncrementStats(taskID uint, status string) error
}
// TaskLogService 任务日志服务 // TaskLogService 任务日志服务
type TaskLogService struct{} type TaskLogService struct {
sendStatsService SendStatsService
}
// NewTaskLogService 创建任务日志服务 // NewTaskLogService 创建任务日志服务
func NewTaskLogService() *TaskLogService { func NewTaskLogService(sendStatsService SendStatsService) *TaskLogService {
return &TaskLogService{} return &TaskLogService{
sendStatsService: sendStatsService,
}
} }
// CleanConfig 清理配置 // CleanConfig 清理配置
@@ -37,8 +46,11 @@ func (s *TaskLogService) SaveTaskLog(taskLog *models.TaskLog) error {
// UpdateTaskStats 更新任务统计 // UpdateTaskStats 更新任务统计
func (s *TaskLogService) UpdateTaskStats(taskID uint, status string) { func (s *TaskLogService) UpdateTaskStats(taskID uint, status string) {
sendStatsService := NewSendStatsService() if s.sendStatsService == nil {
err := sendStatsService.IncrementStats(taskID, status) logger.Error("[TaskLog] SendStatsService 未初始化")
return
}
err := s.sendStatsService.IncrementStats(taskID, status)
if err != nil { if err != nil {
logger.Errorf("UpdateTaskStats err: %v", err) logger.Errorf("UpdateTaskStats err: %v", err)
return return
@@ -1,4 +1,4 @@
package services package tasks
import ( import (
"baihu/internal/database" "baihu/internal/database"