Now Reading: Brag Files 1. – Amire büszke vagyok a melóban

Loading

Brag Files 1. – Amire büszke vagyok a melóban

Mert ne mindig csak a lelki csiganyál legyen itt, így összeírtam, mit csináltam az utóbbi hónapokban: pontosabban az első 6 hónapom alatt. Saját magamat is motiválom ezzel és könnyebb lesz az éves fizetésemelést kiharcolni. Ezt időnként érdemes megtenni és emg is fogom tenni itt a blogon is, minden negyed- vagy félévben, esetleg évente, mert különben az ember fejében az egész összeáll egyetlen hosszú munkanappá, amelyen megivott valamit, megnyitott negyven böngészőfület, és valaki megkérdezte, hogy kész van-e már?

Mert miért is legyen álszerény: a jegyzeteimben akadt néhány dolog, amire már most azt tudom mondani, hogy ezt kurva jól megcsináltam.

Lesznek számok, adatbázisok, egymásra váró szálak és egy fájlfeldolgozó, amelynek egészen sajátos elképzelései voltak a minőségmegőrzésről. Aki önfényezéstől tart, jól látja a helyzetet.

Bekapcsoltam a reflektort. Szakmai dolgok következnek, ami egy számlázási cég ticketeredejében előfordul.

Kezdjük egy PostgreSQL-lekérdezéssel. Loadtesten, meleg cache mellett 12 752 milliszekundumról 7,7 milliszekundumra ment le a futásideje. Hideg cache mellett 35 510-ről 379-re. A régi és az új keresés találati halmazát valós adatokon összehasonlítottam: a diff üres volt. Ugyanazt találta meg, csak közben nem kellett megöregedni.

Az indexelési irányt a DBA adta: trigram GIN indexek és a keresés szétbontása. Én megcsináltam a migrációt CONCURRENTLY indexépítéssel, átírtam a keresést IN alá rendezett UNION ALL ágakra, majd végigmértem az egészet. Arra is figyelni kellett, hogy az összefűzött keresési kifejezés pontosan egyezzen az indexdefinícióval. Az adatbázis ebben kevéssé fogékony a „de hát majdnem ugyanaz” című érvelésre.

Nekem ebben a legjobb rész az üres diff. Gyors lekérdezést ugyanis könnyű írni, ha az eredmény helyességét fakultatív programnak tekintjük. A SELECT 1 például egészen fürge, csak a felhasználók idővel szóvá teszik, hogy mindig ugyanazt találják.

Itt megmaradt a működés, eltűnt a várakozás. Ezt szívesen felírom magamnak.

Egy másik nyomozásnál sessionkezelés és replika-késés találkozott. A mentés utáni ellenőrzés olyan állapotot keresett a replikán, amely oda még nem ért át. A friss írás sikerült, a visszaolvasás viszont ezt nem tudta megerősíteni.

Erre építettem külön, izolált környezetet: saját PostgreSQL, Tomcat, Valkey primary–replica pár, valódi alkalmazáscsomag, szándékosan elrontott replikáció. Ebben a hibás változattal húsz kérésből nulla sikerült, a javítással húszból húsz. Végre lehetett ugyanazt a hibát előállítani, nem csak ülni előtte, hátha ma is megtisztel a jelenlétével.

A kézenfekvő megoldás az lett volna, hogy minden olvasást a primaryra küldök. Ennek viszont ára volt. A terhelési észrevétel után tovább szűkítettem a javítást: csak a mentés utáni, konzisztenciát igénylő létezésellenőrzés került oda, külön writer kapcsolaton. A mért primary-forgalmi többlet így 189 százalék helyett 0,9 százalék lett. A javítás még MR-ben van; ezek az izolált reprodukció és ellenőrzés eredményei.

Ezt szeretem a szakmában. Amikor az első működő megoldást még meg lehet csinálni rendesen is, és a kettő közötti különbség nem esztétikai vita, hanem ott van a mérésben.

Egy másik jegynél: a MTA helyesírási szakszolgálatát kérdeztem meg a saját nyelvészeti állspontomról egy jogi-adózási fogalom helyesírásával kapcsolatban. Igazam volt, a helyesírást rendeztük. Ez is önjáró jegy volt.

Fájlfeldolgozásnál belefutottam egy olyan hibába, amelyben a típusfelismerés kiterjesztés nélküli szerveroldali fájlnéven dolgozott. A Files.probeContentType() az adott környezetben null-t adott, a PDF pedig bekerült az ImageMagick/Ghostscript raszterizáló ágába. Hibajelzés nélkül. A folyamat sikeresen elvégezte azt, amit kurvára nem kellett volna.

A reprodukcióban egy 773 bájtos vektoros PDF-ből 41 kilobájtos raszteres fájl lett. Rosszabb minőség, nagyobb méret: ritka, hogy egy megoldás ennyire következetesen mindkét irányban veszítsen.

A javításnál a %PDF- fejléc felismerésével választottam külön a PDF-ágat, védelmet tettem a képkonverzió elé, és naplózhatóvá tettem a konverziókat. A teszteket valódi fájlokra építettem át, mert a mockolt változatok ezt a regressziót szépen átengedték. Két lokális alkalmazáspéldánnyal ellenőriztem az előtte–utána állapotot; a javítás után a feltöltött és a tárolt fájl ellenőrzőösszege egyezett.

