Zaplanowanie akcji brzmi prosto: zapisz godzinę i uruchom kod, gdy nadejdzie. Produkcja dodaje restarty, podwójne delivery, opóźnione kolejki, korekty zegara i maintenance dokładnie w czasie wykonania. Niezawodny scheduler rzadko gwarantuje magiczne „dokładnie raz o idealnej sekundzie”. Łączy trwały plan, co najmniej jednokrotne dostarczenie i idempotentny efekt biznesowy.
„Kiedy” i „co” powinny być trwałym stanem
Plan zawiera instant albo recurrence oraz stabilny opis intencji. Dane wyłącznie w pamięci procesu znikają przy deployu. Sam systemowy cron często nie przechowuje biznesowego kontekstu ani historii.
Rekord może mieć status, liczbę prób, deadline i idempotency key. Payload należy ograniczyć i nie kopiować bez potrzeby wrażliwych danych.
At-least-once jest realistycznym modelem
Worker może wykonać operację i umrzeć przed potwierdzeniem. Queue dostarczy job ponownie. Jeśli system blokuje retry za wcześnie, crash przed efektem może trwale zgubić pracę.
Operacja biznesowa musi być idempotentna albo atomowo używać unikalnego execution ID. Exactly once wynika ze współpracy delivery i storage, nie z samej nazwy kolejki.
Lease ogranicza równoległość, ale nie wszystkie duplikaty
Kilka workerów szuka due jobs. Atomowy claim lub lease przydziela rekord jednemu na określony czas. Po awarii inny może przejąć pracę.
Wolny pierwszy worker może działać po wygaśnięciu lease. Fencing token albo transakcyjna kontrola wersji zapobiega nadpisaniu nowszego wyniku.
Wall clock planuje, monotonic mierzy
„Wyślij 10 czerwca o 9:00” jest regułą kalendarzową. Timeout 30 sekund powinien korzystać z monotonic clock. Korekta NTP nie może nagle wydłużyć requestu lub dać ujemnego czasu.
Scheduler porównuje instants z wall clock, lecz backoff, runtime i lease powinny używać miary odpornej na skoki.
Spóźniona praca potrzebuje polityki biznesowej
Po dwugodzinnej awarii setki jobów są overdue. Nie każdy należy uruchomić natychmiast. Przypomnienie może być użyteczne, krótkie okno promocji już nie. Recurrence może wymagać jednego catch-up albo każdego pominiętego run.
Deadline i maksymalne opóźnienie powinny być częścią modelu. Przypadkowy default schedulera nie może decydować o skutku dla użytkownika.
Recurrence zachowuje lokalną intencję
„Codziennie o 9:00 Europe/Warsaw” musi przechowywać region. Dodawanie 24 godzin przesuwa lokalny zegar przy DST. Następny termin należy wyliczyć z reguły i kalendarza po każdym wykonaniu.
Trzeba też określić zachowanie dla nieistniejącej i podwójnej godziny. UI powinien wyjaśniać tę decyzję.
Cron nie opisuje pełnej semantyki
Cron string mówi o wzorcu pól kalendarza, ale nie zawsze o strefie, catch-up, równoległości i błędach. Dialekty różnią się sekundami oraz znakami specjalnymi.
API powinno przechowywać dialekt, timezone i execution policy. Dla użytkownika struktura „dni robocze o 08:30” jest często czytelniejsza niż surowy string.
Retry potrzebuje backoff i klasyfikacji
Awaria zewnętrznego API może być chwilowa. Natychmiastowa nieskończona pętla zwiększa przeciążenie. Exponential backoff z jitter rozkłada próby, a maksymalna liczba lub deadline kończy je widocznym stanem.
Błąd walidacji i brak uprawnień nie są retryable. Worker musi klasyfikować wynik, nie powtarzać wszystko.
Dead-letter nie może być cmentarzem bez właściciela
Po wyczerpaniu retry job trafia do stanu wymagającego reakcji. Potrzebne są alert, reason code i bezpieczna możliwość ponowienia po naprawie przyczyny. Ręczny replay nadal musi zachować ten sam idempotency key.
Dashboard powinien pokazywać wiek i liczbę niewykonanych zadań. Samo przeniesienie wiadomości do osobnej kolejki nie realizuje obietnicy wobec użytkownika.
Transakcja chroni przejście stanu
Operacja może zmienić bazę i opublikować event. Crash pomiędzy krokami pozostawia niespójność. Transactional outbox zapisuje zmianę i wiadomość w jednej transakcji, a publisher dostarcza ją później wielokrotnie.
Scheduler staje się wtedy czytelną maszyną stanów. Audit może odtworzyć plan, claim, efekt i publikację.
Clock skew nie może otwierać bezpieczeństwa
Dla tokenów i signed links dopuszcza się małą tolerancję. Zbyt szeroka niszczy krótki expiry. Hosty potrzebują synchronizacji i alarmu przy dużej różnicy.
Do kolejności rozproszonej lepsza jest sekwencja lub logical version. Czas nie jest uniwersalnym źródłem konsensusu.
Drift powinien być obserwowany jak stan infrastruktury
Monitoring NTP offsetu i jakości źródła czasu pozwala wykryć host, zanim zacznie odrzucać tokeny lub uruchamiać zadania za wcześnie. Alarm powinien uwzględniać wymagania systemu, nie tylko ogólny próg.
Kontenery współdzielą zegar hosta, więc restart aplikacji nie naprawi problemu. Runbook musi prowadzić do właściwej warstwy infrastruktury.
Obserwowalność mierzy punktualność
Liczba błędów nie wystarcza. Potrzebne są scheduled-to-start lag, queue age, runtime, retries i liczba overdue. System może zwracać sukces, a przypomnienia wysyłać godzinę za późno.
Logi korelują job ID, plan, próbę i wynik. Pełny payload nie musi trafiać do telemetryki.
Deployment nie powinien podwajać schedulera
Podczas rolling update stara i nowa wersja mogą przez chwilę działać równolegle. Jeżeli obie bez koordynacji materializują te same zadania, powstają duplikaty jeszcze przed kolejką. Leader election, database lock albo unikalny klucz planowanego wystąpienia ogranicza ten problem.
Zmiana kodu recurrence wymaga również decyzji, czy już utworzone jobs zachowują poprzednią semantykę. Release powinien mieć jawny plan migracji harmonogramów.
Testowalny zegar usuwa prawdziwe czekanie
Kod czytający globalne „now” wszędzie jest niedeterministyczny. Wstrzykiwany clock pozwala przejść przez expiry, DST i backoff natychmiast. Test nie musi spać.
Integracja powinna symulować crash przed efektem, po efekcie i przed acknowledge. Właśnie te szczeliny decydują o duplikacie lub utracie.
Niezawodny czas oznacza jawną logikę stanu
System przechowuje intencję, akceptuje możliwość retry, zapewnia idempotency i świadomie decyduje o spóźnionych działaniach. Kalendarz nie jest mieszany z duration.
Timer sam nie gwarantuje procesu biznesowego. Gwarancja powstaje z trwałych rekordów, atomowych przejść, kontrolowanych retry i metryk porównujących plan z rzeczywistym skutkiem.