20 mar 2025·7 min czytania

Przepływy zdarzeniowe vs API żądanie‑odpowiedź dla długotrwałych zadań

Porównanie przepływów zdarzeniowych i API żądanie‑odpowiedź dla długotrwałych procesów — zatwierdzenia, timery, retry i ścieżki audytu w aplikacjach biznesowych.

Przepływy zdarzeniowe vs API żądanie‑odpowiedź dla długotrwałych zadań

Dlaczego długotrwałe procesy są trudne w aplikacjach biznesowych

Proces jest „długotrwały”, gdy nie da się go zakończyć w jednym krótkim kroku. Może trwać minuty, godziny lub dni, bo zależy od ludzi, czasu lub systemów zewnętrznych. Wszystko, co wymaga zatwierdzeń, przekazania sprawy i oczekiwania, mieści się w tej kategorii.

Wtedy myślenie „żądanie‑odpowiedź” zaczyna się sypać. Wywołanie API jest zbudowane dla krótkiej wymiany: wyślij żądanie, dostaniesz odpowiedź, idź dalej. Długie zadania są bardziej jak opowieść z rozdziałami. Trzeba się zatrzymać, zapamiętać dokładnie, gdzie jesteśmy, i wznowić później bez zgadywania.

Widać to w codziennych aplikacjach: zatwierdzenia zakupów wymagające przełożonego i finansów, onboarding pracownika czekający na weryfikację dokumentów, zwroty zależne od dostawcy płatności, czy prośby o dostęp, które trzeba przejrzeć i zastosować.

Gdy zespoły traktują długi proces jak jedno wywołanie API, pojawia się kilka przewidywalnych problemów:

  • Aplikacja traci stan po restarcie lub wdrożeniu i nie potrafi wiarygodnie wznowić.
  • Retry powodują duplikaty: druga płatność, drugi e‑mail, podwójne zatwierdzenie.
  • Własność staje się niejasna: nikt nie wie, czy następnym ma działać wnioskodawca, przełożony czy zadanie systemowe.
  • Support nie ma widoczności i nie potrafi odpowiedzieć „gdzie to utknęło?” bez grzebania w logach.
  • Logika oczekiwania (timery, przypomnienia, terminy) trafia do kruchego kodu tła.

Przykład: pracownik prosi o dostęp do oprogramowania. Przełożony zatwierdza szybko, ale IT potrzebuje dwóch dni na provision. Jeśli aplikacja nie potrafi trzymać stanu procesu, wysyłać przypomnień i bezpiecznie wznawiać, dostajesz manualne follow‑upy, zdezorientowanych użytkowników i dodatkową pracę.

Dlatego wybór między przepływami zdarzeniowymi a API żądanie‑odpowiedź ma znaczenie dla długotrwałych procesów biznesowych.

Dwa modele myślenia: wywołania synchroniczne kontra zdarzenia w czasie

Najprostsze porównanie sprowadza się do pytania: czy praca kończy się, gdy użytkownik czeka, czy trwa dalej po jego odejściu?

API żądanie‑odpowiedź to pojedyncza wymiana: jedno wywołanie i jedna odpowiedź. Pasuje do pracy, która kończy się szybko i przewidywalnie — tworzenie rekordu, kalkulacja wyceny, sprawdzenie stanów magazynowych. Serwer wykonuje zadanie, zwraca sukces lub błąd i interakcja się kończy.

Przepływ zdarzeniowy to seria reakcji w czasie. Coś się dzieje (zamówienie stworzone, przełożony zatwierdził, timer upłynął) i workflow przechodzi do następnego kroku. Ten model pasuje do pracy z przekazaniami, oczekiwaniem, retry i przypomnieniami.

Praktyczna różnica to stan.

W request‑response stan często żyje w kontekście bieżącego żądania plus pamięci serwera do momentu wysłania odpowiedzi. W przepływach zdarzeniowych stan musi być przechowywany (np. w PostgreSQL), żeby proces mógł zostać wznowiony później.

Obsługa awarii też się zmienia. Request‑response zwraca błąd i prosi klienta o ponowienie. Workflow zapisuje porażkę i może bezpiecznie retry, gdy warunki się poprawią. Może też logować każdy krok jako zdarzenie, co ułatwia odtworzenie historii.