A helyreállításhoz külön Spring Batch eszközt is készítettem: alapból dry-run, tényleges módosítás csak explicit kapcsolóval, backup, ellenőrzőösszeg-vizsgálat, a már megfelelő fájlok kihagyása. Lokális alkalmazó futással is ellenőriztem. Egy javítóprogramnak azért illik magasabbra tennie a lécet annál, hogy „reméljük, ez most kevésbé rontja el”.

A szkenner megnyugodott volna. Én még nem.

Egy függőségfrissítés papíron egyszerű verzióemelésnek indult. Csakhogy a szkenner által megnevezett csomag és a leveleket ténylegesen küldő SMTP-provider nem ugyanaz volt. A kért egyetlen pin átírásával a jelentés szebb lett volna, miközben a futó implementáció javítása elmarad.

Úgyhogy megnéztem, mi kerül ténylegesen a classpathra, és több összeállítást lefuttattam a valódi JAR-okkal. A javításból végül a párhuzamos mail-implementációk rendbetétele is lett: API-függőségek, kizárások, verziók, kompatibilitás. A duplikált osztályok száma 139-ről nullára csökkent. Valódi SMTP- és SMTPS-küldéssel, bájtazonos MIME-tartalommal ellenőriztem, hogy a levelezés közben levelezés maradt.

A dependency tree ilyenkor rendkívül szórakoztató olvasmány. Az ember belenéz, és kiderül, hogy ugyanarra a feladatra többen jelentkeztek, mind hoztak saját osztályokat, és a futtatókörnyezetre bízták a családi konfliktus rendezését.

Én jobban szeretem, ha tudom, melyik kód fut. Különösen akkor, amikor éppen azt állítjuk róla, hogy kijavítottunk benne valamit.

A tesztek nem gondolkodtak. Deadlock volt.

Volt egy tesztfutás, amely húsz percen túl is rendületlenül nem csinált semmit. Elővettem a jstack-et. A szinkron adatbázisos log-appender az adatbázis indulására várt, miközben tartott egy lockot. Az adatbázist indító szál pedig ugyanazon a lockon szeretett volna naplózni.

Két szál, mindkettőnek teljesen érthető szándékai vannak, együtt mégis használhatatlanok. Ezt most kivételesen nem társadalmi megfigyelésnek szánom.

A tesztkonfigurációban aszinkron appenderre váltottam neverBlock beállítással. Az első CI-futásnál előkerült logolási ciklust aztán additivity=false-szal rendeztem. A végén 675 core teszt lefutott beállás nélkül.

Másik ügyben az is kiderült, hogy egy tesztosztály olyan modulban lakik, amelyet a CI reaktora nem futtat. Átvittem a futtatott core modulba. Regressziós teszteknél pedig mutációs próbákkal is ellenőriztem, hogy a hibás működést valóban elkapják.

Szeretem a zöld teszteket, de azért érdekel, mitől zöldek. Az, hogy nem futottak le, kétségtelenül csökkenti a hibázás esélyét. A fejlesztésben viszont ezt a fajta nyugalmat nem keresem.

Frontenden is akadt öröm. Firefox alatt egy PDF-előnézetnél majdnem egy másodpercre felvillant egy oda nem illő gomb. Az <object> fallback tartalma jelent meg, amíg a PDF URL-je késleltetve meg nem érkezett. Ráadásul a PDF-megjelenítő ellenőrzése addig olyan állapotban futott, amelyben nem tudott használható eredményt adni.

Átrendeztem az időzítést, helyretettem az ellenőrzést, majd Playwrighttal, Firefoxon, húsz milliszekundumos mintavétellel mértem a gomb láthatóságát. 987 milliszekundumról a mérési sorozatban nullára ment le.

Apróság? Persze. Egy pillanatra felvillanó hülyeség a képernyőn. De ezt is jó érzés úgy kijavítani, hogy a végén nem annyi az eredmény: nálam most éppen nem látszott.

Közben a saját munkakörnyezetemet is automatizáltam: napi szinkronizálás, külön worktree-ből végzett műveletek, sémadrift-ellenőrzés, migrációk, duplikált JAR-okat kereső buildsegéd. Az ismétlődő nyomozásokból pedig újrahasználható tesztreceptek és technikai jegyzetek készültek. Ezek a saját eszközeim; nem fogom csapatszintű reformnak nevezni azt, amit a saját gépemen raktam rendbe. Attól még reggelente rohadt jó, hogy nem nekem kell mindent újra végigkattintanom.

Ezért volt hasznos összeírni az egészet. A fejemben könnyen egybemosódik a nyomozás, a javítás, a teszt, a review és a következő feladat. A végén már csak arra emlékszem, hogy sokat ültem a gépnél.

Most viszont ott vannak az eredmények. Lekérdezések futásideje, reprodukálható hibák, kijavított adatfeldolgozás, kitakarított függőségek, ténylegesen működő tesztek. Kaptam hozzá jó ötleteket és segítséget, én pedig beletettem azt a részt, ami az enyém volt.

És ez a részem jó lett.

Úgyhogy most nem írok mögé három bekezdésnyi mentegetőzést. Örülök neki, büszke vagyok rá, és szeretem, hogy ilyen problémákon dolgozhatok.

A szerénység kedvéért pedig biztosan nem rakom vissza a Seq Scan-t.

svg

What do you think?

Show comments / Leave a comment

Leave a reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Loading
svg
Quick Navigation
  • 01

    Brag Files 1. – Amire büszke vagyok a melóban