JSON response bez terminacji metody

0

Cześć
Mam prosty do opisania problem, a szukałem bardzo długi czas na google i dalej go nie znalazłem - Mam endpoint, którego użycie powoduje rozpoczęcie całej sekwencji. Ale potrzebuję, aby zaraz po wysłania zapytania na endpoint zwróciło response poprzez JSON'a. I może być to zwykły i może też być to exception czy ResponseEntity, obojętnie - byle by zwróciło od razu, ale jednocześnie nie zastopowało całej już rozpoczętej sekwencji w tym endpoincie. Próbowałem wiele rzeczy i niestety - albo zatrzymuje albo czeka aż się skończy.

Ktoś ma jakiś pomysł? Pewnie to jakaś mała bzdura, ja jestem świeżak i się uczę i na prawdę szukałem, ale nie mogę nigdzie znaleźć żadnego rozwiązania.
Będę wdzięczny za pomoc!

2

Przypuszczam, ze najprościej będzie JEDNAK zaterminowac metodę, ale przedtem odpalić wątek / backgroud task / whatever.
Szczerze mówiąc nie wiem, jak to zrobić w sposób naturalny dla Springa. W ogóle te rzeczy w środowisku webowym, to śliska sprawa, to się robi, ale z namysłem i odpowiedzialnością.

Wydaje się, że w porządnie budowanych systemach się dysponuje coś do kolejki i stosowny kod to z kolejki podejmie i wykona.

3

https://www.baeldung.com/spring-async

Albo czegoś nie rozumiem w pytaniu, albo nie wierzę że tego nie znalazłeś

4

@kilroy: wielowątkowość jest od tego.
A co tam właściwie chcesz zrobić?
@kixe52: jak op nie kojarzy wątków a zabiera się za Springa to poszło coś nie tak.

4
  1. W zabawkowym przykładzie odpalasz tą akcje "w tle" w osobnym wątku, np. przez CompletableFuture.runAsync(cośtam)
  2. W praktyce często takie asynchroniczne akcje mieli się jakimś specjalnie utworzonym w tym celu ThreadPoolExecutorze
  3. Często też nie chcesz "zgubić" takiego czegoś, więc wrzuca się request do kolejki z której executor wyciąga sobie zadania do wykonania
  4. Wydaje mi się bardzo dziwne że ktoś pisze aplikacje z użyciem springa i nie wie co to są wątki. To źle wróży.
0

@Emdzej93, @scibi_92, @Shalom, @kixe52 - Przepraszam Was bardzo - oczywiście wiem co to są wątki i wiem jak one działają. Tylko ostatnio dostałem taką informację w porównaniu swojej wiedzy, że w nią mocno zwątpiłem i byłem absolutnie przekonany, że to nie może pójść po prostu przez zwykłe wątki skoro zapytania przez Endpoint mogą iść po kilka, jeden po drugim, a sekwencja od każdego, która ma się zadziać w aplikacji ma trwać po minutę. I stwierdziłem, że na pewno jest to zupełnie inne rozwiązanie. Ale dziękuję Wam, szczególnie, że nie wiem rzeczywiście co to "asynchroniczność" w programowaniu, jedynie domyślam się. Puściłem to przez Async i działa, spróbowałem zwyczajnie przez klasę Thread i też poszło póki co z jednym. Jest to dla mnie kolejna dawka wiedzy, którą zgłębię.
@Shalom: Rozumiem, że w takim przypadku najlepiej używać "asynchronicznych"?

1

Rozumiem, że w takim przypadku najlepiej używać "asynchronicznych"?

? To co chcesz zrobić to asynchroniczna akcja. Synchroniczność jest wtedy kiedy "czekasz" aż operacja się wykona. Jeśli nie czekasz i ona leci w tle to jest asynchroniczne (i oznacza np. ze trzeba odpowiednio oprogramować co się ma dziać kiedy ktoś próbuje pobrać wyniki takiej operacji która właśnie mieli się w tle).

spróbowałem zwyczajnie przez klasę Thread i też poszło póki co z jednym

Problemów z gołym thread jest sporo, taki najbardziej oczywisty to co się stanie jak nagle dostaniesz milion requestów na raz i spróbuesz utworzyć i odpalić milion wątków na raz :D Dlatego lepiej mieć jakiś thread pool o ustalonym rozmiarze. Springowe async też tak robi.

0

@kilroy:

Moze przemyślałeś, może nie, zwrócę na coś uwagę:
W świecie synchronicznym jak zwracasz wynik, to już jest wszystko wiadomo, transakcja się wykonała, efekty są znane.

