fix(02): write fixtures exclusively and only on successful flush (WR-01)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jakub Zych
2026-09-17 14:41:18 +02:00
parent 5994e671b3
commit 7e70afe819
5 changed files with 92 additions and 9 deletions

View File

@@ -49,6 +49,15 @@ func ParseFlow(raw []byte) (Flow, error) {
// SaveFlow writes a validated flow atomically, syncing before rename.
func SaveFlow(path string, flow Flow) error {
return saveFlow(path, flow, false)
}
// SaveFlowExclusive writes a validated flow and fails if path already exists.
func SaveFlowExclusive(path string, flow Flow) error {
return saveFlow(path, flow, true)
}
func saveFlow(path string, flow Flow, exclusive bool) error {
if err := validateFlow(flow); err != nil {
return err
}
@@ -62,6 +71,30 @@ func SaveFlow(path string, flow Flow) error {
return fmt.Errorf("tide: create fixture dir: %w", err)
}
}
if exclusive {
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o644)
if err != nil {
return fmt.Errorf("tide: create fixture: %w", err)
}
ok := false
defer func() {
_ = f.Close()
if !ok {
_ = os.Remove(path)
}
}()
if _, err := f.Write(raw); err != nil {
return fmt.Errorf("tide: write fixture: %w", err)
}
if err := f.Sync(); err != nil {
return fmt.Errorf("tide: sync fixture: %w", err)
}
if err := f.Close(); err != nil {
return fmt.Errorf("tide: close fixture: %w", err)
}
ok = true
return nil
}
tmp, err := os.CreateTemp(dir, ".tide-*.tmp")
if err != nil {
return fmt.Errorf("tide: create temp fixture: %w", err)