Modelowanie HTTP REST API dla skomplikowanych procesów biznesowych czerpiące inspirację z RPC

Modelowanie HTTP API na kształt Remote Procedure Call (RPC)

Proponuję, aby dla skomplikowanych procesów budować HTTP API w sposób przypominający zdalne wywoływanie procedur.

Innymi słowy, dla skomplikowanych procesów biznesowych obejmujących wiele zasobów, możemy rozważyć sam proces biznesowy jako zasób.

REST API Design – Resource Modeling
Thoughtworks

CRUD vs Business Operations

W pierwszej kolejności, zanim zaczniesz czytać dalej, koniecznie przeczytaj ten wpis o projektowaniu REST API Design – Resource Modeling od Thoughtworks.

RPC & SOA vs REST & CRUD over HTTP API

To był wcześniejszy tytuł tego tekstu, który nie za bardzo się kliknął, ale zostawiłem go, ponieważ jeśli już ktoś dotarł tutaj, to ten tytuł w maksymalnie skondensowanej formie wyjaśnia na czym polega pomysł rozwiązania i równie zwięźle podsumowuje wyżej linkowany artykuł o projektowaniu REST API.


Domena

Jako przykład operacji biznesowej posłuży mi domena nauki wraz z jej artykułami naukowymi, które podlegają procesowi recenzji przed opublikowaniem. W tej domenie miałem okazję pracować przez ostatnie dwa lata.

Praca naukowa, która pomyślnie przeszła proces recenzji jest publikowana w czasopiśmie naukowym. Manuskryptem będziemy nazywać pracę naukową, która jest w trakcie recenzji. W celu przeprowadzenia recenzji, recenzenci są zapraszani dla konkretnego manuskryptu. Oni decydują o jego akceptacji lub odrzuceniu. Manuskrypt zaakceptowany jest następnie wysyłany do czasopisma naukowego, aby mógł zostać opublikowany jako artykuł.


Implementacja

Ogólny wzorzec operacji biznesowych na poziomie API przedstawia się następująco: na poziomie zasobów (resources) dodaje się nowy zasób o nazwie „actions„. Następnie, w obrębie „actions„, dodawana jest konkretna operacja biznesowa, czyli czasownik (action) w formie rozkazującej.

POST /{resource}/{id}/actions/{action}

Przykładem synchronicznej operacji biznesowej może być zaproszenie recenzenta oraz akceptacja lub odrzucenie manuskryptu. Każda z tych operacji biznesowych może być realizowana przez inny proces, który zależy od konfiguracji specyficznej dla poszczególnych magazynów naukowych.

POST /manuscripts/256/actions/invite

POST /manuscripts/256/actions/accept

POST /manuscripts/256/actions/reject

Sync

W odpowiedzi zwracany jest status 204 (No Content).

204 No Content

Async

W odpowiedzi zwracany jest status 202 (Accepted), a w nagłówku „Location” podawany jest link, za pomocą którego można sprawdzić status realizowanego procesu.

202 Accepted
Location: /{resources}/{id}/actions/{action}/{actionId}

Powodem modelowania asynchronicznej operacji biznesowej może być proces, w którym wymagane są więcej niż jeden krok (na przykład dodatkowa zgoda redaktora magazynu naukowego) lub gdy operacja jest czasochłonna i nie oczekuje się, że klient będzie czekać na jej zakończenie.

Przykładowo, publikację artykułu naukowego w magazynie naukowym można zamodelować w ten sposób.

POST /journals/16384/actions/submit

Status: 202 Accepted
Location: /journals/16384/actions/submit/4096

Następnie klient, korzystając z otrzymanego linku, wykonuje zapytanie.

GET /journals/16384/actions/submit/4096

W przypadku, gdy akcja nadal jest w trakcie wykonywania, wówczas zwracany jest status 102 (Processing) wraz z nagłówkiem „Retry-After„, który informuje, kiedy klient powinien wykonać ponowne sprawdzenie statusu.

102 Processing
Retry-After: 30

W przypadku, gdy akcja została wykonana w całości, wówczas zwracany jest status 204 (No Content).

204 No content

Sync lub Async

W szczególnych przypadkach możemy dać klientowi możliwość wyboru, czy dana operacja ma być wykonywana synchronicznie, czy asynchronicznie.

Operacja zostanie wykonana synchronicznie, jeśli klient podczas wywoływania API ustawi nagłówek „Expect” z wartością statusu 204 (No Content).

POST /journals/16384/actions/submit
Expected: 204-no-content

Operacja zostanie wykonana asynchronicznie, jeśli klient podczas wywoływania API ustawi nagłówek ‚Expect’ z wartością statusu 202 (Accepted).

POST /journals/16384/actions/submit
Expected: 202-accepted

W przypadku, gdy wybrany przez klienta oczekiwany sposób wykonania nie jest dostępny, wówczas akcja zwraca status 417 (Expectation Failed).

417 Expectation Failed

Acknowledgement

W ostatnim roku pracowałem nad projektem, w którym modelowaliśmy HTTP API w stylu Remote Procedure Call (RPC). Architektem i pomysłodawcą tego podejścia był Konrad Kwiatkowski, który kompletnie zmienił moje postrzeganie świata, przekonując mnie, że nie musimy dążyć do osiągnięcia czwartej, a nawet półtorej wersji dojrzałości modelu Richardsona dla REST API. Za tę perspektywę jestem mu niezmiernie wdzięczny.