W asychnronicznym na moment powrotu, nie ma o tym wiedzy.

Odezwałem się, bo przywołujesz pewne "strange" scenariusze, np rzucanie wyjątkami.
a w nowym poście mówisz o (nielimitowanej) wielokrotności tego, to może prowadzić do wielu rzeczy, od denial of service, po hazardy / konkurowanie na danych.

Mi mocno miga pomarańczowe światełko.

Co to NAPRAWDĘ za scenariusz?

0

@Shalom: Rozumiem, dzięki wielkie za wyjaśnienie! Ogólnie to jest to związane z tym tematem co napisałem do Ciebie też na PW z podziękowaniem, więc zwykły Thread dałby pewnie radę, ale w takim razie już wiem jak zrobić bezpieczniej w razie w :D no i z ręki to sobie zrobię, aby się pouczyć, bo już wiem, że nie sztuką jest używać na moim etapie udogodnień, które dosyć łatwo można je zrobić z ręki :D a obsługę wyjątków rozumiem, że też ogarnę przy CompletableFuture? Bo przy Async można łatwo nadpisać jego ExceptionHandler, aby to zwyczajnie lepiej wyglądało i nie wyrzucało w Logu tego jako ERROR

@ZrobieDobrze: to prosty program na zasadzie "włącz pralkę" z zapisywaniem aktualnego jej trybu, czyli czy chodzi czy nie chodzi. Obsługa przez REST i chodzi o to, aby włączyć parę na raz. I chciałem, aby zwracało mi od razu info w Postman'ie, że uruchomiona i mieliło w tle aż ukończy się pranie.

0

Generalnie lepiej ogarniać sobie wyjątki tak żeby nie "wyskakiwały" z asynchronicznego wątku. Tzn wołać tam metodę która niczego nie rzuca, tylko ogarnia wszystkie problemy sama.
A z tymi pralkami to co się stanie jak ktoś wyśle 2x request żeby włączyć tą samą pralkę? :P

0

@Shalom:

Shalom napisał(a):

A z tymi pralkami to co się stanie jak ktoś wyśle 2x request żeby włączyć tą samą pralkę? :P

W sumie to się nie da 😅 tzn ja nie znam sposobu, pewnie się da na tym co mam xd bo nawet jakby się próbowało przekazać identyfikator przez body to jest on losowany i przypisywany na poziomie aplikacji, więc nie przekaże się tego identyfikatora dalej. Przynajmniej tak to rozumuję xd

Shalom napisał(a):

Generalnie lepiej ogarniać sobie wyjątki tak żeby nie "wyskakiwały" z asynchronicznego wątku. Tzn wołać tam metodę która niczego nie rzuca, tylko ogarnia wszystkie problemy sama.

Rozumiem. A co właśnie w przypadku jak się nie da inaczej? Bo to się właśnie wiąże z tym zastopowaniem metody i wyjątek zwraca info na RESTa, że jest pauza pralki.

0
kilroy napisał(a):

Rozumiem. A co właśnie w przypadku jak się nie da inaczej? Bo to się właśnie wiąże z tym zastopowaniem metody i wyjątek zwraca info na RESTa, że jest pauza pralki.

Nie wiem, czy przemyślałeś do końca i czy naprawdę rozumiesz.
Nie ma już "metody REST", to przeszłość, Zed is dead, baby. Metoda sie skończyła dawno temu.
Masz już tylko wątek, on nie istnieje z punktu widzenia serwera webowego. Nikt nigdy przez weba się nie dowie, co z nim jest / było. Żaglowiec bez radia odpłynął z portu.

Dlatego ja lubię myśleć jako o "backgroud worker", choć prawdopodobnie byłby zaimplementowany jako wątek, ale to nie jest istotą (w jednym z projektów jest to w innym procesie, serwera SQL który robi backup i daje procent). Ów backgroud worker to możesz widzieć jako "wątek na sterydach", tzn goły wątek systemowy PLUS protokół komunikacji, jakieś struktury danych, konwencje, aby jakaś INNA metoda mogła do tego sięgnąć, i udostępnić przez REST / AJAX / whatever

wyjątek zwraca info na RESTa, że jest pauza pralki.

Ani wyjątek nie jest dobrym odwzorowaniem pauzy, wyjątek zrywa sekwencję. Ani nie poinformuje przez REST-a. To słabość tego wyobrażenia

0

@ZrobieDobrze:

ZrobieDobrze napisał(a):

Nie ma już "metody REST", to przeszłość, Zed is dead, baby. Metoda sie skończyła dawno temu.

Ja tylko używam REST na potrzeby nauki.