Prosty przykład: “Złóż raport wydatków” może być synchroniczny. „Uzyskaj zatwierdzenie, poczekaj 3 dni, przypomnij przełożonemu, potem wypłać” już nie.

Zatwierdzenia: jak każdy model radzi sobie z decyzjami ludzi

Zatwierdzenia to moment, gdy długotrwała praca staje się realna. Krok systemowy trwa milisekundy, ale osoba może odpowiedzieć po dwóch minutach albo po dwóch dniach. Kluczowy wybór to: czy modelujesz to jako wstrzymany proces, czy jako nowe zdarzenie, które nadejdzie później.

W API żądanie‑odpowiedź zatwierdzenia często przybierają niezgrabny kształt:

  • Blokowanie (niepraktyczne)
  • Polling (klient pyta „zatwierdzone już?” ciągle)
  • Callbacky/webhooki (serwer oddzwoni później)

Wszystkie to działają, ale dodają instalację tylko po to, by połączyć „czas ludzki” z „czasem API”.

W modelu zdarzeniowym zatwierdzenie wygląda jak opowieść. Aplikacja zapisuje coś jak „ExpenseSubmitted”, potem otrzymuje „ExpenseApproved” lub „ExpenseRejected”. Silnik workflow (albo własny state machine) przesuwa rekord dalej dopiero, gdy nadejdzie kolejne zdarzenie. To odpowiada temu, jak ludzie myślą o krokach biznesowych: złoż, przejrzyj, zdecyduj.

Złożoność rośnie szybko przy wielu zatwierdzających i regułach eskalacji. Możesz wymagać zatwierdzeń menedżera i finansów, a jednocześnie pozwolić seniorowi na override. Jeśli tych reguł nie zamodelujesz jasno, proces staje się trudny do zrozumienia i audytu.

Prosty model zatwierdzania, który się skaluje

Praktyczny wzorzec to posiadanie jednego rekordu „request”, a decyzji przechowywanych oddzielnie. Dzięki temu obsłużysz wielu zatwierdzających bez przepisywania logiki rdzenia.

Przechwyć kilka elementów jako pierwszorzędne rekordy:

  • Żądanie zatwierdzenia: co jest zatwierdzane i jego aktualny status
  • Indywidualne decyzje: kto zdecydował, akceptuj/odrzuć, znacznik czasu, powód
  • Wymagani zatwierdzający: rola lub osoba oraz reguły porządku
  • Reguły wyniku: „dowolny”, „większość”, „wszyscy wymagani”, „override dozwolony”

Cokolwiek wybierzesz, zapisuj kto zatwierdził co, kiedy i dlaczego jako dane, a nie jako linijkę logu.

Timery i oczekiwanie: przypomnienia, terminy i eskalacje

Oczekiwanie to miejsce, gdzie długie zadania robią się chaotyczne. Ludzie idą na lunch, kalendarze wypełniają się, a „odezwiemy się” zmienia się w „kto teraz to ma?”. To jedna z najjaśniejszych różnic między przepływami zdarzeniowymi a API żądanie‑odpowiedź.

W request‑response czas jest niewygodny. Wywołania HTTP mają timeout, więc nie utrzymasz otwartego żądania przez dwa dni. Zespoły zwykle kończą z patternami takimi jak polling, odrębne zadanie harmonogramu skanujące bazę, albo ręczne skrypty do przeterminowanych przypadków. To działa, ale logika oczekiwania żyje poza procesem. Łatwo przegapić przypadki brzegowe: co gdy job uruchomi się dwukrotnie, albo rekord zmienił się tuż przed wysłaniem przypomnienia.

Workflows traktują czas jak normalny krok. Możesz powiedzieć: poczekaj 24 godziny, wyślij przypomnienie, potem po 48 godzinach eskaluj do innego zatwierdzającego. System przechowuje stan, więc terminy nie chowają się w oddzielnym projekcie „cron + zapytania”.

Prosta reguła zatwierdzania może brzmieć:

Po złożeniu raportu wydatków poczekaj 1 dzień. Jeśli status nadal „Pending”, powiadom menedżera. Po 2 dniach, jeśli nadal oczekuje, przypisz do leadu menedżera i zapisz eskalację.

