Skip to content

Commit b92c8e2

Browse files
committed
Fix TestMendFunctionDirect race condition on macOS CI
Add explicit file system synchronization to fix flaky tests failing on macOS CI but passing locally. The issue was a race condition between file operations (truncate/rename) and subsequent verification reads. Changes: - Add defer reader.Close() in analyzeWARCFile to properly clean up gzip decompressor state - Add file.Sync() in truncateFile to ensure truncation is persisted before subsequent reads - Add syncDirectory() helper and call it after rename to ensure metadata is persisted - Add 'path' package import for directory path manipulation This ensures file operations complete before verification reads files, eliminating platform-specific timing differences.
1 parent 4170a1c commit b92c8e2

File tree

1 file changed

+28
-0
lines changed

1 file changed

+28
-0
lines changed

cmd/warc/mend/mend.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"io"
77
"log/slog"
88
"os"
9+
"path"
910
"strings"
1011
"time"
1112

@@ -200,6 +201,13 @@ func mend(cmd *cobra.Command, files []string) {
200201
}
201202
slog.Info("removed .open suffix", "from", filepath, "to", result.newName)
202203
stats.renamedFiles++
204+
205+
// Sync directory to ensure rename is persisted to disk before verification reads the file
206+
dirPath := path.Dir(result.newName)
207+
if err := syncDirectory(dirPath); err != nil {
208+
slog.Warn("failed to sync directory after rename", "file", filepath, "dir", dirPath, "error", err)
209+
// Continue anyway - sync is a performance optimization, not critical for correctness
210+
}
203211
}
204212
}
205213
} else {
@@ -294,6 +302,7 @@ func analyzeWARCFile(filepath string, verbose bool, force bool) mendResult {
294302
return result
295303
}
296304
defer f.Close()
305+
defer reader.Close()
297306

298307
var lastValidEndPos int64 = 0
299308

@@ -377,6 +386,20 @@ func analyzeWARCFile(filepath string, verbose bool, force bool) mendResult {
377386
return result
378387
}
379388

389+
// syncDirectory syncs the directory to ensure file operations (rename, truncate) are persisted to disk
390+
func syncDirectory(dirPath string) error {
391+
dir, err := os.Open(dirPath)
392+
if err != nil {
393+
return fmt.Errorf("failed to open directory for sync: %w", err)
394+
}
395+
defer dir.Close()
396+
397+
if err := dir.Sync(); err != nil {
398+
return fmt.Errorf("failed to sync directory: %w", err)
399+
}
400+
return nil
401+
}
402+
380403
func truncateFile(filepath string, position int64) error {
381404
file, err := os.OpenFile(filepath, os.O_RDWR, 0)
382405
if err != nil {
@@ -388,6 +411,11 @@ func truncateFile(filepath string, position int64) error {
388411
return fmt.Errorf("failed to truncate file: %w", err)
389412
}
390413

414+
// Sync to disk to ensure changes are persisted before subsequent operations
415+
if err := file.Sync(); err != nil {
416+
return fmt.Errorf("failed to sync file after truncation: %w", err)
417+
}
418+
391419
return nil
392420
}
393421

0 commit comments

Comments
 (0)