Baza pod stary CMS
Polskie nazwy tabel i kolumn, statusy jako nieopisane liczby, historycznie rozjechane relacje tagów i surowy HTML z FCKeditora - bez dokumentacji schematu i typów.
Case study · Sport i technologia
Nowy serwis PLK.PL - trzy aplikacje, kompletne archiwum rozgrywek, wyniki na żywo i dane sportowe gotowe na największy ruch w dniu kolejki.
Polska Liga Koszykówki miała serwis działający od kilkunastu lat: aktualności, terminarz, tabele, statystyki, profile drużyn i zawodników, galerie oraz wideo. Był centralnym źródłem informacji o rozgrywkach, ale technologicznie należał do innej epoki.
Polskie nazwy tabel i kolumn, statusy jako nieopisane liczby, historycznie rozjechane relacje tagów i surowy HTML z FCKeditora - bez dokumentacji schematu i typów.
Aktualności, wideo i galerie nie miały slugów. Istniały wyłącznie pod identyfikatorami liczbowymi.
Terminarz, składy, statystyki, boxscore'y i przebieg meczów pochodziły z zewnętrznego, nietypowego API bez warstwy pośredniej.
W dniu kolejki ruch rośnie gwałtownie, a wyniki muszą pozostać świeże. Odpytanie źródła przy każdym wejściu nie mogło się skalować.
Aktualności, galerie, wideo, bannery, partnerzy i strony statyczne były zarządzane w przestarzałym narzędziu.
Przepisaliśmy frontend, API i panel redakcyjny na tej samej produkcyjnej bazie danych. Nowe encje zostały zmapowane na historyczne tabele, dlatego uruchomienie nie wymagało jednorazowej, ryzykownej migracji całego archiwum.
Każdy wynik, tabela i statystyka pochodzą z ESOR - systemu Polskiego Związku Koszykówki. Źródła nie dało się zmienić, a serwis nie mógł być wolniejszy ani mniej dostępny od niego.
Jedno wejście API, formularzowe żądania POST, operacja przekazywana w treści, brak wersjonowania, typów i kontraktu. Odpowiedzi odzwierciedlały wewnętrzny system ewidencji, nie potrzeby serwisu.
13 modułów dla lig, sezonów, kolejek, meczów, drużyn, zawodników, trenerów, tabel, statystyk, hal i wyszukiwania. Frontend nie widzi surowych odpowiedzi ESOR.
Każde zapytanie ma deterministyczny klucz i zdefiniowany czas życia w memcached, z kontrolowanym odświeżeniem i możliwością ominięcia cache.
Ciężkie zapytania są odbudowywane co 4 minuty, a mecze live co minutę - zanim użytkownik ich zażąda.
Tylko instancja zerowa odświeża dane, więc zwiększanie liczby procesów nie zwiększa ruchu do ESOR.
Regeneracja przyrostowa co 60 lub 300 sekund daje niezależną warstwę ochronną między kibicem a backendem.
Serwis pozostaje szybki nawet przy obciążonym źródle, a nowe widoki statystyk korzystają z gotowych, otypowanych modułów zamiast bezpośrednich wywołań obcego API.
Serwis ligowy jest oceniany w dniu kolejki. Wynik meczu musi być widoczny natychmiast na każdej podstronie, niezależnie od liczby kibiców obserwujących go w tej samej minucie.
API odpytuje ESOR o trwające mecze co 60 sekund z pominięciem cache. Przeglądarki nie wykonują żadnego pollingu.
W klastrze wyłącznie instancja zerowa pobiera świeży stan, a wszystkie procesy go serwują.
Dane live są scalane z terminarzem: flaga trwania, kwarta, zegar, wynik i transmisja trafiają do wspólnego modelu.
Trwające mecze i tabela towarzyszą kibicowi w artykule, profilu zawodnika, terminarzu i archiwum.
Karuzela wskazuje mecz live, używa pulsującego znacznika i rozwija się do pełnego widoku kolejki oraz tabeli.
Koszt wyników live nie rośnie wraz z ruchem. Dziesiątki tysięcy sesji nadal oznaczają dokładnie jedno zapytanie na minutę do systemu ligowego.
PLK.PL powstał na dedykowanym design systemie rozwijanym i wersjonowanym razem z aplikacją. Projekt był systemem, z którego składają się widoki, a nie zbiorem niezależnych makiet.
Skala akcentu obsługuje pełny cykl interakcji, powierzchnie mają zdefiniowane poziomy głębi, a kolory sygnalne przekazują status bez czytania.
Trzy rodziny krojów: jedna do treści oraz dwie o stałej szerokości znaku do wyników, czasu gry i tabel statystycznych.
Treść - Inter
Kolejny komplet punktów w hali przy Kolejowej
Nagłówki, zapowiedzi meczów, artykuły i nawigacja. Krój pozostaje czytelny w małych etykietach i gęstych układach tabel.
400 · 500 · 700 · 800Dane - Roboto Mono / Geist Mono
| Zawodnik | PKT | ZB | AS | EVAL |
|---|---|---|---|---|
| A. Kowalski | 24 | 7 | 5 | 28 |
| M. Nowak | 18 | 11 | 2 | 25 |
| P. Zieliński | 9 | 3 | 8 | 17 |
stała szerokość znaku - cyfry układają się w kolumnachWarianty, rozmiary, stany fokusu i wyłączenia wynikają z systemu, a nie z lokalnych nadpisań.
Kwarta 4 · 02:14Promienie, cienie, obwódki fokusu i ruch również są tokenami.
0.125rem0 2px 0 #F8F8F8ring 2px #F88D65180° → #0E0C1DloaderLine 1s linear159 komponentów zachowuje się jak jeden produkt na 71 widokach - również w funkcjach dodanych po premierze, takich jak drabinka play-off i tabela U23.
Nowy serwis nie dostał czystego schematu. 30 encji zmapowaliśmy na tabele starego CMS-a, a polskie kolumny przetłumaczyliśmy na czytelny model domenowy. Zmiany wprowadzały wersjonowane migracje uruchamiane przy wdrożeniu.
Media są konwertowane do WebP i skalowane w locie, ale zachowują strukturę CDN starego serwisu. Archiwalne zdjęcia i logotypy pozostały pod dotychczasowymi adresami.
Specyfikacja OpenAPI jest kontraktem między aplikacjami. Zmiana backendu ujawnia się jako błąd kompilacji frontendu, a nie błąd na produkcji.
Merge do gałęzi rozwojowej publikuje staging, a merge do głównej - produkcję. Pipeline porównuje commit z ostatnim buildem i przebudowuje tylko te z trzech aplikacji, które rzeczywiście się zmieniły.
Migracje bazy uruchamiają się przed nową wersją API. Każdy frontend trafia do osobnego katalogu wydania ze współdzielonym cache obrazów, a procesy są przeładowywane w klastrze bez przerwy w dostępie.
Regularny rytm małych zmian przy 1 230 commitach zamiast rzadkich, obciążonych ryzykiem wdrożeń.
Wspólny proces wdraża frontend, backend i panel, ale przebudowuje wyłącznie zmienione aplikacje.
71 publicznych widoków, wraz z pełnym drzewem archiwum sezonów, działa na produkcji.
Nowy serwis pracuje na tej samej bazie bez ryzykownej, jednorazowej migracji treści.
Slugi, metadane i Open Graph powstały również dla wieloletnich treści istniejących wcześniej tylko pod ID.
Kwarta, zegar i wynik odświeżają się co 60 sekund przy jednym zapytaniu do źródła na minutę.
Tokeny i wspólne komponenty obejmują wszystkie 71 widoków i rozwijają się razem z produktem.
Dwie warstwy cache i wyprzedzające odświeżanie izolują kibiców od obciążenia zewnętrznego API.
Rankingi, rekordy, mapa rzutów, akcja po akcji, CSV i raport PDF działają dla bieżących i historycznych sezonów.
59 komponentów obsługuje treści, media, reklamy, partnerów, play-off i konfigurację z kontrolą uprawnień.
Drabinka play-off, głosowanie, ranking typów i indywidualne grafiki zachęcają do udostępniania.
Kolejne sezony, Puchar, Superpuchar, U23 i eksport kalendarza są dokładane bez przestojów.