Kluczowe pytanie: co robisz, gdy timer odpali, ale świat się zmienił. Dobry workflow zawsze ponownie sprawdza stan przed akcją:

  • Załaduj najnowszy status
  • Potwierdź, że nadal jest pending
  • Potwierdź, że przypisany użytkownik nadal jest ważny (zmiany w zespole się zdarzają)
  • Zapisz, co zdecydowano i dlaczego

Retry i odzyskiwanie bez duplikatów

Buduj trwałe przepływy zatwierdzeń
Zaprojektuj długotrwały proces zatwierdzania ze stanem zapisanym w bazie, retry i jasnymi polami audytu.
Wypróbuj AppMaster

Retry to to, co robisz, gdy coś nie zadziała z przyczyn niezależnych: gateway płatności timeoutuje, dostawca e‑mail zwraca błąd tymczasowy, albo aplikacja zapisała krok A, ale padła przed krokiem B. Niebezpieczeństwo jest proste: spróbujesz ponownie i przypadkowo zrobisz akcję dwa razy.

W request‑response zwykle klient wywołuje endpoint, czeka i jeśli nie ma jasnego sukcesu, próbuje ponownie. Aby to zabezpieczyć, serwer musi traktować powtarzające się wywołania jako tę samą intencję.

Praktyczne rozwiązanie to klucz idempotency: klient wysyła unikalny token jak pay:invoice-583:attempt-1. Serwer przechowuje wynik dla tego klucza i zwraca ten sam rezultat przy powtórkach. To zapobiega podwójnym opłatom, zduplikowanym ticketom czy podwójnym zatwierdzeniom.

Przepływy zdarzeniowe mają inny rodzaj ryzyka duplikacji. Zdarzenia często są dostarczane co najmniej raz, co oznacza, że duplikaty mogą się pojawić nawet przy poprawnym działaniu. Konsumenci muszą robić deduplikację: zapisz ID zdarzenia (lub klucz biznesowy jak invoice_id + step) i ignoruj powtórki. To zasadnicza różnica: request‑response skupia się na bezpiecznym odtwarzaniu wywołań, zdarzenia — na bezpiecznym odtwarzaniu wiadomości.

Kilka reguł retry sprawdza się w obu modelach:

  • Używaj backoffu (np. 10s, 30s, 2m).
  • Ustal limit prób.
  • Oddziel błędy tymczasowe (retry) od trwałych (fail fast).
  • Kieruj powtarzające się porażki do stanu „wymaga uwagi”.
  • Loguj każdą próbę, żeby później móc wytłumaczyć, co się stało.

Retry powinny być explicite w procesie, nie ukrytą magią. Takie podejście czyni błędy widocznymi i możliwymi do naprawienia.

Ścieżki audytu: jak uczynić proces wytłumaczalnym

Projektuj zdarzenia jako przepływ
Zamień swój proces w stany i zdarzenia przy użyciu logiki wizualnej zamiast kruchego skryptu.
Zacznij budować

Ślad audytu to twój plik „dlaczego”. Gdy ktoś pyta „dlaczego ten wydatek został odrzucony?”, powinieneś umieć odpowiedzieć bez zgadywania, nawet po miesiącach. To ważne w obu modelach, ale wygląda inaczej.

Dla każdego długotrwałego procesu zapisuj fakty, które pozwolą odtworzyć historię:

  • Aktor: kto to zrobił (użytkownik, serwis, timer systemowy)
  • Czas: kiedy się stało (ze strefą czasową)
  • Wejście: co wtedy było znane (kwota, dostawca, progi polityki, zatwierdzenia)
  • Wynik: jaka decyzja lub akcja nastąpiła (zatwierdzono, odrzucono, wypłacono, retry)
  • Wersja reguły: która wersja polityki/logiki była użyta

Przepływy zdarzeniowe ułatwiają audyt, bo każdy krok naturalnie produkuje zdarzenie jak „ManagerApproved” czy „PaymentFailed”. Jeśli przechowasz zdarzenia z payloadem i aktorem, otrzymasz czystą linię czasu. Kluczowe jest, by zdarzenia były opisowe i dostępne do zapytań po sprawie.

W request‑response też da się audytować, ale historia często rozproszona jest między usługami. Jeden endpoint loguje „zatwierdzono”, inny „żądanie płatności”, trzeci „retry powiódł się”. Jeśli każdy używa innego formatu, audyt zamienia się w dochodzenie.