Ani wyjątek nie jest dobrym odwzorowaniem pauzy, wyjątek zrywa sekwencję. Ani nie poinformuje przez REST-a. To słabość tego wyobrażenia

No właśnie złapałem się na tym. Tzn. gdy nie było to wrzucone w wątek to pięknie zwracało, a też chodziło, aby wyjątek zrywał sekwencję. A jak go wrzucam w wątek to niestety, ale wątkowy ExceptionHandler wyrzuca go tylko do logu. Próbowałem jakoś wrzucić to do Async, bo powiedzmy, że pierw nadpisałem w nowej klasie metodę wyrzucającą info, aby wyrzucił w logu ładnie informację. I w tej samej klasie próbowałem wrzucić poprzez @ExceptionHandler(AsyncUncaughtExceptionHandler.class) z @ResponseStaus(tu jaki chciałem) i dodać adnotację do klasy @RestControllerAdvice, ale niestety to nie działa. Szukam info w necie, ale coś nie mogę znaleźć, jestem niestety dosyć słaby w szukaniu w Google i to moja pięta Achillesowa xD

Czy ktoś wrzuciłby mi jakąś podpowiedź jak mogę ogarnąć, aby te wyjątki były wyrzucane jednak na RESTa? Jaki jest na to sposób?

0

Ale niby jakby to miało działać? o_O Ty rozumiesz jak działa REST? Bo mam wrażenie że nie za bardzo. Na początku tego wątku piszesz ze chcesz odesłać odpowiedź od razu a potem wykonywać operacje w tle. To automatycznie eliminuje możliwość wysłania czegokolwiek więcej do klienta bo już mu odesłałeś odpowiedź i połączenie się zakończyło. Przecież ten twój wątek moze się zacząć wykonywać za godzinę, a klient może już dawno wyłączyć komputer :D Odesłałeś mu odpowiedź i koniec. Nie da sie nagle odesłać mu kolejnej, bo przecież to by wymagało żeby po stronie klienta jakoś trzymać połączenie i sprawdzać w jakimś osobnym wątku czy coś nie przyszło.

Możesz wyjaśnić jak to wg ciebie miałoby działać?

0

real-time communication (jak czat) => https://spring.io/guides/gs/messaging-stomp-websocket/

0

@Shalom: Wiem jak działa REST i, że to jest odpowiedź i zakończenie połączenia, ale w tym momencie uświadomiłem sobie jedną rzecz i jak to zrobić, jak napisałeś swoją odpowiedź i sprawdzę to jutro.
Tu chodziło o przypadek walidacji, która sprawdzała na wstępie w tej metodzie dane i zwracało ten exception zamiast tamtego.
A walidacja innych danych działała bez problemu i wyrzucało wyjątki tylko teraz sobie uświadomiłem, że były one sprawdzane na innym poziomie i dlatego były wyrzucane tak jak chciałem. Myślałem, że to inaczej działało, ale jednak nie xd
Dzięki wielkie za odpowiedź, bo serio mi pomogła i wiem, że Was irytuję i przepraszam za to, ale takie są początki i często u mnie to są głupie błędy jak ten :) dodatkowo poczytam o tym utrzymywaniu połączenia i w ten sposób wyrzucania :)

0

@kilroy:

  1. Nawalanie adnotacji nie polepsza upewnienia się czy/co jak działa. Tu nie Narnia, magii nie ma. Jakbyś myslał banalnym try catch, bylo by to bardziej wyczuwalne.
  2. czy websocket, czy coś nieco innego, do obserwowania "hej wątku, co u ciebie słychać" trzeba przygotować dedykowany endpoint, i przygotować mu dostęp do stosownych informacji (status wątku, zwał jak zwał). Trzecie, że ten endpoint musi ktoś ktoś odczytywać (A websocket też nikomu w gardło nie wepchnie informacji, jeśli odbiorca nie otworzy)
0

@ZrobieDobrze:

  1. Odnośnie adnotacji to jak najbardziej rozumiem, bo właśnie ostatnio przerobiłem tą nauczkę co świetnie uświadomił mi @Shalom za co jestem mu bardzo wdzięczny. W tym przypadku z Async wiem co się dzieje i też robiłem dla siebie ręcznie na asynchronicznym i na synchronicznym zwykłym Thread. Ogólnie to już to naprawiłem, po prostu źle spojrzałem na ten problem, od złej strony.

  2. Dzięki za info! Mam taki Endpoint i może dla własnej nauki coś takiego sobie zrobię, aby zobaczyć jak to działa, tym bardziej, że widać, że mam sporo przed sobą do nauki :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1