Przejdź do treści

Tryb rozgłoszeniowy (zdarzenia)

Tryb rozgłoszeniowy odwraca kierunek inicjatywy względem trybu żądaniowego: to system dziedzinowy zgłasza zdarzenie (utworzenie, zmiana, usunięcie zasobu), a API.ERP natychmiast eksportuje pełną zawartość powstałego/zmienionego zasobu do repozytorium integratora — bez konieczności cyklicznego odpytywania API.

Tryb rozgłoszeniowy działa naprzemiennie z trybem notyfikacyjnym — dla danego zasobu obowiązuje zawsze tylko jeden z nich, ustalony w ramach integracji.

Charakterystyka

  • Obsługa zdarzeń w systemach dziedzinowych — setki zdarzeń (FK, WMS, HR, ESM) mogą powodować eksport zasobu.
  • Pełna zawartość zasobu — do repozytorium integratora trafia kompletny, przekonwertowany model kanoniczny (np. Party, Invoice), bez potrzeby dodatkowego zapytania zwrotnego.
  • Natychmiastowy przepływ informacji po wystąpieniu zdarzenia w systemie źródłowym.

Przepływ informacji

Cel eksportu jest jednym z dwóch (do wyboru w ramach integracji): endpoint integratora — dostawa bezpośrednio do API integratora — albo magazyn obiektowy, z którego integrator odczytuje dane we własnym zakresie.

flowchart RL
    D1["FK"]:::domain --> A["API.ERP"]:::api
    D2["WMS"]:::domain --> A
    D3["HR"]:::domain --> A
    A -- "zasób — POST bezpośrednio" --> I["Aplikacja integratora<br/>(endpoint HTTP)"]:::integrator
    A -- "zasób — zapis obiektu" --> B["Magazyn obiektowy"]:::repo
    B -. "odczyt (integrator)" .-> I

    classDef integrator fill:#8BC34A,stroke:#558B2F,color:#000
    classDef api fill:#03A9F4,stroke:#0277BD,color:#000
    classDef domain fill:#FFA000,stroke:#E65100,color:#000
    classDef repo fill:#FFFFFF,stroke:#333,color:#000

Sekwencja przetworzenia jednego zdarzenia (dwa warianty celu):

sequenceDiagram
    participant D as Systemy dziedzinowe (FK / WMS / HR / ESM)
    participant A as API.ERP
    participant I as Aplikacja integratora / magazyn

    D->>A: Zdarzenie (utworzenie / zmiana / usunięcie zasobu)
    A->>A: Konwersja do modelu kanonicznego
    alt Endpoint HTTP (bezpośrednio do integratora)
        A->>I: POST — zasób
        I-->>A: 2xx (potwierdzenie odbioru)
    else Magazyn obiektowy
        A->>I: Zapis obiektu (zasób)
        Note over I: integrator odczytuje asynchronicznie
    end

Szczegóły obu celów: Repozytorium danych.

Repozytorium danych

API.ERP dostarcza zasób do celu wskazanego przez integratora. Dostępne są dwa typy celu:

  • Endpoint HTTP — dostawa bezpośrednio do API integratora (API.ERP jest klientem POST-a; nie ma pośredniego magazynu).
  • Magazyn obiektowy (Blob Storage) — API.ERP zapisuje obiekt do magazynu, a integrator odczytuje go we własnym zakresie (asynchronicznie).

Magazyn obiektowy (Blob Storage)

API.ERP zapisuje każdy zasób (lub powiadomienie) jako obiekt JSON w kontenerze wskazanym przez integratora.

  • Nazwa obiektu: {resourceType}/{id}_{znacznik-czasu}.json.
  • Uprawnienia connection string: API.ERP wyłącznie zapisuje — nie odczytuje ani nie usuwa danych. Poświadczenia muszą pozwalać na zapis i tworzenie obiektów w docelowym kontenerze oraz utworzenie kontenera, jeśli jeszcze nie istnieje (API.ERP zapewnia jego istnienie przed pierwszym zapisem).
  • Dla SAS: uprawnienia Write i Create; zakres obejmujący kontener i obiekty (aby możliwe było utworzenie kontenera i zapis obiektów).
  • Nie są wymagane uprawnienia Read, Delete ani List.
  • Zalecane: SAS ograniczony do jednego kontenera, z terminem ważności; connection string w formacie BlobEndpoint=...;SharedAccessSignature=... lub oparty o klucz konta.