Proste remedium to wspólne ID sprawy (correlation ID). To jeden identyfikator, który dołączasz do każdego żądania, zdarzenia i rekordu bazy dla instancji procesu, np. „EXP‑2026‑00173”. Dzięki temu wyśledzisz całą drogę procesu.

Wybór właściwego podejścia: mocne strony i kompromisy

Najlepszy wybór zależy od tego, czy potrzebujesz odpowiedzi natychmiast, czy proces ma się toczyć przez godziny lub dni.

Request‑response sprawdza się, gdy praca jest krótka, a reguły proste. Użytkownik wysyła formularz, serwer waliduje, zapisuje dane i zwraca sukces lub błąd. Dobrze pasuje do jednoetapowych akcji: create, update, check permission.

Boli, gdy „pojedyncze żądanie” cicho zmienia się w wiele kroków: oczekiwanie na zatwierdzenie, wywołania systemów zewnętrznych, timeouty czy rozgałęzienia. Albo trzymasz połączenie otwarte (kruche), albo przenosisz oczekiwanie i retry do zadań tła, które trudno zrozumieć.

Przepływy zdarzeniowe błyszczą, gdy proces to opowieść w czasie. Każdy krok reaguje na nowe zdarzenie (zatwierdzono, odrzucono, timer, błąd płatności) i decyduje, co dalej. Ułatwia to wstrzymywanie, wznawianie, retry i utrzymanie jasnego śladu decyzji.

Są kompromisy:

  • Prostota kontra trwałość: request‑response łatwiej zacząć, zdarzenia są bezpieczniejsze dla długiego oczekiwania.
  • Styl debugowania: request‑response to prosta linia, workflow wymaga śledzenia kroków.
  • Narzędzia i nawyki: zdarzenia potrzebują dobrego logowania, correlation ID i klarownych modeli stanu.
  • Zarządzanie zmianami: workflowy ewoluują i rozgałęziają się; dobrze zaprojektowane zdarzeniowe podejścia lepiej radzą sobie z nowymi ścieżkami.

Przykład: raport wydatków wymagający zatwierdzenia menedżera, potem finansów, potem płatności. Jeśli płatność się nie powiedzie, chcesz retry bez podwójnej wypłaty — to naturalnie pasuje do modelu zdarzeniowego. Jeśli to tylko „złóż wydatki” z szybkim sprawdzeniem, request‑response wystarczy.

Krok po kroku: projektowanie długotrwałego procesu odpornego na opóźnienia

Wdróż bez przepisywania
Uruchamiaj przepływy w AppMaster Cloud lub wdrażaj we własnej chmurze, gdy będziesz gotowy.
Wdrażaj teraz

Długotrwałe procesy zawodzą w nudny sposób: karta zamknięta, restart serwera, zatwierdzenie trwa trzy dni, provider płatności timeoutuje. Projektuj z myślą o tych opóźnieniach od początku, niezależnie od wybranego modelu.

Zacznij od zdefiniowania małego zestawu stanów, które można zapisać i wznowić. Jeśli nie potrafisz wskazać bieżącego stanu w bazie, nie masz naprawdę wznowialnego workflow.

Prosty ciąg projektowy

  1. Ustal granice: określ wyzwalacz startowy, warunek zakończenia i kilka kluczowych stanów (Pending approval, Approved, Rejected, Expired, Completed).
  2. Nazwij zdarzenia i decyzje: zapisz, co może się wydarzyć w czasie (Submitted, Approved, Rejected, TimerFired, RetryScheduled). Używaj nazw w czasie przeszłym.
  3. Wybierz punkty oczekiwania: zidentyfikuj, gdzie proces zatrzymuje się dla człowieka, systemu zewnętrznego lub terminu.
  4. Dodaj reguły timerów i retry dla każdego kroku: ustal, co zrobić, gdy minie czas lub wywołanie się nie powiedzie (backoff, max attempts, eskalacja, poddanie się).
  5. Zdefiniuj wznowienie procesu: dla każdego zdarzenia lub callbacku ładuj zapisany stan, weryfikuj, że nadal jest ważny, a potem przejdź do następnego stanu.

