Cześć, piszę sobie hobbysticznie gierkę przeglądarkową w standardowym stacku Spring Boot 2/SQL i nie mam pomysłu w jaki dobry sposób zaimplementować funkcjonalność obsługiwania wydarzeń po określonym czasie.
Mamy następujący Use Case - użytkownik chce sobie wybudować budynek. Czas budowy wynosi 1 h, po tym czasie następuje wybudowanie budynku, aktualizacja db, itp. Ponadto użytkownik może zawsze cofnąć rozkaz i odzyskać wydane surowce.
W prosty sposób można to zrobić używając ScheduledExecutorService - dać po prostu odpowiedni delay do zadania. Jednakże widzę tutaj dwa problemy:
- nie widzę prostego sposobu w którym użytkownik może anulować rozkaz
- dla każdego rozkazu przez długi okres czasu będzie utrzymywany jeden wątek, których w założeniu może być miliony
Więc zamiast tego myślałem o stworzeniu czegoś podobnego do js'owego EventLoopa (przynajmniej jeśli dobrze go rozumiem). W pseudo codzie:
public final class CommandsExecutor{
PriorityQueue<AppEvent> queue;
public CommandsExecutor(){
this.run();
}
public <T extends AppEvent> void add(T event){
queue.add(event);
}
public <T extends AppEvent> void remove(T event){
queue.remove(event);
}
public void run(){
while(true){
if (LocalDateTime.now() == queue.peek().getExecutionTime()){
CompletableFuture.supplyAsync(() -> queue.peek().proccess())
queue.pop();
}
}
}
}
Założenia:
- Klasa byłaby singletonem.
- Zadania w kolejce są priorytetowane ze względu na czas (im krótszy, tym event jest wyżej w kolejce)
- Zadania pewnie musiałyby być synchroniczne by nie było sytuacji, że event mający wydarzyć się później został zakończony przed eventem który wydarzył się wcześniej (bo np. transakcja się wcześniej skommitowała)
Nawet nie próbowałem czegoś takiego implementować więc nie mam pojęcia jak trudne by to było w implementacji (nie wiem jakie Spring może mieć zdanie o takich pomysłach). Mechanizm który zostanie stworzony będzie de facto podstawą systemu więc musi być szybki i niezawodny. I pytania - takie założenie ma sens? Jest jakiś wzorzec projektowy który pomaga rozwiązywać podobne problemy? Jest jakiś mechanizm w Springu który to zrobi za mnie? Jestem otwarty na pomysły.
Co gdy ktoś na serwerze cofnie strefę czasową?
po to jest monotonic clock, żeby nie przejmować się takimi głupotami