refactor: 移除冗余中间类型和不必要代码

- 移除 ScheduledTestOutcome 中间类型,RunTestBackground 直接返回 *ScheduledTestResult
- 简化 SaveResult 直接接受 *ScheduledTestResult
- 移除 handler 中不必要的 nil 检查
- 移除前端 ScheduledTestsPanel 中多余的 String() 转换

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
guoyongchang
2026-03-05 16:37:07 +08:00
parent 817a491087
commit 831abf7977
6 changed files with 20 additions and 47 deletions

View File

@@ -47,9 +47,6 @@ func (h *ScheduledTestHandler) ListByAccount(c *gin.Context) {
response.InternalError(c, err.Error()) response.InternalError(c, err.Error())
return return
} }
if plans == nil {
plans = []*service.ScheduledTestPlan{}
}
c.JSON(http.StatusOK, plans) c.JSON(http.StatusOK, plans)
} }
@@ -154,8 +151,5 @@ func (h *ScheduledTestHandler) ListResults(c *gin.Context) {
response.InternalError(c, err.Error()) response.InternalError(c, err.Error())
return return
} }
if results == nil {
results = []*service.ScheduledTestResult{}
}
c.JSON(http.StatusOK, results) c.JSON(http.StatusOK, results)
} }

View File

@@ -1564,7 +1564,7 @@ func (s *AccountTestService) sendErrorAndEnd(c *gin.Context, errorMsg string) er
// RunTestBackground executes an account test in-memory (no real HTTP client), // RunTestBackground executes an account test in-memory (no real HTTP client),
// capturing SSE output via httptest.NewRecorder, then parses the result. // capturing SSE output via httptest.NewRecorder, then parses the result.
func (s *AccountTestService) RunTestBackground(ctx context.Context, accountID int64, modelID string) (*ScheduledTestOutcome, error) { func (s *AccountTestService) RunTestBackground(ctx context.Context, accountID int64, modelID string) (*ScheduledTestResult, error) {
startedAt := time.Now() startedAt := time.Now()
w := httptest.NewRecorder() w := httptest.NewRecorder()
@@ -1574,28 +1574,25 @@ func (s *AccountTestService) RunTestBackground(ctx context.Context, accountID in
testErr := s.TestAccountConnection(ginCtx, accountID, modelID) testErr := s.TestAccountConnection(ginCtx, accountID, modelID)
finishedAt := time.Now() finishedAt := time.Now()
latencyMs := finishedAt.Sub(startedAt).Milliseconds()
body := w.Body.String() body := w.Body.String()
responseText, errMsg := parseTestSSEOutput(body) responseText, errMsg := parseTestSSEOutput(body)
outcome := &ScheduledTestOutcome{ status := "success"
Status: "success", if testErr != nil || errMsg != "" {
status = "failed"
if errMsg == "" && testErr != nil {
errMsg = testErr.Error()
}
}
return &ScheduledTestResult{
Status: status,
ResponseText: responseText, ResponseText: responseText,
ErrorMessage: errMsg, ErrorMessage: errMsg,
LatencyMs: latencyMs, LatencyMs: finishedAt.Sub(startedAt).Milliseconds(),
StartedAt: startedAt, StartedAt: startedAt,
FinishedAt: finishedAt, FinishedAt: finishedAt,
} }, nil
if testErr != nil || errMsg != "" {
outcome.Status = "failed"
if errMsg == "" && testErr != nil {
outcome.ErrorMessage = testErr.Error()
}
}
return outcome, nil
} }
// parseTestSSEOutput extracts response text and error message from captured SSE output. // parseTestSSEOutput extracts response text and error message from captured SSE output.

View File

@@ -32,16 +32,6 @@ type ScheduledTestResult struct {
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
} }
// ScheduledTestOutcome is returned by RunTestBackground.
type ScheduledTestOutcome struct {
Status string
ResponseText string
ErrorMessage string
LatencyMs int64
StartedAt time.Time
FinishedAt time.Time
}
// ScheduledTestPlanRepository defines the data access interface for test plans. // ScheduledTestPlanRepository defines the data access interface for test plans.
type ScheduledTestPlanRepository interface { type ScheduledTestPlanRepository interface {
Create(ctx context.Context, plan *ScheduledTestPlan) (*ScheduledTestPlan, error) Create(ctx context.Context, plan *ScheduledTestPlan) (*ScheduledTestPlan, error)

View File

@@ -117,13 +117,13 @@ func (s *ScheduledTestRunnerService) runScheduled() {
} }
func (s *ScheduledTestRunnerService) runOnePlan(ctx context.Context, plan *ScheduledTestPlan) { func (s *ScheduledTestRunnerService) runOnePlan(ctx context.Context, plan *ScheduledTestPlan) {
outcome, err := s.accountTestSvc.RunTestBackground(ctx, plan.AccountID, plan.ModelID) result, err := s.accountTestSvc.RunTestBackground(ctx, plan.AccountID, plan.ModelID)
if err != nil { if err != nil {
logger.LegacyPrintf("service.scheduled_test_runner", "[ScheduledTestRunner] plan=%d RunTestBackground error: %v", plan.ID, err) logger.LegacyPrintf("service.scheduled_test_runner", "[ScheduledTestRunner] plan=%d RunTestBackground error: %v", plan.ID, err)
return return
} }
if err := s.scheduledSvc.SaveResult(ctx, plan.ID, plan.MaxResults, outcome); err != nil { if err := s.scheduledSvc.SaveResult(ctx, plan.ID, plan.MaxResults, result); err != nil {
logger.LegacyPrintf("service.scheduled_test_runner", "[ScheduledTestRunner] plan=%d SaveResult error: %v", plan.ID, err) logger.LegacyPrintf("service.scheduled_test_runner", "[ScheduledTestRunner] plan=%d SaveResult error: %v", plan.ID, err)
} }

View File

@@ -77,16 +77,8 @@ func (s *ScheduledTestService) ListResults(ctx context.Context, planID int64, li
} }
// SaveResult inserts a result and prunes old entries beyond maxResults. // SaveResult inserts a result and prunes old entries beyond maxResults.
func (s *ScheduledTestService) SaveResult(ctx context.Context, planID int64, maxResults int, outcome *ScheduledTestOutcome) error { func (s *ScheduledTestService) SaveResult(ctx context.Context, planID int64, maxResults int, result *ScheduledTestResult) error {
result := &ScheduledTestResult{ result.PlanID = planID
PlanID: planID,
Status: outcome.Status,
ResponseText: outcome.ResponseText,
ErrorMessage: outcome.ErrorMessage,
LatencyMs: outcome.LatencyMs,
StartedAt: outcome.StartedAt,
FinishedAt: outcome.FinishedAt,
}
if _, err := s.resultRepo.Create(ctx, result); err != nil { if _, err := s.resultRepo.Create(ctx, result); err != nil {
return err return err
} }

View File

@@ -469,8 +469,8 @@ const handleCreate = async () => {
const maxResults = Number(newPlan.max_results) || 100 const maxResults = Number(newPlan.max_results) || 100
await adminAPI.scheduledTests.create({ await adminAPI.scheduledTests.create({
account_id: props.accountId, account_id: props.accountId,
model_id: String(newPlan.model_id), model_id: newPlan.model_id,
cron_expression: String(newPlan.cron_expression), cron_expression: newPlan.cron_expression,
enabled: newPlan.enabled, enabled: newPlan.enabled,
max_results: maxResults max_results: maxResults
}) })
@@ -515,8 +515,8 @@ const handleEdit = async () => {
updating.value = true updating.value = true
try { try {
const updated = await adminAPI.scheduledTests.update(editingPlanId.value, { const updated = await adminAPI.scheduledTests.update(editingPlanId.value, {
model_id: String(editForm.model_id), model_id: editForm.model_id,
cron_expression: String(editForm.cron_expression), cron_expression: editForm.cron_expression,
max_results: Number(editForm.max_results) || 100, max_results: Number(editForm.max_results) || 100,
enabled: editForm.enabled enabled: editForm.enabled
}) })