Aby przetrwać restarty, zachowaj minimalne dane potrzebne do bezpiecznego kontynuowania. Zapisz wystarczająco, by móc uruchomić ponownie bez zgadywania:

  • ID instancji procesu i aktualny stan
  • Kto może działać dalej (assignee/rola) i jakie podjął decyzje
  • Terminy (due_at, remind_at) i poziom eskalacji
  • Metadane retry (liczba prób, ostatni błąd, next_retry_at)
  • Klucz idempotencji lub flagi „już wykonano” dla efektów ubocznych (wysłano wiadomość, obciążono kartę)

Jeśli możesz odtworzyć „gdzie jesteśmy” i „co dalej wolno zrobić” z zapisanych danych, opóźnienia przestają być straszne.

Typowe błędy i jak ich unikać

Długotrwałe procesy zwykle łamią się dopiero, gdy pojawią się realni użytkownicy. Zatwierdzenie trwa dwa dni, retry odpala w złym momencie i masz podwójną płatność lub brak śladu audytu.

Typowe błędy:

  • Trzymanie żądania HTTP otwartego w oczekiwaniu na zatwierdzenie. Timeoutuje, zajmuje zasoby i daje użytkownikowi mylne wrażenie, że „coś się dzieje”.
  • Retry bez idempotencji. Usterka sieci zamienia się w duplikaty faktur, e‑maili lub przejść „Zatwierdzono”.
  • Brak przechowywania stanu procesu. Jeśli stan żyje w pamięci, restart go kasuje. Jeśli tylko w logach, nie potrafisz bezpiecznie kontynuować.
  • Chaotyczny ślad audytu. Zdarzenia mają różne zegary i formaty, więc oś czasu nie jest wiarygodna podczas incydentu lub przeglądu zgodności.
  • Mieszanie async i sync bez jednego źródła prawdy. Jeden system mówi „Zapłacono”, inny „Oczekuje” i nikt nie wie, który jest prawdziwy.

Prosty przykład: raport wydatków zatwierdzony w czacie, webhook przychodzi późno, a API płatności dostaje retry. Bez stanu i idempotencji retry może wysłać płatność dwukrotnie, a twoje zapisy nie wyjaśnią dlaczego.

Większość poprawek sprowadza się do jawności:

  • Persistuj przejścia stanu (Requested, Approved, Rejected, Paid) w bazie z informacją kto/co je zmieniło.
  • Używaj kluczy idempotencji dla każdego efektu ubocznego (płatności, e‑maile, tickety) i zapisuj wynik.
  • Oddziel „zaakceptuj żądanie” od „dokończ pracy”: zwróć szybko, a potem dokończ workflow w tle.
  • Standaryzuj znaczniki czasu (UTC), dodaj correlation ID i zapisuj zarówno żądanie, jak i rezultat.

Szybka lista kontrolna przed budową

Zachowaj czystą ścieżkę kodu
Generuj rzeczywisty kod źródłowy, gdy potrzebujesz pełnej kontroli nad hostingiem lub przeglądem.
Eksportuj kod

Długotrwała praca to mniej jedno idealne wywołanie, a więcej zachowania poprawnego po opóźnieniach, przy ludziach i awariach.

Zapisz, co oznacza „bezpieczne kontynuowanie” dla twojego procesu. Jeśli aplikacja restartuje się w połowie, powinieneś móc wznowić od ostatniego znanego kroku bez zgadywania.

Praktyczna lista kontrolna:

  • Zdefiniuj, jak proces wznawia się po awarii lub wdrożeniu. Jaki stan jest zapisany i co wykona się dalej?
  • Nadaj każdej instancji unikalny klucz procesu (np. ExpenseRequest‑10482) i jasny model statusów (Submitted, Waiting for Manager, Approved, Paid, Failed).
  • Traktuj zatwierdzenia jako rekordy, nie tylko jako outcome: kto zatwierdził lub odrzucił, kiedy i z jakim powodem/komentarzem.
  • Zmapuj reguły oczekiwania: przypomnienia, terminy, eskalacje, wygaśnięcia. Nadaj właściciela dla każdego timera (manager, finance, system).
  • Zaplanuj obsługę błędów: retry musi być ograniczony i bezpieczny, a także powinien istnieć punkt „wymaga przeglądu”, gdzie człowiek może poprawić dane lub zatwierdzić powtórkę.

Test sanity: wyobraź sobie, że provider płatności timeoutuje po tym, jak już obciążyłeś kartę. Twój projekt powinien zapobiec podwójnemu obciążeniu, a mimo to pozwolić procesowi się dokończyć.

