Kolejka dropowa i ekspresowe zamówienie
Sklep z kartami kolekcjonerskimi sprzedaje w oknach dropowych: o ustalonej godzinie do sprzedaży trafia kilkanaście pozycji, często po kilka sztuk każda, a kilkudziesięciu kupujących rusza na nie w tej samej minucie. Zwykła kasa sklepu internetowego jest na taki moment za ciężka — każde wejście to pełne uruchomienie WordPressa, koszyk, kilka ekranów i kilka zapytań do bazy, a przy pojedynczych sztukach dochodzi ryzyko sprzedania tej samej karty dwa razy. Zbudowaliśmy dla tego sklepu osobną ścieżkę zakupu na czas dropu: lekką kolejkę, która stoi obok WordPressa i wpuszcza kupujących partiami, oraz formularz ekspresowy, który zakłada zamówienie i przekazuje do płatności w jednym kroku. Całość ma jedną zasadę nadrzędną: błąd naszego mechanizmu nie może oznaczać zera sprzedaży w dniu dropu.
Schemat działania — krok po kroku
Start dropu
O ustalonej godzinie strona dropu odsłania przycisk wejścia do kolejki — bez przeładowania strony, więc o pełnej godzinie nie ma salwy żądań.
Numer w kolejce
Kupujący dostaje podpisany bilet z numerem. Numer nie zmienia się przy odświeżaniu strony.
Poczekalnia
Statyczna strona pokazuje pozycję i odpytuje jeden lekki adres — WordPress w tym nie uczestniczy.
Wejście do środka
Gdy zwalnia się miejsce, kolejka wpuszcza następną osobę i daje jej kilka minut na zakup.
Formularz ekspresowy
Jeden ekran: pozycje dropu, ilości, dostawa i dane. Bez koszyka i bez przechodzenia między stronami.
Zamówienie i płatność
Jedno żądanie rezerwuje sztuki, sprawdza limit na klienta, zakłada zamówienie i odsyła do płatności.
Co to daje
Sklep nie pada w szczycie
Ruch czekających obsługuje lekki kod poza WordPressem, a do kasy wchodzi naraz tyle osób, ile serwer uniesie.
Jedna sztuka, jeden kupujący
Sztuka jest rezerwowana na czas zamówienia i wraca do puli, gdy zamówienie nie dojdzie do skutku.
Uczciwa kolejność
Kto przyszedł pierwszy, ten kupuje pierwszy. Odświeżanie strony nie przesuwa nikogo ani w górę, ani w dół.
Zakup w jednym kroku
Od wejścia do płatności jest jeden formularz — przy kilku sztukach na pozycję liczą się sekundy.
Awaria nie zatrzymuje sprzedaży
Gdy kolejka nie może działać, przepuszcza wszystkich i zapisuje to w dzienniku, zamiast zamknąć sklep.
Limity pod kontrolą
Limit sztuk na klienta jest sprawdzany przy zamówieniu, a odmowa oddaje sztukę do puli.
Szczegóły
Dlaczego zwykła kasa tu nie wystarcza
W zwykły dzień sklep obsługuje zamówienia bez wysiłku. Drop jest innym zjawiskiem: cały ruch dnia mieści się w kilku minutach i wszyscy chcą tego samego. Standardowa ścieżka — karta produktu, koszyk, kasa — to kilka pełnych odsłon strony na osobę, każda z uruchomieniem całego sklepu. Przy kilkudziesięciu osobach naraz serwer albo zwalnia tak, że kupujący rezygnują, albo dwa zamówienia w tej samej sekundzie sięgają po tę samą ostatnią sztukę.
Kolejka zamiast wyścigu
Zamiast wpuszczać wszystkich do kasy jednocześnie, ustawiamy ich w kolejce. Poczekalnia jest statyczną stroną, a jedyny często odpytywany adres odpowiada bez udziału WordPressa. Do środka wchodzi naraz ograniczona liczba osób — to jeden parametr konfiguracji, dobierany do możliwości serwera. Miejsce zwalnia się po opłaceniu zamówienia, po upływie czasu na zakup albo wtedy, gdy kupujący zamknie kartę.
Co się dzieje, gdy coś pójdzie nie tak
Najgroźniejszy scenariusz dnia dropu to nie błąd w sklepie, tylko błąd w naszym dodatku, który zamknąłby sprzedaż wszystkim. Dlatego kolejka działa w zasadzie fail-open: gdy nie może odczytać swojego sekretu albo składu danych, przepuszcza kupujących prosto do formularza, oznacza każde takie przejście w dzienniku i nie blokuje nikogo. W teście, w którym celowo odebraliśmy kolejce najpierw sekret, a potem skład danych, wszystkie żądania doszły do celu — 20 z 20 w każdej z dwóch prób.
Dla zainteresowanych — jak to działa „pod maską". Kolejka to kilka plików PHP w osobnym katalogu, serwowanych z pominięciem WordPressa. Formularz ekspresowy jest statycznym HTML-em z JavaScriptem, a z WordPressem i WooCommerce rozmawia dopiero jedno żądanie: to, które zakłada zamówienie.
Kolejka poza WordPressem
Bilet kupującego to podpisany token (HMAC-SHA256), sprawdzany bez sięgania do bazy sklepu. Stan kolejki — numerator biletów, lista osób w środku, czas ostatniego sygnału — trzyma skład danych z dwiema wymiennymi implementacjami jednego interfejsu: Redis i MySQL. Porzucone miejsca zwalniają się leniwie, przy okazji kolejnych zapytań o status: po czterech brakujących sygnałach życia albo po upływie twardego limitu czasu, bez osobnego zadania cron. W teście na serwerze produkcyjnym zapytanie o status zajmowało średnio 9 ms.
Zrzut dropu zamiast zapytań do bazy
Formularz ekspresowy nie pyta sklepu o listę pozycji przy każdym wejściu. Przy zapisie dropu motyw buduje zrzut do pliku JSON — pozycje, limity, teksty o terminie wysyłki — a formularz czyta go przez jeden adres buforowany na 60 sekund. Treść zmienia się raz na drop, więc setki wejść kosztują tyle, co jedno. Kwoty i kody rabatowe jadą osobną drogą, poza katalogiem publicznym.
Zamówienie w jednym żądaniu
Jedno żądanie przechodzi całą drogę: weryfikuje przepustkę z kolejki, rezerwuje sztuki, sprawdza limit na klienta, zakłada zamówienie przez API WooCommerce (nigdy bezpośrednim zapisem do tabel) i uruchamia płatność w bramce, z odesłaniem na stronę płatności jako wyjściem zapasowym. Odmowa na którymkolwiek etapie oddaje zarezerwowane sztuki, a zwolnienie miejsca w kolejce jest idempotentne — powtórzone nie zrobi nic drugi raz.