v0.297.0: burn-down round 2 — 24 small rows (R-591 R-568 R-567 R-363 R-547 R-10 R-552 R-251 R-104 R-619 R-362 R-675 R-256 R-257 R-240 R-365 R-425 R-565 R-564 R-603 R-454 R-208 R-457-swept) + the banner countdown and deepCopyStack twins; MinAgent 0.131.0
gates / gates (push) Failing after 50s

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-10-05 20:12:56 +02:00
parent 114ff2761a
commit 1453cfc69b
68 changed files with 3953 additions and 116 deletions
+19
View File
@@ -228,6 +228,17 @@ func DumpAll(ctx context.Context, dbs []DiscoveredDB, dumpDir string, logger *lo
return results
}
// syncDumpDir fsyncs a directory so a rename inside it survives a power cut (R-10). A variable so a
// test can observe the call; production never replaces it.
var syncDumpDir = func(dir string) error {
d, err := os.Open(dir)
if err != nil {
return err
}
defer d.Close()
return d.Sync()
}
// CanonicalDumpName is the app's own dump filename for one database: `<stack>-<dbtype>.sql`. It is
// the name the replay loop matches EXACTLY, which is why nothing else may ever be written to it.
func CanonicalDumpName(db DiscoveredDB) string {
@@ -393,6 +404,14 @@ func DumpOneTo(ctx context.Context, db DiscoveredDB, finalPath string, logger *l
result.Duration = time.Since(start)
return result
}
// R-10 (T-6E-1): the rename is durable only once the DIRECTORY entry is on disk. Without this a
// power cut right after the rename can leave the old dump (or none) under the final name, even
// though the data itself was fsynced above. Best-effort, like atomicPromoteTar's dir.Sync() in
// internal/backup/backup.go — the dump is already complete, so a failed dir sync is logged, not
// fatal. Pinned by TestDumpOneTo_SyncsTheDumpDirectoryAfterRename.
if err := syncDumpDir(dumpDir); err != nil {
logger.Printf("[DEBUG] DumpOne: syncing dump directory %s after rename failed (best-effort): %v", dumpDir, err)
}
result.FilePath = finalPath
result.Size = stat.Size()