Przykład: zatwierdzenie wydatku z terminem i retry płatności

Przestań walczyć z długimi zadaniami
Zastąp polling i jednorazowe cron-joby przepływem, który śledzi, co robić dalej.
Wypróbuj no-code

Scenariusz: pracownik składa rachunek taxi na 120 USD do zwrotu. Potrzebne jest zatwierdzenie menedżera w ciągu 48 godzin. Po zatwierdzeniu system wypłaca środek pracownikowi. Jeśli płatność zawiedzie, retry odbywa się bezpiecznie i zostawia czytelny zapis.

Przebieg w modelu request-response

W request‑response aplikacja często zachowuje się jak rozmowa, którą trzeba stale sprawdzać.

Pracownik klika Wyślij. Serwer tworzy rekord z status „Pending approval” i zwraca ID. Menedżer dostaje powiadomienie, ale aplikacja pracownika zwykle polluje status, np. GET reimbursement status by ID.

Aby wymusić termin 48 godzin, uruchamiasz albo zadanie harmonogramu skanujące przegrane żądania, albo zapisujesz timestamp terminu i sprawdzas przy pollingu. Jeśli job się opóźni, użytkownicy zobaczą nieaktualny status.

Gdy menedżer zatwierdza, serwer zmienia status na „Approved” i wywołuje dostawcę płatności. Jeśli Stripe zwróci błąd tymczasowy, serwer musi zdecydować, czy retryować teraz, później, czy zgłosić błąd. Bez ostrożnych kluczy idempotencji retry może stworzyć podwójną wypłatę.

Przebieg w modelu zdarzeniowym

W modelu zdarzeniowym każda zmiana to zarejestrowany fakt.

Pracownik wysyła, powstaje zdarzenie „ExpenseSubmitted”. Workflow startuje i czeka na „ManagerApproved” albo na timer „DeadlineReached” po 48 godzinach. Jeśli timer odpali pierwszy, workflow zapisuje „AutoRejected” i powód.

Po zatwierdzeniu workflow zapisuje „PayoutRequested” i próbuje płatności. Jeśli Stripe timeoutuje, zapisuje „PayoutFailed” z kodem błędu, planuje retry (np. za 15 minut) i dopiero raz zapisuje „PayoutSucceeded” używając klucza idempotencji.

Dla użytkownika widok jest prosty:

  • Pending approval (48 godzin pozostało)
  • Approved, wypłata w toku
  • Retry płatności zaplanowany
  • Wypłacono

Ślad audytu czyta się jak oś czasu: submitted, approved, deadline checked, payout attempted, failed, retried, paid.

Następne kroki: zamiana modelu w działającą aplikację

Wybierz jeden realny proces i zbuduj go end‑to‑end zanim uogólnisz. Zatwierdzenie wydatku, onboarding i obsługa zwrotów to dobre starty — obejmują kroki ludzkie, oczekiwanie i ścieżki błędów. Trzymaj cel mały: jedna ścieżka szczęśliwa i dwa najczęstsze wyjątki.

Opisz proces jako stany i zdarzenia, nie jako ekrany. Na przykład: „Submitted” -> „ManagerApproved” -> „PaymentRequested” -> „Paid”, z rozgałęzieniami jak „ApprovalRejected” czy „PaymentFailed”. Kiedy widzisz punkty oczekiwania i efekty uboczne jasno, wybór między przepływami zdarzeniowymi a request‑response staje się praktyczny.

Zdecyduj, gdzie przechowywany jest stan procesu. Baza danych może wystarczyć, jeśli flow jest prosty i możesz wymusić aktualizacje w jednym miejscu. Silnik workflow pomaga, gdy potrzebujesz timerów, retry i rozgałęzień, bo on śledzi, co jest do zrobienia dalej.

Dodaj pola audytu od pierwszego dnia. Przechowuj kto co zrobił, kiedy i dlaczego (komentarz lub kod powodu). Gdy ktoś zapyta „dlaczego ta płatność została powtórzona?”, chcesz prostą odpowiedź bez grzebania w logach.

Jeśli budujesz workflow w platformie no-code, AppMaster jest jedną z opcji, gdzie możesz modelować dane w PostgreSQL i wizualnie budować logikę procesu, co ułatwia utrzymanie spójnych zatwierdzeń i śladu audytu w aplikacjach web i mobilnych.

