Cześć
Mam prolem z projektem gdzie muszę zaimplementować racecondition podczas walidacji.
Czy ktoś obeznany w temacie mógłby mi pomóc??
Cześć
Mam prolem z projektem gdzie muszę zaimplementować racecondition podczas walidacji.
Czy ktoś obeznany w temacie mógłby mi pomóc??
Musisz zaimplementować race condition? Ominąć czy zabezpieczyć przed to miałoby jeszcze sens, ale w zaimplementowaniu nie widzę żadnego celu ("mam problem [...] muszę połączyć rurę wydechową z wnętrzem samochodu") - czy na pewno tak brzmi treść Twojego polecenia?
Doprecyzuje moje pytanie chodzi obsłużenie racecondition podczas walidacji, brakuje mi tego w projekcie i nie wiem jak do tego podejść, jak to rozwiązać
Nadal trochę mało - skąd bierze się ten race condition, czego dotyczy (baza danych, jakaś wewnętrzna struktura danych w aplikacji, ...)? Najlepiej byłoby gdybyś wrzucił kod.
@Patryk27:
ja z tym kolegą sobie rozmawiałem i sytuacja wygląda tak:
Masz rest api służące do dodawania np. lekarzy. API przyjmuje LekarzDTO
, na klasie jest zrobiona walidacja. Walidacja jest zrobiona w postaci customowej adnotacji, walidacja sprawdza czy tam nip taki nie istnieje w bazie. No generalnie walidacja odpytuje bazę czy może taki obiekt wgl. spróbować wstawić - nie pytaj czemu tak jest bo to bez sensu. No i rozpatrz taki case:
I teraz cała zabawa polega na tym że trzeba do tego naklepać testy w Springu.
W takiej sytuacji oparłbym się o mechanizmy dostępne wprost w bazie danych - i tak na przykład Postgresql obsługuje tzw. predicate locking, który powinien rozwiązać ten problem :-)
W sensie zamkną walidację i zapis w jakimś locku bazodanowym aby uczynić tą operację atomową?
Kinda; wykonujesz transakcje w trybie serializable - wtedy gdy jedna transakcja odpali select * from lekarze where nip = 'abcd'
, to druga, próbując odpalić to samo zapytanie, zostanie AFAIR zblokowana do czasu zakończenia tej pierwszej (stąd "predicate locking", ponieważ blokada następuje na predykacie nip = 'abcd'
, a nie na konkretnym wierszu - który może nie jeszcze istnieć - jak miałoby miejsce w przypadku select for update
).
Przy czym wiem tyle tylko, że taki mechanizm istnieje - nie jestem na 100% pewien czy tak właśnie działa, ale do przetestowania wystarczy odpalić w konsoli kilka zapytań :-)
Moim zdaniem to w ogóle nie ma żadnego sensu jako walidator na poziomie DTO. Tam sie waliduje jakieś statyczne duperele jak puste pola czy długość stringa. Trudniejsze rzeczy niech się walidują w operacjach biznesowych i tyle. Inaczej to i tak jest klasyczne https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use i nie da się tego jakoś magicznie naprawić. Jakakolwiek walidacja która nie jest atomowa z finalną operacją, będzie miała race condition.
Tak bardziej szczegółowo - to co tutaj jest problemem zazwyczaj w kontekście baz jest nazywane phantom read. Wyszukujesz w tabeli wszystkie wiersze spełniające pełen predykat, ale przy poziomach izolacji repeatable read i poniżej nie masz żadnej gwarancji że zestaw wierszy zwróconych z predykatu się nie zmieni w trakcie transakcji (repeatable read gwarantuje jedynie że wiersze zwrócone w poprzednich odczytach z predykatem zostaną zwrócone po raz drugi, nie gwarantuje że nie powstaną nowe wiersze)
Zgodnie z ANSII jedyny mocniejszy poziom izolacji to serializable, z tym że tutaj trzeba popatrzyć na:
Najprościej będzie sobie wrzucić unique constraint na NIP, bo to zostanie wykryte nawet w przypadku kiedy dojdzie do podobnego problemu w transakcji.
Jeśli chodzi o testowanie - jedynie testy integracyjne niefunkcjonalne, bo problem leży po stronie bazy a nie aplikacji (chyba że chcesz się bawić w implementację transakcji na poziomie aplikacji, tylko po co dla takiej pierdoły)