Serialize restore recovery and rebase manifest paths

This commit is contained in:
2026-08-10 21:01:28 +00:00
parent 4158394dcf
commit 8375ad83f3
14 changed files with 581 additions and 78 deletions

View File

@@ -69,23 +69,23 @@ func Restore(ctx context.Context, args []string, out io.Writer) (resultErr error
if err != nil {
return fmt.Errorf("restore: %w", err)
}
plan, err := buildRestorePlanFn(ctx, cfg, current, objectStore, RestorePlanOptions{
IncludeAudio: includeAudio,
Force: force,
DryRun: dryRun,
})
if err != nil {
return fmt.Errorf("restore: %w", err)
}
report, err := newRestoreReport(current, plan, RestorePlanOptions{
IncludeAudio: includeAudio,
Force: force,
DryRun: dryRun,
})
if err != nil {
return fmt.Errorf("restore: %w", err)
}
if dryRun {
plan, err := buildRestorePlanFn(ctx, cfg, current, objectStore, RestorePlanOptions{
IncludeAudio: includeAudio,
Force: force,
DryRun: true,
})
if err != nil {
return fmt.Errorf("restore: %w", err)
}
report, err := newRestoreReport(current, plan, RestorePlanOptions{
IncludeAudio: includeAudio,
Force: force,
DryRun: true,
})
if err != nil {
return fmt.Errorf("restore: %w", err)
}
if err := writeRestoreDryRunSummary(out, report); err != nil {
return fmt.Errorf("restore: write plan output: %w", err)
}
@@ -110,6 +110,24 @@ func Restore(ctx context.Context, args []string, out io.Writer) (resultErr error
}
}()
// Classification and installation share the same transition lock as a
// runner. This prevents a runner from making reuse decisions against state
// that restore is about to replace.
plan, err := buildRestorePlanFn(ctx, cfg, current, objectStore, RestorePlanOptions{
IncludeAudio: includeAudio,
Force: force,
})
if err != nil {
return fmt.Errorf("restore: %w", err)
}
report, err := newRestoreReport(current, plan, RestorePlanOptions{
IncludeAudio: includeAudio,
Force: force,
})
if err != nil {
return fmt.Errorf("restore: %w", err)
}
if plan.ConflictCount > 0 {
report.setFailed(fmt.Errorf("conflict: %d conflicting path(s)", plan.ConflictCount))
if _, reportErr := persistRestoreReport(artifactStore, cfg, report); reportErr != nil {
@@ -123,6 +141,9 @@ func Restore(ctx context.Context, args []string, out io.Writer) (resultErr error
plan.ConflictCount,
)
}
if err := writeRestoreMarker(artifactStore.SessionPathsFor(cfg.Session.Campaign, cfg.Session.SessionID)); err != nil {
return fmt.Errorf("restore: mark incomplete restore: %w", err)
}
result, err := executeRestorePlanFn(ctx, cfg, current, plan, report, objectStore)
if err != nil {
@@ -134,6 +155,9 @@ func Restore(ctx context.Context, args []string, out io.Writer) (resultErr error
}
report.Execution.Downloaded = result.DownloadedCount
report.setSucceeded()
if err := clearRestoreMarker(artifactStore.SessionPathsFor(cfg.Session.Campaign, cfg.Session.SessionID)); err != nil {
return fmt.Errorf("restore: clear incomplete restore marker: %w", err)
}
if _, err := persistRestoreReport(artifactStore, cfg, report); err != nil {
return fmt.Errorf("restore: write report: %w", err)
}