FAQ

When should I use request-response instead of an event-driven workflow?

Używaj request-response, gdy praca kończy się szybko i przewidywalnie, podczas gdy użytkownik czeka — np. tworzenie rekordu lub walidacja formularza. Stosuj przepływy zdarzeniowe, gdy proces trwa od minut do dni, obejmuje zatwierdzenia ludzkie, timery, retry i musi bezpiecznie wznowić się po restarcie.

Why do long-running processes break when built like a single API call?

Długotrwałe zadania nie mieszczą się w jednym żądaniu HTTP: połączenia mają timeouty, serwery się restartują, a praca często zależy od ludzi lub systemów zewnętrznych. Traktując to jak jedno wywołanie, zwykle tracisz stan, dostajesz duplikaty przy retry i kończysz z rozproszonymi skryptami tła do obsługi oczekiwania.

How do I make a long-running process resumable after a restart?

Domyślnie zapisuj jasny stan procesu w bazie i przesuwaj go jedynie przez explicite przejścia. Przechowuj ID instancji procesu, aktualny status, kto może działać dalej i kluczowe znaczniki czasu, żeby bezpiecznie wznowić po wdrożeniach, awariach czy opóźnieniach.

What’s the cleanest way to handle human approvals?

Modeluj zatwierdzenia jako zatrzymany krok, który wznawia się po nadejściu decyzji, zamiast blokować albo bez przerwy pollować. Zapisuj każdą decyzję jako dane (kto, kiedy, akceptuj/odrzuć i powód), by przepływ mógł deterministycznie i audytowalnie przejść dalej.

Is polling for approval status a bad idea?

Polling działa w prostych przypadkach, ale generuje hałas i opóźnienia, bo klient ciągle pyta „czy już?”. Lepszym domyśłem jest wypychanie powiadomienia przy zmianie i pozwolenie klientowi na odświeżenie na żądanie, podczas gdy serwer pozostaje źródłem prawdy.

How should I implement reminders, deadlines, and escalations?

Traktuj czas jako część procesu: zapisuj terminy i czasy przypomnień, a gdy timer zadziała, przed podjęciem akcji ponownie sprawdź aktualny stan. Dzięki temu nie wyślesz przypomnienia po tym, jak już ktoś zatwierdził, i eskalacje będą spójne nawet jeśli zadania cykliczne uruchomią się spóźnione lub wielokrotnie.

How do I prevent double payments or duplicate emails when retries happen?

Dla każdego efektu ubocznego (np. obciążenie karty, wysłanie e-maila) stosuj klucze idempotentności i zapisuj wynik dla tego klucza. Retry staje się wtedy bezpieczny, bo powtórzenie tej samej intencji zwróci ten sam wynik zamiast wykonać akcję ponownie. Przykład klucza: pay:invoice-583:attempt-1.

How do I handle duplicate events in an event-driven system?

Zakładaj, że komunikaty mogą zostać dostarczone więcej niż raz i projektuj konsumentów z deduplikacją. Przechowuj ID zdarzenia (lub klucz biznesowy dla kroku) i ignoruj powtórki, aby replay nie uruchomił tej samej akcji dwukrotnie.

What should an audit trail include for long-running workflows?

Zarejestruj oś czasu faktów: aktor, znacznik czasu, input w momencie zdarzenia, rezultat i wersja reguły/polityki użytej przy decyzji. Przypisz jedną sprawę/ID korelacji do wszystkiego, co dotyczy procesu, żeby support mógł odpowiedzieć „gdzie to utknęło?” bez grzebania w niepowiązanych logach.

What’s a practical data model for approvals that won’t get messy as rules grow?

Trzymaj jeden rekord żądania jako „sprawę”, zapisuj decyzje osobno i napędzaj zmiany stanu przez zapisane przejścia, które można odtworzyć. W platformach no-code, takich jak AppMaster, możesz modelować dane w PostgreSQL i wizualnie implementować logikę kroków, co pomaga utrzymać spójność zatwierdzeń, retry i pól audytu w całej aplikacji.

Łatwy do uruchomienia
Stworzyć coś niesamowitego

Eksperymentuj z AppMaster z darmowym planem.
Kiedy będziesz gotowy, możesz wybrać odpowiednią subskrypcję.

Rozpocznij