Spring Boot Scheduled + długo działający proces

Spring Boot Scheduled + długo działający proces
Black007
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 14 godzin
0

Cześć.
Mam taki ciekawy case:
Otóż mam @Service, ktory uruchamia się co minutę:

Kopiuj
@Scheduled(cron = "0 * * * * *") // tu mi coś smierdzi - bo validator nie rozpoznaje co to jest za czas....
public void sync() {
List<Transaction> transactions =
                    transactionRepository
                            .findByExternalSourceAndTransactionStatusIn(XXX_TRANSACTION, Arrays.asList(TransactionStatus.PAID, TransactionStatus.IN_PROGRESS));
checkCorrectPriceAndSetStatusToInProgressIfPriceIsWrong(xxxTransactions);

A w samej metodzie:

Kopiuj
 try {
                XXXAmount xxxAmount = xxxClient.getXXXAmount(transaction, OffsetDateTime.now());
                String tariffId = xxxAmount.getTariffId();
//... jakaś tam logika
transaction.setTransactionStatus(TransactionStatus.IN_PROGRESS);
/// logika dalej
transactionRepository.save(transaction);
} catch(...){

xxxClient strzela do zewnętrzego api i sprawdza, czy bilet parkingowy został opłacony.
Jeśli trwa to bardzo długo, to serwis prawdopodobnie drugi raz odapala metodę i robią sie kwiatki
Efekt jest taki, że klientowi wyskakuje raz, że zapłacił i może wyjechać z parkingu a raz że nie. bo statusy potrafią skakać wte i z powrotem.

Teraz pytanie. czy ktoś miał podbny problem?
Jak synchronizowac takie rzeczy, które sa time consuing, czy wystarczy block synchronized?

Pozdrawiam.


"Nie popełnia błędów tylko ten, kto nic nie robi"
MrMadMatt
  • Rejestracja:ponad 9 lat
  • Ostatnio:4 dni
  • Postów:373
1

Wydaje mi się że taki przypadek powinno się zrobić tak że scheduler nie wykonuje bezpośrednio zapytania do zewnętrznego API tylko dodaje kolejne zadanie do kolejki, jakiś ExecutorService czy coś w tym guście.

Black007
O tym właśnie myślałem, bo w tej chwili błąd występuje nawet dla pojedynczej transakcji, a co będzie, jak będzie np. 600 transakcji :)
LU
  • Rejestracja:ponad 11 lat
  • Ostatnio:7 dni
  • Lokalizacja:Gdańsk
0

Jeżeli chcesz aby task wykonywał się co minute i aby kolejny się odpalał tylko po zakończeniu poprzedniego użyj:

Kopiuj
@Scheduled(fixedDelay = 60000)

Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:około 4 godziny
  • Postów:1880
1

Powinieneś przy pobieraniu transakcji oznaczyć ją jako "przetwarzana" tak, aby kolejne odpalenie joba (albo równoległe odpalenie na innej instancji aplikacji) nie spowodowało jej przetworzenia kilkukrotnie. Oczywiście samo przetwarzanie powinieneś zrzucać na osobną pulę wątków, ale to niezależny problem.


”Engineering is easy. People are hard.” Bill Coughran

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.