(ctx context.Context, source Run)
| 515 | } |
| 516 | |
| 517 | func (m *Service) requireRetryChainDepth(ctx context.Context, source Run) error { |
| 518 | runs, err := m.store.ListTaskRuns(ctx, RunQuery{TaskID: source.TaskID}) |
| 519 | if err != nil { |
| 520 | return err |
| 521 | } |
| 522 | byID := make(map[string]Run, len(runs)) |
| 523 | for _, run := range runs { |
| 524 | byID[run.ID] = run |
| 525 | } |
| 526 | depth := 0 |
| 527 | for current := source; strings.TrimSpace(current.PreviousRunID) != ""; { |
| 528 | depth++ |
| 529 | if depth >= MaxRetryRunChainDepth { |
| 530 | return forceRunDiagnosticError( |
| 531 | diagnosticcontract.CodeRetryChainTooDeep, |
| 532 | "Retry chain is too deep", |
| 533 | fmt.Sprintf("Run %s already has retry depth %d.", source.ID, depth), |
| 534 | diagnosticcontract.SeverityError, |
| 535 | fmt.Sprintf("agh task inspect %s", source.TaskID), |
| 536 | map[string]any{runEvidenceIDKey: source.ID, taskEvidenceIDKey: source.TaskID, "depth": depth}, |
| 537 | ErrRetryChainTooDeep, |
| 538 | ) |
| 539 | } |
| 540 | previous, ok := byID[strings.TrimSpace(current.PreviousRunID)] |
| 541 | if !ok { |
| 542 | break |
| 543 | } |
| 544 | current = previous |
| 545 | } |
| 546 | return nil |
| 547 | } |
| 548 | |
| 549 | func normalizeForceReleaseRun(req ForceReleaseRun) (ForceReleaseRun, error) { |
| 550 | req.Reason = strings.TrimSpace(req.Reason) |
no test coverage detected