Repository navigation
Naprawy/audyt 2026 09 23 - #4
Merged
Merged
Conversation
The queue read goes through `rclone rc vfs/stats`. When it timed out the caller got nil, substituted zeros for every counter, and `UploadState.from` concluded `.upToDate` — so both `drive-status` and the app card announced "Wszystko wysłane na Google Drive" while 386 bands were still waiting. It happened twice on 23 September, and `drive-status` printed the contradiction in plain sight: "Kolejka wysylki: (interfejs rc nieosiagalny)" two lines above the all-clear. Missing numbers are not zeros. `UploadState` gains `.queueUnknown`, which is not nominal, so the menu bar cannot go green on it; `from(...)` now takes a `queueKnown:` argument with no default, which forces every call site to answer the question it used to skip. `BufferStatus` defaults it to false, so an unpopulated status reads as unmeasured rather than empty. The three-state verdict no longer fits two booleans, so the badge moves onto `UploadState` itself, and the views stop claiming "Brak zaległości" from counters nobody read. Also raises the read timeout from 30 s to 60 s: the same call was measured at 36.7 s under a saturated buffer, and at 0.03 s a second later. That alone would not have fixed anything — a slower answer is still no answer — but it makes the question worth asking. Verified on a live bad sample: with the mount up and rclone refusing to answer, the new binary prints "Nie wiadomo, co czeka w kolejce". Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…wyslane" `CMLock` bylo MARTWYM KODEM - 241 linii mechanizmu blokad, ktorego nie wolalo ani jedno miejsce w repozytorium, takze zaden test. `attach()`, `detach()`, `verify()` i `create()` nie mialy wiec zadnego wzajemnego wykluczenia, a `detach()` ma okno ~10,5 min (sleep 35 s + drenaz do 600 s), w ktore tik `gdrive-attach` (StartInterval 900) trafia z duzym prawdopodobienstwem: widzi `.detached`, podpina obraz z powrotem, Time Machine rusza z zapisem, a `prepare-shutdown` konczy drenaz i wypisuje "Mozna restartowac". Teraz te cztery operacje ida przez `withCMLock`, a nieudane zdobycie blokady zwraca `busyResult`, nie milczacy sukces. `acquire()` weryfikuje tez zapis PID-a na sciezce "katalog utworzony" - dotad robila to tylko sciezka przejecia, wiec proces przerwany miedzy `createDirectory` a `writePid()` byl uznawany za osierocony i blokada trafiala do DWOCH wlascicieli naraz. "Nie wiem" czytane jako dobra odpowiedz, cztery razy: - `isQuiet` ignorowalo `erroredFiles`. Pasma porzucone przez rclone wypadaja z kolejki, wiec `detach()` meldowal "wszystko wyslane na Google Drive", a `safeToRebootNow()` mowil TAK - przy danych istniejacych tylko lokalnie. Czekanie chodzi teraz po `isIdle`, werdykt po `isQuiet`: gdyby czekac na `isQuiet`, kazde podpiecie placiloby pelne 600 s, bo porzucone pasma zostaja w liczniku do konca zycia procesu rclone. - `vfs/stats` bez sekcji `diskCache` dawalo komplet ZER zamiast `nil`, bo fallback `?? json` plus `number()` zwracajace 0 dla brakujacego klucza przechodzily walidacje. `queueKnown` bylo wtedy prawda i znow padalo "Wszystko wyslane". To ten sam wzorzec, ktory naprawiono wyzej przez `queueUnknown`, tylko przesuniety do parsowania - ktore siedzialo w funkcji async i nie dalo sie przetestowac. Wydzielone i pokryte testem. - `ImageProbe` polykalo bledy LISTOWANIA (`try? regularFiles()`), wiec ENXIO na samym katalogu dawalo `.nothingToProbe`, a `attachment` mapowalo to na `.attached`. Martwy obraz uchodzil za zywy - awaria z 22.09 wejsciem, ktorego tamta poprawka nie objela. - `mountPoints()` i `mountTable()` szly przez `/sbin/mount` BEZ limitu czasu, czyli pytaly o wolumen, ktory bywa martwy, tym sposobem, ktory na nim wisi. Zamiast ograniczac ten tryb awarii - usuniety: `getmntinfo(MNT_NOWAIT)` czyta tablice z pamieci jadra, bez procesu i bez dotykania systemu plikow. `MNT_WAIT` wolalby `VFS_STATFS` na kazdym montowaniu i wieszalby sie tak samo. `create()` sprawdzalo istnienie obrazu przez `fileExists` na cache FUSE i - w przeciwienstwie do `attach-image` - nie czekalo na `BufferReadiness`. W oknie, gdy rclone wystawil montowanie przed wczytaniem katalogu, straznik "obraz juz istnieje" przepuszczal, a `hdiutil create` szedl na sciezke istniejacego backupu, z piecioma ponowieniami. Teraz nieobecnosc potwierdza `rclone lsf` na zdalnym, a BRAK ODPOWIEDZI PRZERYWA - operacja nieodwracalna nie moze isc naprzod bez pewnosci. `verify()` meldowalo "Obraz NIESPOJNY", gdy `fsck_apfs` padl, bo tik agenta wyrwal mu urzadzenie - falszywy alarm o utracie backupu. `attach-image` rozroznia teraz sukces / pominiecie (kod 0) / awarie (kod 1) po typie `CMActionResult.Disposition`, a nie po tekscie: "zajete przez inna operacje" nie jest awaria i nie ma prawa zapisywac sie jako awaria w logu bledow. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ma wykryc
`ProcessRunner.run` ma `timeout` domyslnie `nil`, a `TimeMachineStatus` wolalo
`tmutil` BEZ limitu we wszystkich siedmiu miejscach. Przy martwym montowaniu
FUSE-T (incydent ENXIO z 22.09) `tmutil destinationinfo` blokuje sie
w nieprzerywalnym I/O, `BackupHealth.currentReport` nigdy nie wraca, a launchd
ze `StartInterval` NIE odpala drugiej instancji, dopoki zyje pierwsza - czujka
milkla NA STALE. Naglowek `BackupHealth.swift` deklarowal dokladnie odwrotnosc
tego stanu i zostal poprawiony.
Limit 90 s na wspolnym wejsciu, dobrany NIE pod "ile zwykle trwa" (ulamek
sekundy), tylko z zapasem dwoch rzedow wielkosci - bo 120 s dobrane pod czysty
start juz raz zabraklo o 10 s po awarii. Realne maksimum czekania to 100 s
(SIGTERM -> SIGKILL -> poddanie sie) przy oknie czujki 1800 s. Brak odpowiedzi
nie jest juz `false`: doszly `runningState() -> Bool?` i `destinationReading()`,
a `nil` daje OSOBNY problem "tmutil nie odpowiada - nie wiadomo, gdzie idzie
backup", a nie "Time Machine nie wskazuje na CloudMachine" (ten drugi
wysylalby czlowieka do przestawiania celu, ktory jest ustawiony dobrze).
Dozorca uznawal pauze za wykonana, nie patrzac na wynik `tmutil stopbackup`
(`_ = try? await ...`, a przejscie stanu BEZWARUNKOWE). Gdy polecenie padlo
- brak uprawnien albo przekroczony limit - stan szedl na `.pausedForBuffer`,
a `stopBackup()` wola sie tylko przy ZMIANIE stanu, wiec nigdy nie ponawial.
Time Machine pisal dalej, dozorca czekal na drenaz, dysk zapelnial sie do
konca, a w logu stalo "PAUZA ... czekam na wysylke".
`.pausedForQuota` (brak miejsca na Google Drive) dzielila galaz wznowienia
z `.pausedForBuffer`, a warunek patrzyl na bufor i wolne miejsce LOKALNEGO
dysku - o miejscu na Dysku nie wiedzial nic. `hitStorageQuota()` czyta tylko
30 minut logu rclone, wiec po zatrzymaniu Time Machine wpisy sie starzaly
i pauza spadala sama. Wyjscie wymaga teraz POZYTYWNEGO dowodu z `remoteQuota()`;
brak odpowiedzi PODTRZYMUJE pauze.
`freeGB()` zwracalo 0 przy nieudanym `statfs`. Warunek pauzy byl wtedy
spelniony natychmiast, a warunek wznowienia NIGDY - dozorca wstrzymywal Time
Machine i nie wznawial go juz nigdy. Teraz `Int?`; osobny test pilnuje, ze
ZMIERZONE zero nadal pauzuje, zeby ta poprawka nie przeszla w druga skrajnosc.
Panel nie pytal ANI RAZU o date ostatniej UDANEJ kopii - `grep BackupHealth`
po `CloudMachineApp/` nie dawal zadnego trafienia. Montowanie stoi, obraz
podpiety, kolejka pusta, Time Machine od dwoch dni nie dokonczyl kopii -
i swiecilo "Sprawny / Gotowe". To jest awaria opisana w naglowku
`BackupHealth.swift` jako najgrozniejsza w tym systemie.
Nieudane `osascript` bylo wyrzucane przez `_ = try?`, a `report()` i tak
zapisywalo `lastSummary` i `lastAlertAt` - alarm ginal po cichu na 12 h.
Przypomnienie i tak nie dzialalo, bo `summary` zawiera wiek awarii ("od 3 h"),
wiec zmienialo sie CO GODZINE i powiadomienie wracalo przy kazdym przebiegu.
`connect` chodzilo na rclone z Homebrew, ktorego wg README na tej maszynie nie
ma, podczas gdy `isConfigured` w tym samym pliku idzie przez wlasna binarke.
Po dolozeniu `Attachment.unknown` wyrazenie `attached: attachment != .detached`
zaczelo dawac `true` - czujka MILCZALABY o stanie, ktorego nie zna. `mounted`
i `attached` sa teraz trojstanowe, a brak odczytu daje wlasny problem.
ZNANY OSAD, rozstrzygniety swiadomie: `CloudMachineController.swift:124` nadal
czyta `isMounted`, wiec panel przy nieodczytanej tablicy montowan pokaze
"Bufor nie dziala". Po przebudowie na `getmntinfo` ten odczyt idzie z pamieci
jadra i praktycznie nie ma jak zawiesc, skutkiem jest falszywy ALARM (nie
cisza), a panel odswieza sie co 10 s. Trojstanowosc wymagalaby zmiany
`UploadState.from(mounted:)` i dwunastu testow kodujacych dzisiejszy kontrakt
- nie warte tego dla galezi, do ktorej realnie nie da sie dojsc.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
mbeczynski
added a commit
that referenced
this pull request
Sep 25, 2026
CI CloudMachine pada od scalenia PR #4 (2026-09-23); ostatni zielony przebieg to 2026-09-22. Przyczyna: `swift format lint --strict` zglasza piec linii dluzszych niz limit. To NIE jest zmiana zachowania - wylacznie zawijanie wierszy. Zadna instrukcja nie zostala dodana ani usunieta. DLACZEGO TO WAZNIEJSZE NIZ PIEC WIERSZY: przez dwa dni zadna zmiana w tym repozytorium nie byla sprawdzana przez build ani testy, bo sygnal juz swiecil na czerwono z innego powodu. Kolejna wada wjechalaby na main bez ostrzezenia, a nikt nie odroznilby nowej porazki od tej starej. Zmierzone tym samym poleceniem, ktorego uzywa CI: przed - piec bledow `[LineLength]`, po - zero. `swift build` i `swift test` przechodza: 224 testy, 0 porazek. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NQC6qZ3rTwghioqdpLDckT
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.