Endpoint HTTP

API.ERP wysyła dane pojedynczym żądaniem HTTP POST na adres wskazany przez integratora.

  • Metoda: POST na jeden, stały URL (jedno wywołanie = jeden zasób lub jedno powiadomienie).
  • Body: JSON (camelCase) — pełny zasób kanoniczny (tryb rozgłoszeniowy) lub Notification (tryb notyfikacyjny).
  • Nagłówki: Content-Type: application/json; Authorization (Bearer JWT lub Basic — zależnie od ustaleń integracji); dodatkowo nagłówki metadanych zdarzenia identyfikujące jego typ i parametry.
  • Odpowiedź: endpoint musi zwrócić kod 2xx dla powodzenia (inny kod skutkuje ponowieniem wg polityki retry). Opcjonalny nagłówek Location z adresem utworzonego zasobu jest odczytywany i zapisywany.

Pełny kontrakt endpointu odbiorczego w formacie OpenAPI 3.0: API-ERP-Export-Receiver.yaml. Zarys:

paths:
  /:                              # ścieżka/host ustalane przez integratora
    post:
      security: [ { bearerAuth: [] }, { basicAuth: [] } ]   # Bearer JWT lub Basic
      requestBody:
        required: true
        content:
          application/json:
            schema:
              oneOf:
                - $ref: '#/components/schemas/Notification'        # tryb notyfikacyjny
                - $ref: '#/components/schemas/CanonicalResource'   # tryb rozgłoszeniowy
      responses:
        '200': { description: Przyjęto }        # dowolny 2xx = sukces
        '202': { description: Przyjęto do przetworzenia }
        # kod inny niż 2xx → ponowienie wg polityki retry

Zgodność z eksportem API.ERP

Body to model kanoniczny serializowany camelCase, z polem resourceType identyfikującym rodzaj zasobu (zgodnie z DomainResource; pole umożliwia też pakowanie do Bundle). Dla akcji create/update przesyłany jest pełny zasób; dla delete — ponieważ zasób źródłowy już nie istnieje — zdarzenie z referencją do usuniętego zasobu (bez treści). W trybie notyfikacyjnym wszystkie operacje, w tym deleted, są przenoszone jako Notification.

Potwierdzenie odbioru

  • Endpoint HTTP: potwierdzeniem przyjęcia jest kod odpowiedzi HTTP — dowolny 2xx oznacza sukces. API.ERP nie oczekuje żadnego dodatkowego callbacku ani treści odpowiedzi; wystarczy status. Brak 2xx, brak połączenia lub przekroczenie czasu = niepowodzenie (patrz niżej).
  • Magazyn obiektowy: brak potwierdzenia zwrotnego — dostarczenie jest uznane po udanym zapisie obiektu do magazynu. Integrator konsumuje obiekty asynchronicznie we własnym zakresie (np. nasłuch zdarzeń magazynu lub cykliczny odczyt).

Dostarczanie i ponawianie

  • Przy niepowodzeniu dostawy (brak połączenia, przekroczenie czasu, kod inny niż 2xx) element pozostaje w kolejce i jest ponawiany w kolejnych cyklach eksportu, aż do skonfigurowanego limitu prób.
  • Po wyczerpaniu limitu element trafia do martwej kolejki (dead-letter) i nie jest dalej wysyłany automatycznie — wymaga interwencji lub ponownego zlecenia.
  • Idempotencja (ważne): ponawianie oznacza, że integrator może otrzymać ten sam zasób/powiadomienie więcej niż raz. Odbiorca musi być idempotentny — rozróżniać duplikaty po id (i reference w Notification) i nie dublować skutków.
  • Kolejność dostarczenia nie jest gwarantowana — nie zakładaj, że zdarzenia przychodzą w kolejności ich wystąpienia.

Kiedy używać

Tryb rozgłoszeniowy pasuje tam, gdzie integrator potrzebuje kompletnych danych od razu, bez dodatkowego zapytania zwrotnego — np. pełna synchronizacja danych kontrahenta. Jeśli integratorowi wystarczy sama informacja o zmianie (a pełne dane pobiera na żądanie, gdy faktycznie ich potrzebuje), właściwy jest lżejszy tryb notyfikacyjny. Dla operacji inicjowanych przez integratora (zapis, zapytanie ad-hoc) właściwy jest tryb żądaniowy.

Odniesienia