W API, nad którym pracuję, jest operacja usuwania zbiorczego, która akceptuje tablicę identyfikatorów:
["1000", ..., "2000"]
Mogłem zaimplementować operację usuwania według własnego uznania, więc postanowiłem uczynić całą transakcję transakcyjną: to znaczy, jeśli pojedynczy identyfikator jest nieprawidłowy, całe żądanie kończy się niepowodzeniem. Nazywam to trybem ścisłym .
try{
savepoint = conn.setSavepoint();
for(id : IDs)
if( !deleteItem(id) ){
conn.rollback(savepoint);
sendHttp400AndBeDoneWithIt();
return;
}
conn.commit();
}
Alternatywą (zaimplementowaną gdzie indziej w naszym pakiecie oprogramowania) jest robienie tego, co możemy w backendu i zgłaszanie awarii w tablicy. Ta część oprogramowania obsługuje mniej żądań, więc odpowiedź nie jest gigantyczną tablicą ... teoretycznie.
Niedawny błąd występujący na serwerze ubogim w zasoby zmusił mnie do ponownego spojrzenia na kod, a teraz kwestionuję moją pierwotną decyzję - tym razem bardziej motywują mnie potrzeby biznesowe niż najlepsze praktyki. Jeśli, na przykład, nie uda mi się całe żądanie, użytkownik będzie musiał spróbować ponownie, a jeśli pewna liczba elementów zostanie usunięta, użytkownik może zakończyć akcję, a następnie poprosić administratora o resztę (podczas pracy nad naprawieniem błędu) !). Byłby to tryb dozwolony .
Próbowałem poszukać wskazówek w tej sprawie, ale wpadłem z pustymi rękami. Przyszedłem więc do ciebie: czego najbardziej oczekują tego rodzaju operacje masowe? Czy powinienem bardziej trzymać się ściśle, czy powinienem być bardziej liberalny?
Odpowiedzi:
Można wykonać „ścisłą” lub „ładną” wersję usuwanego punktu końcowego, ale musisz wyraźnie powiedzieć użytkownikowi, co się stało.
Wykonujemy akcję usuwania z tym punktem końcowym. Prawdopodobnie
DELETE /resource/bulk/
lub coś podobnego. Nie jestem wybredna. Liczy się tutaj to, że bez względu na to, czy zdecydujesz się być surowy, czy miły, musisz zgłosić dokładnie to, co się stało.Na przykład interfejs API, z którym współpracowałem, miał
DELETE /v1/student/
punkt końcowy, który akceptował identyfikatory zbiorcze. Regularnie wysyłaliśmy żądanie podczas testowania, otrzymywaliśmy200
odpowiedź i zakładaliśmy, że wszystko jest w porządku, ale później dowiedzieliśmy się, że wszyscy na liście byli jeszcze w bazie danych (ustawiona jako nieaktywna) lub nie zostali faktycznie usunięci z powodu błędu, który zawiedliśmy przyszłe połączenia,GET /v1/student
ponieważ otrzymaliśmy dane, których się nie spodziewaliśmy.Rozwiązanie pojawiło się w późniejszej aktualizacji, która dodała treść do odpowiedzi z identyfikatorami, które nie zostały usunięte. Według mojej wiedzy jest to rodzaj najlepszej praktyki.
Podsumowując, bez względu na to, co robisz, upewnij się, że zapewnisz sposób, aby użytkownik końcowy wiedział, co się dzieje i być może dlaczego. IE, jeśli wybraliśmy ścisły format, odpowiedź może być
400 - DELETE failed on ID 1221 not found
. Gdybyśmy wybrali „ładną” wersję, mogłaby to być207 - {message:"failed, some ids not deleted", failedids:{1221, 23432, 1224}}
(przepraszam za moje złe formatowanie JSona).Powodzenia!
źródło
207 Multi-Status
może być odpowiednie dla tej częściowej reakcji na awarięNależy być surowym i tolerancyjnym.
Zwykle ładunki masowe są podzielone na 2 fazy:
Na etapie sprawdzania poprawności każdy rekord jest sprawdzany ściśle, aby upewnić się, że spełnia wymagania specyfikacji danych. Można łatwo sprawdzić 10 z 1000 rekordów w ciągu zaledwie kilku sekund. Prawidłowe rekordy są umieszczane w nowym pliku do załadowania, nieprawidłowy (e) oflagowane i usunięte i zwykle umieszczane w osobnym pliku (pomiń plik). Powiadomienie jest następnie wysyłane do rekordów, które nie przeszły sprawdzania poprawności, dzięki czemu można je sprawdzić i zdiagnozować w celu rozwiązania problemów.
Po sprawdzeniu poprawności dane są następnie ładowane. Zwykle jest ładowany partiami, jeśli jest wystarczająco duży, aby uniknąć długotrwałych transakcji lub jeśli wystąpi awaria, łatwiej będzie go odzyskać. Rozmiar partii zależy od tego, jak duży jest zestaw danych. Jeśli ma się tylko kilka 1000 rekordów, jedna partia byłaby OK. Tutaj możesz być nieco tolerancyjny w przypadku awarii, ale możesz chcieć ustawić nieudany próg wsadowy, aby zatrzymać całą operację. Być może, jeśli partie [N] zawiodą, można by zatrzymać całą operację (gdyby serwer był wyłączony lub coś podobnego). Zwykle w tym momencie nie ma awarii, ponieważ dane zostały już sprawdzone, ale jeśli wystąpiły z powodu problemów środowiskowych lub innych, po prostu załaduj ponownie partię, która się nie powiodła. To sprawia, że odzyskiwanie jest trochę łatwiejsze.
źródło
Nie ma na to kanonicznej odpowiedzi. Konieczne jest zbadanie potrzeb i konsekwencji dla użytkownika oraz ocena kompromisów. OP podał niektóre z wymaganych informacji, ale oto, jak mam postępować:
Pytanie 1 : „Jakie są konsekwencje dla użytkownika, jeśli indywidualne usunięcie się nie powiedzie?”
Odpowiedź powinna kierować resztą zachowań projektowych / wdrożonych.
Jeśli, jak stwierdzono w OP, to po prostu użytkownik zauważy wyjątek i otworzy zgłoszenie problemu, ale w inny sposób nie zostanie zmieniony (nie usunięte elementy nie wpływają na kolejne zadania), to wybrałbym zezwolenie z automatycznym powiadomieniem Tobie.
Jeśli nieudane usunięcia muszą zostać usunięte, zanim użytkownik będzie mógł kontynuować, ścisłe jest zdecydowanie preferowane.
Danie użytkownikowi opcji (np. Zasadniczo ignorowanie awarii jako domyślnych albo ścisłych lub dopuszczających) może być najbardziej przyjaznym dla użytkownika podejściem.
Pytanie 2 : „Czy wystąpiłyby jakiekolwiek problemy ze spójnością / spójnością danych, gdyby kolejne zadania były wykonywane z nieod usuniętymi elementami w magazynie danych?”
Ponownie, odpowiedź zapewniłaby najlepszy projekt / zachowanie. Tak -> Surowe, Nie -> Dopuszczalne, Może -> Surowe lub Wybrany przez użytkownika (szczególnie jeśli użytkownik może polegać na dokładnym określeniu konsekwencji).
źródło
Myślę, że zależy to od tego, czy chcesz skalowalność, czy nie. Jeśli nie masz wielu identyfikatorów, nie powinno to mieć większego znaczenia. Jeśli zamierzasz mieć milion identyfikatorów, a jeszcze lepiej, nie masz absolutnej pewności, że tak się nie stanie, możesz poświęcić godzinę na usunięcie identyfikatorów, aby całkowicie zresetować z powodu 1 nieprawidłowego identyfikatora.
źródło
Powiedziałbym, że jednym ważnym punktem jest to, co oznacza usunięcie większości rzeczy.
Czy te identyfikatory są w jakiś sposób powiązane logicznie, czy to tylko wygoda / wydajność - grupowanie ich w partiach?
W przypadku jakiegoś, nawet luźnego połączenia, wybrałbym
strict
. Jeśli jest to tylko tryb wsadowy (np. Użytkownik klika „zapisz” dla ostatnich minut pracy i dopiero wtedy partia jest przesyłana), wybrałbympermissive
wersję.Zgodnie z drugą odpowiedzią: W każdym razie powiedz „użytkownikowi” dokładnie, co się stało.
źródło