Vlna vylepšení — zoznam dodávateľov v milisekundách, dávkové pravidlá kategórií, limity pre nový VPS
· Infraštruktúra
Konsolidovaná vlna vylepšení za obdobie 4. 8. – 13. 8. 2026. (1) Zoznam dodávateľov už nepočíta produkty pri každej požiadavke (64b72aaf, af4a50ee, c7ee452f, migrácia 497) — GET /vendors trval na produkcii 23–30 s, lebo join na produkty nemal podmienku na spoločnosť a Postgres sekvenčne prechádzal 265 364 riadkov produktov všetkých tenantov, aby spočítal 126 466 jedného. Migrácia 497 pridáva per-tenant tabuľku vendor_product_count, obnovovanú pri dokončení importu, flushi, čistení feedových kategórií, vytvorení či zmazaní produktu a presune produktu medzi dodávateľmi, plus 5-minútový sweep označených riadkov; filter „má produkty" je teraz EXISTS (1,84 ms). Stránka zároveň prestala každé 2 s načítavať celý zoznam — bežiaci dodávatelia sa sledujú jednotlivo. (2) Pravidlá mapovania kategórií sa vyhodnocujú dávkovo (5c3accc2) — aplikovanie mapovacích pravidiel na jeden produkt posielalo jeden SQL EXISTS na každé filtrovacie pravidlo, sekvenčne, teda ~1 937 spiatočných ciest na jediný produkt v kroku, ktorý beží nad katalógom 15 072 produktov. Odlišné filtre sa teraz vyhodnocujú po ~50 v jednom príkaze, plán deduplikácie aj vyhľadávanie podkategórií sú memoizované na spoločnosť popri už cachovanej sade pravidiel a počet spiatočných ciest klesol 1 533 → 36. Predikáty sa neprepisujú — obe cesty kompilujú cez rovnaký builder — a nekompilovateľný filter, zlyhaná dávka či priveľký filter degradujú na pôvodné správanie namiesto zlyhania produktu. (3) Limity kontajnerov prispôsobené posilnenému VPS (6f7a20f5) — stroj sme navýšili na 8 jadier / 31 GB, limity však stále mierili na staré 4 jadrá / 16 GB. Merané za 8 dní behu: postgres bol CPU-throttlovaný v 46,3 % období (138,7 hodiny čakania) a s 24 MB work_mem odlial 55 GB do 2 218 dočasných súborov, rabbitmq bol throttlovaný 18,3 %, api 11,8 %. shared_buffers 1536 MB → 3 GB, effective_cache_size 4608 MB → 9 GB, maintenance_work_mem 384 MB → 1 GB, work_mem 24 MB → 64 MB; každá premenná zdrojov v compose dostala fallback (24 ich nemalo, takže chýbajúci .env rozbil celý stack namiesto degradácie). (4) Koniec zbytočných pushov do napojených e-shopov (3af220d6, 9fbe1fc9, 31069c96, 0a71b949) — import zapisuje tabuľky produktu postupne a kandidátsky dopyt porovnával časové pečiatky, nie obsah, takže jeden importný cyklus vybral ten istý produkt viackrát a každý push po prvom niesol identický payload (na produkcii 7,4 pushov na produkt denne pri 20 823 produktoch, s automatickým resyncom Grandusu na strope 1 000 kandidátov pri zhruba polovici tikov). Produkt sa teraz pripustí až vtedy, keď je jeho najnovšia zmena 60 sekúnd v pokoji — rovnako pre Grandus, WooCommerce aj Shoptet — s poistkou proti vyhladovaniu zdvihnutou na 24 hodín. Súhrn dávky sa navyše vypíše vždy a počíta pushy bez zmeny obsahu, a signál „zmenili sa obrázky" používa presne tie štyri podmienky, ktoré používa samotný push. (5) Uzavreté krížové čítanie parametrov medzi tenantmi (56adf8db) — obidve čítania matice parametrov, nové aj pôvodné hromadné overenie súladu so šablónou, vyberali hodnoty parametrov len podľa id produktov prevzatých z tela požiadavky, bez akejkoľvek podmienky na spoločnosť. Prihlásený používateľ jednej spoločnosti tak mohol poslať id produktov inej spoločnosti a prečítať si ich hodnoty parametrov. Obe teraz filtrujú na denormalizovaný stĺpec company_id, ktorý každá hodnota parametra nesie od migrácie 235, takže predikát nemôže odrezať legitímne riadky. (6) Dlhé zlučovania duplicít už nepadajú na timeout proxy (68907792, 1e5657a3) — hromadné zlučovanie, behy uložených vyhľadávaní, jednotlivé zlúčenie aj jeho vrátenie nemali vlastnú nginx lokáciu, takže spadli pod všeobecný 60-sekundový read timeout, hoci hromadné zlučovanie je dokumentované ako viacminútové: administrátor dostal chybu brány, kým sa zlúčenia na pozadí ďalej zapisovali. Vývojová aj produkčná konfigurácia majú teraz vlastné 300-sekundové lokácie so zodpovedajúcimi klientskymi timeoutmi (globálny predvolený je 30 s) a beh ukončený timeoutom zamkne formulár a odkáže na históriu zlúčení namiesto toho, aby znova povolil tlačidlo nad behom, ktorý server pravdepodobne stále dokončuje. (7) Cenník predplatného sa vytvára zo zdroja a s korektnou daňou (81302629, 4db400a9, 385be5af) — štyri predajné balíčky a ich osem cien vytvára u platobného poskytovateľa jeden opakovateľne spustiteľný príkaz priamo z cenníka v kóde, párovaný cez metadáta, takže nedokončený beh sa dá bezpečne zopakovať, a existujúca cena sa nikdy neupravuje (predplatitelia si držia cenu, na ktorej sa dohodli). Každá cena vzniká ako suma bez DPH a označená daňovým kódom pre SaaS na firemné použitie namiesto zdedenej predvoľby účtu. Na platobnej relácii sa zároveň zapol automatický výpočet dane spolu s vyžiadaním fakturačnej adresy a IČ DPH — samotný príznak „daň sa pripočítava" totiž nepočíta nič, takže by sa účtovala holá čistá suma a DPH by šla z marže. (8) Počty na záložkách parametrov sú lacné a pravdivé (1c2a2ac1) — podmienené načítavanie dopytov jednotlivých záložiek pripravilo stránku pri prvom otvorení o odznak „nenamapované: N", teda o hlavný dôvod jej existencie. Nová trasa počítajúca iba počet ho vracia za 5,35 ms oproti 2 134,9 ms, ktoré stojí úplný súčet nad 908-tisíc riadkami hodnôt parametrov tenanta, a odznaky ukazujú skutočné súčty (1 493) namiesto veľkosti aktuálnej 25-riadkovej strany (25). (9) Vizuálne úpravy administrácie (7a0742e2, 07db4a44) — tenant na Monokaido Platinum už na záložke predplatného nevidí štandardný blok S/M/L, jeho miesto zaberá Platinum banner, pričom vlastný balíček tenanta filter vždy prežije, aby mu ostala cesta do správy fakturácie. Notifikácie pribudli medzi položky ponuky nastavení (predtým boli dostupné len cez lištu záložiek alebo napísanú adresu, čo na tej záložke nezvýraznilo nič v bočnom paneli). Filtračné selecty vykresľovali ikonu a stavovú bodku v jednom 10 px riadku, čo pôsobilo ako chyba vykreslenia: ikona sa presunula k popisu poľa, spoločný komponent FilterField nahradil značkovanie kopírované 18× (popis), 14× (trieda triggeru) a 24× (bodka), a z filtrov objednávok a košíkov zmizla nikdy nefarbená dekoratívna bodka.