Data-loss hunt: R-1188 (c) proven — a leftover .felhom-restoring blocks every retry of the second drive's whole restore
gates / gates (push) Successful in 13m33s

This commit is contained in:
admin committed 2026-10-20 13:11:32 +02:00
1 parent a942ae90d6
commit d750a90d0e
4 files changed
+32 -2

No files matched your search

@@ -26,7 +26,7 @@ Register: none of the candidates below is in OPEN-ITEMS or CLOSED-ITEMS (searche
| R7 `.fab` import has no guard / undo / record | PLAUSIBLE | defect | |
| R8 `.fab` import drops the family gate | **CONFIRMED LIVE** on 9202 (`C3-R1187e-fab-family-gate/`: stranger 401 before, 200 after the import) → **R-1191 (P1)** | defect | `cmd/controller/main.go:3517-3530`, `stacks/family_gate.go:173-190` |
| R9–R11, R13, R14 | PLAUSIBLE | defect / design (R13) | low |
| R12 interrupted whole restore leaves `*.felhom-restoring`, every retry fails | CONFIRMED-CODE | defect | `tier2_whole.go:86-87` O_EXCL; removed only on an in-process error |
| R12 interrupted whole restore leaves `*.felhom-restoring`, every retry fails | **CONFIRMED** (unit test: `C3-R12-leftover-temp/`) → R-1188 (c) | defect | `tier2_whole.go:86-87` O_EXCL; removed only on an in-process error |
| **D2** a missing / emptied app folder deletes its second-drive copy within one night | **CONFIRMED** for a MISSING folder (unit test, production code + real copy seam: `C3-D2-missing-leg/` — mirror of `photos` deleted, run „ok", the warning says only „nem kerültek a másodlagos mentésbe"); the EMPTIED case CONFIRMED-CODE (`rsyncMirror` = `rsync -a --delete`, `tier2.go:744-751`; the test seam does not delete) | defect-shaped corner of a choice: 07 §8.2 „data legs are NOT guarded" is about a leg LEAVING the class set; this is a declared leg that is MISSING, which the code itself logs as a gap (`tier2_capture.go:55-61`) and then reconciles away (`tier2.go:454`) | P1 for optional legs (no other tier holds them) |
| D3 / T11 a host clock ahead silences the whole-guest tier; the hub reads the same clock | PLAUSIBLE (B6 #8 on the rehearsal VM is its live test) | defect | agent `localapi/server.go:1178-1190` |
| D5 a dump that fails its own check has already replaced the good one | **CONFIRMED** (unit test with a docker stub: `C3-D5-dump-replaced/`) → R-1185 | defect for the ORDER | `appbackup/dbdump.go:388-422`: size check, rename (`:399`), then `ValidateDump` |
@@ -0,0 +1,7 @@
# go test at controller 7ca59e2 (v0.336.0), scratch clone; 2026-10-20T11:11:31Z
=== RUN TestRehearsalR12_LeftoverTempBlocksEveryRetry
zz_rehearsal_r12_test.go:21: retry 1: err=fájlmásolás sikertelen: restoring appdata/app/p1.jpg: open /tmp/TestRehearsalR12_LeftoverTempBlocksEveryRetry3138873193/001/usb/appdata/app/p1.jpg.felhom-restoring: file exists; p1.jpg back=false; app restarted=true
zz_rehearsal_r12_test.go:21: retry 2: err=fájlmásolás sikertelen: restoring appdata/app/p1.jpg: open /tmp/TestRehearsalR12_LeftoverTempBlocksEveryRetry3138873193/001/usb/appdata/app/p1.jpg.felhom-restoring: file exists; p1.jpg back=false; app restarted=true
--- PASS: TestRehearsalR12_LeftoverTempBlocksEveryRetry (0.01s)
PASS
ok gitea.dooplex.hu/admin/felhom-controller/internal/backup 0.020s
@@ -0,0 +1,23 @@
package backup
// THROWAWAY proof for the 2026-10-20 data-loss hunt (R-1188 c). Never committed. A crash during the whole restore's
// file copy leaves `<file>.felhom-restoring` behind (the copy writes it with O_EXCL); the retry then meets it.
import (
"os"
"path/filepath"
"testing"
)
func TestRehearsalR12_LeftoverTempBlocksEveryRetry(t *testing.T) {
f, _, liveLeg := wholeFixture(t)
// what a power cut in the middle of copying p1.jpg leaves on the live drive
if err := os.MkdirAll(liveLeg, 0o755); err != nil {
t.Fatal(err)
}
os.WriteFile(filepath.Join(liveLeg, "p1.jpg.felhom-restoring"), []byte("half"), 0o644)
for i := 1; i <= 2; i++ {
_, err := f.m.RestoreTier2Whole("app")
_, statErr := os.Stat(filepath.Join(liveLeg, "p1.jpg"))
t.Logf("retry %d: err=%v; p1.jpg back=%v; app restarted=%v", i, err, statErr == nil, f.fake.fullStarted)
}
}