| 241 | } |
| 242 | |
| 243 | func (r *Run) Close(summary Summary) error { |
| 244 | if r.closed { |
| 245 | return errors.New("export run already closed") |
| 246 | } |
| 247 | r.resultsCSV.Flush() |
| 248 | if err := r.resultsCSV.Error(); err != nil { |
| 249 | _ = r.Abort() |
| 250 | return fmt.Errorf("failed to flush results to %q: %w", r.resultsPath, err) |
| 251 | } |
| 252 | if err := r.resultsBuf.Flush(); err != nil { |
| 253 | _ = r.Abort() |
| 254 | return fmt.Errorf("failed to flush results buffer to %q: %w", r.resultsPath, err) |
| 255 | } |
| 256 | if err := r.resultsFile.Sync(); err != nil { |
| 257 | _ = r.Abort() |
| 258 | return fmt.Errorf("failed to sync results file %q: %w", r.resultsPath, err) |
| 259 | } |
| 260 | if err := r.resultsFile.Close(); err != nil { |
| 261 | _ = r.Abort() |
| 262 | return fmt.Errorf("failed to close results file %q: %w", r.resultsPath, err) |
| 263 | } |
| 264 | if err := os.Rename(r.tempResultsPath, r.resultsPath); err != nil { |
| 265 | _ = os.Remove(r.tempResultsPath) |
| 266 | return fmt.Errorf("failed to replace results file %q: %w", r.resultsPath, err) |
| 267 | } |
| 268 | if err := writeSummary(r.summaryPath, summary); err != nil { |
| 269 | return err |
| 270 | } |
| 271 | r.closed = true |
| 272 | return nil |
| 273 | } |
| 274 | |
| 275 | func (r *Run) Abort() error { |
| 276 | if r.closed { |