From 3cfe53251718c991cd120cf9082f0008defe724e Mon Sep 17 00:00:00 2001 From: huang <1724659546@qq.com> Date: Wed, 3 Dec 2025 17:51:29 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9B=E5=BB=BA=E6=A3=80=E6=9F=A5=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E5=88=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/core/data_initializer.go | 79 ++++++++++++++++++++++++++++++- internal/infra/models/models.go | 3 ++ internal/infra/models/plan.go | 2 + 3 files changed, 82 insertions(+), 2 deletions(-) diff --git a/internal/core/data_initializer.go b/internal/core/data_initializer.go index 2086ebe..0af4eec 100644 --- a/internal/core/data_initializer.go +++ b/internal/core/data_initializer.go @@ -2,6 +2,7 @@ package core import ( "context" + "encoding/json" "fmt" "path/filepath" @@ -87,6 +88,10 @@ func (app *Application) initializeSystemPlans(ctx context.Context) error { return err } + if err := app.initializeOtaCheckPlan(appCtx, existingPlanMap); err != nil { + return err + } + logger.Info("预定义系统计划检查完成。") return nil } @@ -252,12 +257,13 @@ func (app *Application) initializeAlarmNotificationPlan(ctx context.Context, exi func (app *Application) initializeHeartbeatCheckPlan(ctx context.Context, existingPlanMap map[models.PlanName]*models.Plan) error { appCtx, logger := logs.Trace(ctx, app.Ctx, "initializeHeartbeatCheckPlan") + cron := 5 predefinedPlan := &models.Plan{ Name: models.PlanNamePeriodicHeartbeatCheck, - Description: "这是一个系统预定义的计划, 每5分钟自动触发一次区域主控心跳检测。", + Description: fmt.Sprintf("这是一个系统预定义的计划, 每%d分钟自动触发一次区域主控心跳检测。", cron), PlanType: models.PlanTypeSystem, ExecutionType: models.PlanExecutionTypeAutomatic, - CronExpression: "*/5 * * * *", // 每5分钟执行一次 + CronExpression: fmt.Sprintf("*/%d * * * *", cron), Status: models.PlanStatusEnabled, ContentType: models.PlanContentTypeTasks, Tasks: []models.Task{ @@ -418,3 +424,72 @@ func (app *Application) cleanupStaleTasksAndLogs(ctx context.Context) error { logger.Info("过期的任务及日志清理完成。") return nil } + +// initializeOtaCheckPlan 负责初始化 "定时检查OTA升级超时" 计划。 +func (app *Application) initializeOtaCheckPlan(ctx context.Context, existingPlanMap map[models.PlanName]*models.Plan) error { + appCtx, logger := logs.Trace(ctx, app.Ctx, "initializeOtaCheckPlan") + + // 1. 从应用配置中获取超时时间,并提供一个安全默认值 + timeout := app.Config.OTA.DefaultTimeoutSeconds + if timeout <= 0 { + timeout = 300 // 如果配置不合法,则使用默认值 300 秒 + } + + // 2. 定义任务参数并序列化 + params := task.OtaCheckTaskParams{ + TimeoutSeconds: timeout, + } + paramsJSON, err := json.Marshal(params) + if err != nil { + return fmt.Errorf("序列化OTA检查任务参数失败: %w", err) + } + + // 3. 构建预定义的计划对象 + cron := 10 + predefinedPlan := &models.Plan{ + Name: models.PlanNameOtaCheck, + Description: fmt.Sprintf("每%d分钟执行一次,扫描所有正在进行的OTA升级任务,并将超时的任务标记为失败。当前超时时间设置为 %d 秒。", cron, timeout), + PlanType: models.PlanTypeSystem, + ExecutionType: models.PlanExecutionTypeAutomatic, + CronExpression: fmt.Sprintf("*/%d * * * *", cron), + Status: models.PlanStatusEnabled, + ContentType: models.PlanContentTypeTasks, + Tasks: []models.Task{ + { + Name: "OTA升级检查", + Description: "扫描并处理超时的OTA升级任务", + ExecutionOrder: 1, + Type: models.TaskTypeOTACheck, + Parameters: paramsJSON, + }, + }, + } + + // 4. 检查计划是否存在,并执行创建或更新操作 + if foundExistingPlan, ok := existingPlanMap[predefinedPlan.Name]; ok { + // 如果计划存在,则进行无差别更新 + logger.Infof("预定义计划 '%s' 已存在,正在进行无差别更新...", predefinedPlan.Name) + + predefinedPlan.ID = foundExistingPlan.ID + predefinedPlan.ExecuteCount = foundExistingPlan.ExecuteCount + + if err := app.Infra.repos.planRepo.UpdatePlanMetadataAndStructure(appCtx, predefinedPlan); err != nil { + return fmt.Errorf("更新预定义计划 '%s' 的元数据和结构失败: %w", predefinedPlan.Name, err) + } + + if err := app.Infra.repos.planRepo.UpdatePlan(appCtx, predefinedPlan); err != nil { + return fmt.Errorf("更新预定义计划 '%s' 的所有顶层字段失败: %w", predefinedPlan.Name, err) + } + + logger.Infof("成功更新预定义计划 '%s'。", predefinedPlan.Name) + } else { + // 如果计划不存在, 则创建 + logger.Infof("预定义计划 '%s' 不存在,正在创建...", predefinedPlan.Name) + if err := app.Infra.repos.planRepo.CreatePlan(appCtx, predefinedPlan); err != nil { + return fmt.Errorf("创建预定义计划 '%s' 失败: %w", predefinedPlan.Name, err) + } else { + logger.Infof("成功创建预定义计划 '%s'。", predefinedPlan.Name) + } + } + return nil +} diff --git a/internal/infra/models/models.go b/internal/infra/models/models.go index 1d8eca9..264ca25 100644 --- a/internal/infra/models/models.go +++ b/internal/infra/models/models.go @@ -90,6 +90,9 @@ func GetAllModels() []interface{} { // Notification Models &Notification{}, + + // OTA Upgrade Models + &OTATask{}, } } diff --git a/internal/infra/models/plan.go b/internal/infra/models/plan.go index c68265b..1249baa 100644 --- a/internal/infra/models/plan.go +++ b/internal/infra/models/plan.go @@ -20,6 +20,8 @@ const ( PlanNamePeriodicHeartbeatCheck PlanName = "周期性心跳检测" // PlanNameAlarmNotification 是告警通知发送计划的名称 PlanNameAlarmNotification PlanName = "告警通知发送" + // PlanNameOtaCheck 是定时检查OTA升级任务的计划名称 + PlanNameOtaCheck PlanName = "定时检查OTA任务" ) // PlanExecutionType 定义了计划的执行类型