Edee.one 9.0 – Reimplementace objednávkového modulu, podpora GA4 a další vylepšení
V této verzi přicházíme mj. s kompletně přepracovaným mechanismem tvorby, ukládání a správy objednávek. Vše začíná už ve chvíli vytvoření nového košíku...
Reimplementace objednávkového modulu
Objednávková část našeho řešení byla myšlenkově a technologicky 10 let stará. Plnila svůj účel, ale naši zákazníci i my jsme ji už dávno přerostli, a tak byla devátá verze EdeeShopu především o přepracování této části na základě nejnovějších poznatků z produkčních prostředí.
Vzhledem k tomu, že objednávky jsou srdcem každého e-shopu, dotklo se přepracování objednávkového modulu průřezově mnoha dalších částí, jako je synchronizace s ERP našich zákazníků, napojení na tržiště, platební systémy a mnoho dalšího.
Současné řešení se dostávalo do úzkých už při nižších desítkách vystavených objednávek za sekundu. Na vině bylo především množství synchronně prováděných operací a počet databázových tabulek, do kterých bylo nutné zapsat nové záznamy v moment vystavení objednávky. Zároveň byl objekt a datový model objednávky příliš složitý, takže se se s ním našim implementátorům obtížně pracovalo a špatně se zpětně dohledávaly potřebné informace (jedním z důvodů bylo i postupné doplňování funkcionality v průběhu oněch 10 let, kdy jsme se spolu s našimi zákazníky učili EdeeShop plno nových věcí).
V této verzi přicházíme s kompletně přepracovaným mechanismem tvorby, ukládání a správy objednávek. Vše začíná už ve chvíli vytvoření nového košíku. Košík již není sada jednotlivých řádků v několika tabulkách databáze, ale jeden velký dokument, který se do databáze ukládá nestrukturovaně. Jeho načtení a uložení je otázkou milisekund, protože naši tabulku košíků používáme v podstatě jako jednoduché key-value úložiště.
Při práci s košíkem máme nově nastavený jednoznačný validační cyklus, který nám zajišťuje potřebné přepočty a kontroly na základě změn v košíku ze strany uživatele. Do tohoto cyklu můžeme nově velmi snadno zapojovat další kousky klientské logiky, které jsou běžné pro většinu našich projektů.
Košík se stal inteligentním – sleduje souvislosti v datech, a pokud dojde ke změně na položce A, ihned ví, že tato změna ovlivnila položky B a C, které automaticky přepočte. Vývojáři tedy nemusí detailně znát procesy uvnitř košíku a při rozšiřování logiky košíku si vystačí s pár anotacemi nad novými vlastnostmi.
Dalším kritickým momentem je dokončení nákupu a přidělení unikátního čísla objednávky, které stává typicky základem pro variabilní symbol používaný k platbě. Přidělování unikátního čísla ze sekvence bývá problematické z toho důvodu, že pokud je potřeba vystavit více objednávek současně, musí se vlákna mezi sebou synchronizovat a vyžádat si čísla postupně tak, aby bylo zaručeno, že jedno konkrétní číslo bude použito právě pro jedinou z objednávek. V clusterovaném prostředí je navíc nutné se takto dohodnout mezi různými servery v rámci sítě a to je ještě mnohem pomalejší.
Pro tyto účely jsme nově zavedli mechanismus tzv. kohort – každý server si při startu z databáze vypůjčí rozsah čísel pro nové objednávky (např. 1000 čísel pro nové objednávky). Tento rozsah si pak udržuje v paměti a přiděluje z něj jedno číslo po druhém v rámci jednoduché paměťové synchronizace (mutexu). Jakmile se blíží ke konci řady, s předstihem si s databázovým serverem vykomunikuje a vypůjčí novou sadu čísel pro přidělování. Celý mechanismus je popisován zjednodušeně – v reálné implementaci je celá řada drobností a chytáků, které bylo nutné vyřešit, aby vše fungovalo spolehlivě a zajistilo vydání všech čísel z vypůjčených sad.
Při vystavení objednávky se synchronně provedou pouze následující operace:
- Pro objednávku se vyhodnotí unikátní číslo objednávky (pouze operace v paměti).
- Číslo objednávky se zapíše společně s košíkem do databáze (jediný zápis do databáze).
- Zapíšou se rezervace všech položek zboží v objednávce do příslušných záznamů ve skladech (vložení několika nových záznamů do tabulek v databázi).
- Zapíše se informace o použití konkrétního voucheru či použití kreditů (vložení několika nových záznamů do tabulek v databázi).
- Uživatel je následně přesměrován na platební bránu, nebo jsou mu zobrazeny pokyny k platbě převodem (vložení jednoho řádku transakce do databáze).
Vytváření nových řádků v databázi je z pohledu databáze výkonnostně optimální, protože vyžaduje minimum zámků a eliminuje nutnost čekání na získání zámku.
Oproti původnímu řešení se jedná o naprosté minimum operací, které se musí provést ve chvíli dokončení objednávky. Na pozadí se následně startuje asynchronní proces, který provádí celou řadu dalších operací, které je nutné s objednávkou provést:
- Konverze objednávky z dokumentového formátu do formátu relačního, se kterým se mnohem lépe pracuje v následných fázích zpracování objednávky.
- Nastartování nakonfigurovaného workflow spojeného s objednávkou
- Odeslání notifikace e-mailem nebo jiným komunikačním kanálem.
- Přidělení bodů do kreditového systému.
- Odeslání informací o objednávce do externích systémů.
- Publikace nových ponížených zůstatků zboží do feedů a indexů pro rychlé zobrazování
Data jsou v databázi uložena takovým způsobem, že jsme schopni zpětně přesně popsat, jak došlo k výpočtu finální ceny v objednávce až na úroveň jednotlivých položek, ať už je cenová politika, kreditní systém a systém slev jakkoli složitý a přizpůsobený na míru požadavkům zákazníka. Podrobný rozpis výpočtu jsme nově schopni exportovat společně s objednávkou do ERP systému zákazníka např. ve formě textové poznámky.
Pro naše implementátory je klíčové zjednodušení komunikačních rozhraní a také fakt, že svoje rozšíření mohou psát jednotně jak pro košík, tak pro finální objednávku – přestože tyto dvě datové struktury vypadají v databázi naprosto odlišně. Pro tyto účely používáme mechanismus dynamického generování Java tříd, se kterým nám pomáhá open-source knihovna Proxycian, kterou jsme uvolnili pro volné použití pod licencí MIT.
Sjednocení práce s platebními branami
Podobným zeštíhlením a sjednocením prošly i naše integrace s platebními branami. Těch máme v nabídce celou řadu: Comgate, ČSOB platební bránu, Essox, GoPay, GP webpay, iplatba, Pays a PayU.
Po několika letech používání a postupného doplňování podpor pro různé poskytovatele platebních řešení již dokážeme odhadnout sadu společných vlastností a funkcí, které mají všichni společné a vyextrahovat speciality, které jsou pro každého poskytovatele unikátní.
To nám umožnilo sjednotit a zjednodušit administrační rozhraní k platebním systémům, které by mělo být teď uživatelsky stravitelnější a zároveň zjednodušilo práci implementátorům, kteří mohou přenášet své znalosti z používání jedné platební brány na jiné. Zároveň jsme zachovali přístup ke specialitám jednotlivých bran tak, aby bylo možné i nadále využívat jejich konkurenční výhody.
To nám mj. umožní i mnohem jednodušší a tím pádem i levnější přidávání podpory nových poskytovatelů platebních řešení.
Přepracování slučovacích skupin parametrů
V této verzi jsme změnili logiku slučovacích skupin parametrů, která našim zákazníkům slouží ke sjednocení parametrů produktů, jenž čerpají z různých dodavatelských číselníků, které se vzájemně překrývají (např. různí dodavatelé mají různé pojmenování pro barvy, velikosti a řadu dalších parametrů, které chceme směrem ke koncovému uživateli komunikovat jednodušeji).
Původní logika vypočítávala sloučení parametrů až při vlastním zobrazování na frontendu, což se ukázalo jako velmi nepraktické a složité. Vzhledem k tomu, že chystáme zcela novou verzi frontendu do další z „velké“ verze EdeeShopu, bylo nutné frontend výrazně zjednodušit a komplexní logika v této části nám nezapadala do dlouhodobých plánů.
V původním řešení bylo také možné vytvořit takové kombinace sloučených hodnot parametrů skrz různé typy, že bylo obtížné domyslet některé dopady na chování facetových filtrů nad produkty a nešlo dostatečně ovlivnit jejich seřazení ve výpisech.
V novém řešení došlo k několika zjednodušením – např. hodnoty je vždy možné slučovat pouze ve stejném nadřízeném typu parametru. Pokud se slučují celé typy parametrů (sady hodnot), pak se hodnoty v nich slučují separátně. Sloučené hodnoty je možné pomocí drag’n’drop mechanismu správně zařazovat a tím ovlivňovat jejich pořadí ve výpisech na frontendu a hlavně už v administraci uživatel jasně vidí, jak bude vypadat podoba na frontendu.
Frontendová část navíc o původních hodnotách, které byly sloučeny, už nic neví a vidí pouze sloučené prvky, které jsou pro něj k nerozeznání od těch, které administrátor nechal v původní nesloučené podobě.
Podpora Google Analytics v4
Google před časem uvedl novou verzi svého analytického nástroje založenou na událostech. EdeeShop ve verzi 9 má integrovanou podporu pro zasílání těch nejdůležitějších událostí GA4, které zahrnují například zobrazení produktu, zobrazení položky produktového výpisu, přidání/odebrání zboží do/z košíku nebo provedení nákupu. Podpora pro starší verzi Universal Analytics zůstává v produktu zachována, měřit lze tedy paralelně oběma verzemi.
Migrace na nejnovější verze JDK a MySQL
Ve verzi 9.0 jsme přešli na nejnovější dostupné LTS verze klíčových prvků naší platformy. Používáme Java platformu ve verzi 17, Tomcat 9.x a také databázi Percona ve verzi 8.x., Spring Framework 5.3.x.
To má řadu pozitiv – kromě možnosti používat nejnovější funkce, jsou nové verze použitých prvků výkonnostně lepší a samozřejmě také bezpečnější. Mnohem lépe se nám také reaguje na zjištěné zranitelnosti, protože na nejnovější LTS verze vycházejí opravné záplaty jako první.