Kod 200 i zgodny odczyt wysłanych pól nie dowodzą, że zapis niczego nie zepsuł. W Shoper API zachowanie zapisu częściowego zależy od zasobu, a dokumentacja go nie opisuje. Bezpieczny zapis zaczyna się od sprawdzenia, jak dany zasób przyjmuje PUT, i kończy porównaniem całego rekordu oraz wyrenderowanej strony.
| Zapis | PUT na kolekcję z polami nazwy, tytułu SEO i opisu SEO |
|---|---|
| Objaw | strona kolekcji przekierowuje na stronę główną; odczyt wysłanych pól zgodny |
| Przyczyna | kolekcja zresetowała pola, których nie wysłano; pole aktywności spadło z 1 na 0 |
| Czas | około czterech minut do przywrócenia |
| Zasada | dla kolekcji zapis całego tłumaczenia z polem aktywności; po zapisie porównanie całego rekordu i strony |
Objaw: kolekcja przekierowuje na stronę główną po zapisie SEO
Zadanie było proste: kolekcje produktów w sklepie nie miały własnych tytułów i opisów, więc w wynikach wyszukiwania pokazywał się szablonowy opis. Skrypt wysłał przez API dla każdej kolekcji nazwę, tytuł SEO i opis SEO, tak samo jak wcześniej dla kategorii i producentów, gdzie taki zapis działał bez skutków ubocznych.
Odczyt kontrolny porównał wysłane pola z zapisanymi i wszystkie zgadzały się co do znaku. Problem wyszedł dopiero przy otwarciu strony kolekcji w przeglądarce: karta pokazywała tytuł strony głównej, bo kolekcja przekierowywała na stronę główną. Obie kolekcje zostały wyłączone.
Po ponownym zapisie z polem aktywności ustawionym na 1 obie kolekcje wróciły pod swoje adresy, z produktami i nowymi tytułami. Od zapisu do przywrócenia minęły około cztery minuty.
Dlaczego odczyt kontrolny tego nie wykazał
W dokumentacji Shoper API dla zapisu kolekcji pole aktywności siedzi w obiekcie tłumaczenia, obok nazwy, opisu i pól SEO. Dokumentacja nie mówi, co dzieje się z polami tłumaczenia, których zapis nie zawiera. W tym przypadku kolekcja potraktowała brak pola jak nową wartość i zresetowała je.
Odczyt kontrolny porównywał tylko pola, które skrypt wysłał. Te zapisały się poprawnie, więc kontrola przeszła. Zmiana, której nikt nie zamierzał, czyli pole aktywności, była poza jej zasięgiem. To ogólna zasada: odczyt wysłanych pól sprawdza, czy zapis się udał, ale nie sprawdza, czy niczego innego nie zepsuł.
Jak poszczególne zasoby przyjmują zapis
W dwóch sklepach, w których pracujemy przez Shoper API, zaobserwowaliśmy takie zachowania. To nie jest specyfikacja Shopera, tylko wynik zapisów na żywych sklepach, i może się zmienić z aktualizacją platformy:
| Zasób | Zapis częściowy | Zapis całego obiektu |
|---|---|---|
categories | działa, w wycinku translations.pl_PL; tam też są aktywność i adres | HTTP 400 |
aboutpages (strony informacyjne) | zwraca 200 i gubi pola, w tym tytuł SEO | wymagany; obiekt jest płaski, bez translations, wysyłany bez page_id |
collections | resetuje pola, których nie wysłano | wymagany, z polem aktywności w tłumaczeniu |
producers | działa dla tytułu i opisu SEO | nie był potrzebny |
products | działa dla tytułu SEO | nie był potrzebny |
Do tego dwa przypadki, w których kod 200 nie oznaczał zapisu: sortowanie kategorii ustawione przez API zostawało na wartości 0, a pole kolejności produktu zapisywało się, ale listing go nie uwzględniał. Przy kontach klientów wysyłamy zawsze adres e-mail razem ze zmienianym polem i porównujemy cały rekord przed zapisem i po nim, żeby wykluczyć zmiany poza zamierzonym polem.
Cichy kod 200 przy powtórzonym zapisie kategorii
Przy kategoriach jest jeszcze jedna pułapka. Powtórzony zapis tej samej kategorii, wysłany szybko po poprzednim, wracał z kodem 200 i treścią odpowiedzi 1, ale danych nie zmieniał. W jednym ze sklepów zapis po 0,9 s i po 2–6 s nie przechodził, po około 8 s zwykle przechodził, a jedna kategoria potrzebowała 30 s. Zapis z inną treścią przechodził od razu. Obserwacje pasują do odrzucania powtórzonego zapisu, ale nie rozstrzygają, jak Shoper to realizuje; w części przypadków mógł też grać rolę opóźniony odczyt, opisany w kolejnym wpisie serii.
- po zapisie odczyt kontrolny, a przy niezgodności ponowienie po 10, 20 i 30 s
- porównanie po obcięciu białych znaków na końcu: Shoper obcina końcowy znak nowej linii, więc ścisłe porównanie zgłasza fałszywy błąd
- bez sztuczek w rodzaju dopisywania znacznika, żeby treść „różniła się” od poprzedniej; to zmienia dane w sklepie
Procedura bezpiecznego zapisu
Po tym przypadku każdy skrypt zapisujący do Shopera działa według tych samych kroków:
- przed pierwszym zapisem do nowego zasobu: próba docelowego rodzaju zmiany, z tym samym zestawem pól, na rekordzie testowym (np. nieaktywnym albo mało ważnym), z porównaniem pól zamierzonych i chronionych przed i po; zapis rekordu bez zmian tego nie zastąpi, bo nie pokazuje, co zasób robi z polem, którego w żądaniu brakuje
- rozdzielenie trzech zbiorów pól: pełna odpowiedź odczytu zapisana jako kopia, pola dopuszczalne w zapisie (cała odpowiedź odczytu odesłana jako zapis potrafi skończyć się błędem 400) i pola zmieniane przez system, np. daty
- kopia stanu sprzed zmiany w pliku, z którego da się przywrócić rekordy
- odczyt przed zapisem i porównanie z kopią: jeśli ktoś zmienił rekord w panelu w międzyczasie, rekord jest pomijany
- po zapisie porównanie całego rekordu, łącznie z polem aktywności, a nie tylko wysłanych pól
- na koniec sprawdzenie wyrenderowanych stron i przeliczenie wszystkich rekordów: zapis, który ukrywa stronę, nie jest sukcesem, nawet jeśli pola SEO się zgadzają
Kolejny wpis z tej serii opisuje przypadek, w którym nawet odczyt kontrolny nie wystarczył, bo treść wróciła później: zapis potwierdzony odczytem, a po chwili wraca stara treść.
Kiedy zapis masowy zrobisz sam, a kiedy z kimś
Pojedyncze zmiany przez API w zasobach, których zachowanie już znasz, z odczytem całego rekordu po zapisie i sprawdzeniem strony. Dla nowego zasobu zacznij od próby docelowej zmiany na rekordzie testowym i porównania pól zmienianych i chronionych przed i po.
Masowe zapisy do kategorii, kolekcji i stron informacyjnych, wdrożenia, które muszą być odwracalne, albo proces, w którym inna integracja też zapisuje do sklepu.
Gdy zlecasz nam zapis masowy przez Shoper API, dostajesz sprawdzenie zachowania każdego zasobu przed zapisem, kopię stanu sprzed zmiany z możliwością przywrócenia, zapis z porównaniem całych rekordów i raport z kontroli wyrenderowanych stron. Więcej o integracjach i automatyzacjach przez Shoper API i w przeglądzie najczęstszych błędów Shoper API.