| 743 | } |
| 744 | |
| 745 | func (d *Daemon) bootSessionRepair(ctx context.Context, state *bootState) error { |
| 746 | if state == nil { |
| 747 | return errors.New("daemon: boot session repair state is required") |
| 748 | } |
| 749 | if state.sessions == nil { |
| 750 | return errors.New("daemon: boot session repair requires session manager") |
| 751 | } |
| 752 | |
| 753 | infos, err := state.sessions.ListAll(ctx) |
| 754 | if err != nil { |
| 755 | if ctxErr := ctx.Err(); ctxErr != nil { |
| 756 | return fmt.Errorf("daemon: boot session repair canceled: %w", ctxErr) |
| 757 | } |
| 758 | state.logger.Warn("daemon: boot session repair skipped session list", "error", err) |
| 759 | return nil |
| 760 | } |
| 761 | |
| 762 | for _, info := range infos { |
| 763 | if err := ctx.Err(); err != nil { |
| 764 | return fmt.Errorf("daemon: boot session repair canceled: %w", err) |
| 765 | } |
| 766 | if !bootShouldRepairSession(info) { |
| 767 | continue |
| 768 | } |
| 769 | |
| 770 | result, repairErr := state.sessions.RepairSession( |
| 771 | ctx, |
| 772 | session.RepairOpts{SessionID: info.ID}, |
| 773 | ) |
| 774 | if repairErr != nil { |
| 775 | if ctxErr := ctx.Err(); ctxErr != nil { |
| 776 | return fmt.Errorf("daemon: boot session repair canceled: %w", ctxErr) |
| 777 | } |
| 778 | state.logger.Warn( |
| 779 | "daemon: boot session repair failed", |
| 780 | "session_id", info.ID, |
| 781 | "error", repairErr, |
| 782 | ) |
| 783 | continue |
| 784 | } |
| 785 | if result == nil { |
| 786 | continue |
| 787 | } |
| 788 | errorIssues := repairIssueCount(result, session.RepairSeverityError) |
| 789 | if len(result.Actions) == 0 && errorIssues == 0 { |
| 790 | continue |
| 791 | } |
| 792 | state.logger.Info( |
| 793 | "daemon: boot session repair complete", |
| 794 | "session_id", result.SessionID, |
| 795 | "persisted", result.Persisted, |
| 796 | "actions", len(result.Actions), |
| 797 | "issues", len(result.Issues), |
| 798 | "error_issues", errorIssues, |
| 799 | ) |
| 800 | } |
| 801 | if recoverer, ok := state.sessions.(sessionHealthRecoverer); ok { |
| 802 | result, recoveryErr := recoverer.RecoverSessionHealth(ctx) |