Na ovoj stranici
U predavanju tima kompanije Crusoe za odnose sa programerima, koje je AI Engineer objavio 3. oktobra 2026. godine, pokrenut je PyTorch posao treniranja na dva A100 čvora. Zatim je samom sistemu za nadzor demonstracije javljeno da je jedan GPU izbacio grešku XID 79. Čvor je označen kao nedostupan, a posao otkazan. Proces je dobio SIGTERM i „do dva minuta da obradi taj SIGTERM i sačuva kontrolne tačke ili isprazni logove“. Uskočio je rezervni čvor, i „slurm posao će se ponovo pokrenuti. Učitaće kontrolnu tačku i nastaviti treniranje tamo gde je stao“. Nešto manje od petnaest minuta od početka do kraja. Niko nije bio pozvan na dežurstvo.
Sinhronizacija je mnogo manja životinja od treniranja. Pitanje je isto. Šta je pokretanju potrebno da bi gašenje radnog procesa koštalo nekoliko minuta i nijedan duplikat?
Ovo je odgovor za Tajo sopstveni pokretač sinhronizacije, pročitan iz koda, a ne iz brošure. Reverse ETL opisuje oblik posla. Ovo je ono što se dešava kada posao umre.
Pratite jedan kontakt
Pokretanje čita izvor stranicu po stranicu, od sačuvanog kursora. Nazovimo kursor stranice c3, a naš kontakt 212. zapisom na toj stranici. Tri stvari važe za taj kontakt pre nego što se išta upiše.
Prvo, ima ključ isporuke. Ključ je heš ID-ja sinhronizacije, izvora, kursora stranice, pozicije na stranici i samog zapisa. Kursor i zapis ulaze u heš i nikada nisu ugrađeni u ključ, pa ključ ne nosi nijednu imejl adresu.
Drugo, upis prolazi kroz registar, a ne direktno do odredišta. Pre poziva odredištu ključ se preuzima kao „na čekanju“. Kada upis uspe, red se označava kao završen i čuva sedam dana.
Treće, kursor se nije pomerio. Pomera se samo na kraju serije, samo ako je svaki zapis u toj seriji stigao, i samo nakon što je pokretanje dokazalo da je i dalje vlasnik sinhronizacije.
Sada ugasite radni proces između upisa i kontrolne tačke.
Na SIGTERM se svaki radni proces reda čekanja prazni uz jedan zajednički rok od petnaest sekundi, a proces izlazi posle dvadeset pet sekundi, šta god da se još izvršava; systemd mu daje četrdeset pet pre nego što ga ubije. Pokretanje koje se nije završilo u tom prozoru i dalje je označeno kao u toku, a sledeći radni proces ga preuzima kroz mehanizam reda za oporavak zaglavljenih poslova. Kod naglog gašenja nema pražnjenja uopšte. U oba slučaja važe iste dve činjenice. Odredište ima naš kontakt. Naš kursor i dalje kaže c3.
Ponavljanje
Sledeće pokretanje počinje od c3, čita istu stranicu, izvodi isti ključ za 212. zapis i pita registar. Registar kaže: završeno. Odredište se ne poziva; sačuvani rezultat se reprodukuje i pokretanje ide dalje. Na putanji za masovni uvoz, gde Brevo endpoint za uvoz prima celu stranicu jednim pozivom, ista provera se izvršava po ključu pre nego što se zahtev sastavi. Stranica u kojoj je svaki ključ već završen ne šalje ništa.
To je ceo trik, i vredi reći zašto radi. Ključ se izvodi iz kursora stranice na početku serije, a ne iz pokretanja koje se slučajno izvršavalo. Pad, ponovni pokušaj šezdeset sekundi kasnije i zakazano pokretanje sutra izvode isti ključ za isti zapis. Registru je svejedno ko od njih pita.
Sada cena. Registar zaboravlja posle sedam dana. Komentar u samom kodu kaže da sedam dana pokriva odloženi ponovni pokušaj i kratak prekid rada, i to je sve što tvrdi. Ponavljanje od kursora starijeg od toga upisuje ponovo. A pokretanje prekinuto naglim gašenjem može da čeka. Zakup mrtvog pokretanja važi do petnaest minuta, a kod zakazane sinhronizacije pokretanje čiji je zakup slobodan biva pokupljeno i ponovo zakazano tek kada je počelo pre više od sat vremena. Demonstracija kompanije Crusoe se vraća za manje od petnaest minuta. Naša ne uvek.
Ko je vlasnik sinhronizacije dok se ponovo pokreće
U svakom trenutku jedno pokretanje je vlasnik sinhronizacije. Pokretanje uzima zakup u Redisu sa sopstvenim tokenom, trajanjem od petnaest minuta i obnavljanjem na svakih pet minuta. Pre svake kontrolne tačke potvrđuje da i dalje drži taj zakup. Ako ga ne drži, zaustavlja se. Pokretanje se beleži jednostavnom rečenicom koju će osoba pročitati: „The run lost its slot part-way through and stopped to avoid writing twice.“ (pokretanje je usput izgubilo svoje mesto i zaustavilo se da ne bi upisalo dvaput). Drugo pokretanje koje naleti na živog vlasnika ne pokušava se ponovo. Završava se porukom „Another run of this sync was already in progress“ (drugo pokretanje ove sinhronizacije je već bilo u toku), a sledeće zakazano pokretanje počinje normalno.
Vlasništvo nad ispravkom je takođe zapisano. Svaki kod greške mapira se na jednu rečenicu o tome šta se dogodilo, jednu o tome šta dalje uraditi, i na vlasnika: vas ili Tajo. Odredište koje je odbilo svaki zapis jer je mapiranje pogrešno je vaše. Izgubljeni zakup je naš. Stranica pokretanja pokazuje sledeći korak; vodič za oporavak sinhronizacije navodi koje je od ta dva.
Do sada je ovo laka polovina. Pad košta jedno ponavljanje i ništa ne stiže dvaput. Dva incidenta su nas naučila drugu polovinu.
Greška za greškom
Jedna sinhronizacija je padala iznova i iznova. Ne u uskoj petlji: jednom po intervalu planera, pokretanje za pokretanjem, svaki put sa istom porukom, da prilagođeni ID ne sme da sadrži dvotačku. Pokretanje nikada nije stiglo do odredišta. Umiralo je dok je stavljano u red, pre nego što ga je bilo koji pokretač video, pa upozorenje vezano za pokretač nikada nije imalo na šta da reaguje.
Ništa nije pratilo niz. To je ceo nalaz.
Ispravka je prekidač. Posle svake zabeležene greške on čita poslednjih pet završenih pokretanja sinhronizacije od njene poslednje izmene. Ako su svih pet greške, pauzira sinhronizaciju, upisuje jedan red u revizioni dnevnik sa razlogom circuit_breaker_tripped i šalje jedno kritično upozorenje. Niz se izvodi iz sačuvanih pokretanja, a ne iz brojača u radnom procesu. Računa se greška zabeležena bilo kojim putem, uključujući i grešku pri stavljanju u red koja je izazvala incident. Komentar u kodu kaže da bi taj incident zaustavio na petom pokretanju. Jedan uspeh poništava niz. Uklanjanje pauze ponovo naoružava prekidač umesto da ga ponovo aktivira na starim redovima. Vodič za Shopify konektor kaže isto u jednom redu: posle pet uzastopnih neuspešnih pokretanja sinhronizacija se sama pauzira, a njena stranica prikazuje poslednju grešku.
Ono što prekidač ne radi jeste da bilo šta popravi. Crusoe zamenjuje čvor i ponovo pokreće posao bez pitanja. Tajo se zaustavlja i pita: pauzirana sinhronizacija ostaje pauzirana dok osoba ne otkloni uzrok i ponovo je ne objavi. Oprezno podrazumevano ponašanje je namerno: automatski ponovni pokušaj sinhronizacije koja upisuje u zapise kupaca i sam je upis.
Tišina koju niko nije video
Prigovor je fer i glasi ovako: „Prekidač koji pauzira posle pet grešaka uhvatio bi i drugi incident. Zašto praviti drugog čuvara?“ Zato što drugi incident nije izgledao kao greška. Dugo je jedan radni prostor imao aktivnu sinhronizaciju, sve veću gomilu redova sa greškama i nijedan uspeh, nikada, i ništa nije poslalo upozorenje. Svaki signal koji je postojao bio je vezan za aktivnost: pokretanje je palo, stigao je webhook, budžet je premašen. Nula uspeha nije događaj. To je odsustvo događaja, a prekidač radi samo kada se zabeleži greška. Mrtav planer, zaglavljen red čekanja, radni proces koji se nikada ne podigne: oni ne beleže ništa, i prekidač se nikada ne probudi.
Budnik u lokomotivi (dead man’s handle) radi obrnuto. Mašinovođa mora stalno da ga pritiska, a tišina zaustavlja voz. Verzija za sinhronizaciju radi jednom na sat, trinaest minuta posle punog sata. Za svaki radni prostor sa aktivnom sinhronizacijom postavlja jedno pitanje: da li je ijedno pokretanje uspelo u poslednja dvadeset četiri sata? Radni prostor čija je najstarija aktivna sinhronizacija uključena pre manje od jednog dana ostaje na miru; još nije imao dan da uspe. Onaj koji je stariji i nem dobija jedno kritično upozorenje. Upozorenje kaže o kojoj je tišini reč: pokretanja su zabeležena, ali nijedno ne uspeva, ili nijedno pokretanje uopšte nije zabeleženo. Aktivira se jednom po incidentu. Oznaka u Redisu ga drži zatvorenim do prvog uspešnog pokretanja, a zatim se briše, pa sledeći incident ponovo šalje upozorenje.
Oba čuvara su stigla u jednom commitu, naknadno. Komentar prekidača kaže da bi zaustavio prvi incident na petom pokretanju. Komentar dead man provere kaže da sinhronizacija uključena davno, sa nula pokretanja, mora da pošalje upozorenje. Nijedan nije postojao kada je bio potreban. Napisali smo ih posle, sa oba incidenta zapisana u zaglavlju datoteke, da niko ne zaboravi zašto.
Šta je izgrađeno, a šta nije
Izgrađeno, u trenutku pisanja:
- Kursor se čuva na kraju svake čiste serije, i ponovo pri padu.
- Ključ isporuke svakog zapisa izvodi se iz kursora stranice i njegove pozicije i proverava u registru od sedam dana pre svakog poziva odredištu.
- Jedan zakup po sinhronizaciji, sa trajanjem od petnaest minuta.
- Pet pokušaja po pokretanju, sa razmakom koji raste počev od šezdeset sekundi.
- Prekidač koji pauzira sinhronizaciju posle pet uzastopnih grešaka i beleži zašto.
- Upozorenje, proveravano svakog sata, na dvadeset četiri sata bez uspeha.
Nije izgrađeno, i vredi znati pre nego što se oslonite na to:
- Dead man provera prati radni prostor, a ne sinhronizaciju. Jedna zdrava sinhronizacija sakriva nemu sestrinsku sinhronizaciju u istom radnom prostoru.
- Njeno upozorenje stiže do Tajo operatera: uvek kao red u logu, a kao Sentry, webhook ili imejl tamo gde je to podešeno. Ne pojavljuje se na stranici sinhronizacije. Pauza prekidača se pojavljuje.
- Ništa ne pokreće ponovo pauziranu sinhronizaciju. To radi osoba.
- Oporavak posle naglog gašenja nije brz. Zakup može da važi petnaest minuta, a čišćenje čeka sat vremena.
- Oba praga, pet grešaka i dvadeset četiri sata, jesu podešavanja implementacije. Ne možete ih podesiti po sinhronizaciji.
Dug niz gotovo savršenih koraka i dalje ne uspeva; izlaz je definisati konačno stanje i proveravati ga. Ovaj članak je operativna polovina toga. Definišite šta mrtvo pokretanje ostavlja za sobom, i proveravajte ono ništa koje tišina ostavlja za sobom.
Završna rečenica kompanije Crusoe bila je da su „greške neizbežne“. Naša ide korak dalje. Pad je bio laka polovina, jer je ostavio redove. Tišina je bila polovina koju smo morali da potražimo.
Često Postavljana Pitanja
Šta se dešava sa sinhronizacijom u toku kada radni proces padne usred serije?
Kursor i dalje pokazuje na početak prekinute serije, jer ga Tajo pomera tek kada serija čisto prođe. Sledeće pokretanje ponovo čita istu stranicu. Svaki zapis nosi ključ isporuke izveden iz kursora stranice i njegove pozicije, a registar čuva svaki završeni upis sedam dana, pa se zapisi koji su već upisani reprodukuju iz registra umesto da se odredištu pošalju drugi put.
Zašto ponovljena sinhronizacija ne upisuje isti kontakt dvaput?
Pre svakog poziva odredištu pokretanje proverava ključ isporuke zapisa u registru. Ključ je heš sinhronizacije, izvora, kursora stranice, pozicije na stranici i samog zapisa, pa pad, ponovni pokušaj minut kasnije i zakazano pokretanje sledećeg dana izvode isti ključ za isti zapis. Ključ koji je već označen kao završen unutar perioda od sedam dana ne šalje se ponovo.
Šta je dead man upozorenje za sinhronizaciju?
Provera koja se aktivira na odsustvo, a ne na grešku. Jednom na sat Tajo pregleda svaki radni prostor sa aktivnom sinhronizacijom i šalje upozorenje kada nijedno pokretanje nije uspelo u poslednja dvadeset četiri sata, uključujući slučaj kada uopšte nije zabeleženo nijedno pokretanje. Aktivira se jednom po incidentu i ponovo se naoružava posle prvog uspešnog pokretanja. Postoji zato što upozorenje na grešku može da vidi samo greške koje su zabeležene.