Systemy informacyjne MON mają wymaganie, z którym aplikacje komercyjne rzadko się spotykają: każda zmiana stanu systemu musi być trwale zarejestrowana, odporna na manipulacje i odtwarzalna. Analiza po operacji (After-Action Review), prawna odpowiedzialność za działania bojowe, ocena wartości rozpoznawczej zebranych danych — wszystko to wymaga autorytatywnego, niezmiennego zapisu tego, co system wiedział i jakie decyzje były podejmowane w każdym momencie. Event sourcing jest wzorcem architektonicznym, który to zapewnia, a zrozumienie jak poprawnie go wdrożyć w kontekście obronnym jest tematem tego artykułu.
Event sourcing kontra CRUD: podstawowa różnica
W tradycyjnym systemie CRUD (Create, Read, Update, Delete) stan jest przechowywany jako bieżąca wartość każdej encji. Gdy aktualizowana jest pozycja toru, poprzednia pozycja jest nadpisywana. Gdy SITREP jest korygowany, poprzednia wersja może lub nie być zachowana w zależności od projektu aplikacji. Stan systemu w dowolnym historycznym momencie nie jest wewnętrznie odtwarzalny z bazy danych — wymaga to jawnych decyzji projektowych dotyczących wersjonowania.
Event sourcing odwraca ten model. Stan nigdy nie jest przechowywany bezpośrednio. Zamiast tego każda zmiana stanu systemu jest przechowywana jako zdarzenie — niezmienny, dołączany-tylko rekord. Magazyn zdarzeń zawiera: TrackPositionUpdated w momencie T1 ze współrzędnymi X1; TrackPositionUpdated w momencie T2 ze współrzędnymi X2; TrackIdentityAttributed w momencie T3 do oznaczenia jednostki Y. Bieżący stan toru jest zawsze obliczalny przez odtworzenie strumienia zdarzeń od początku. Sam magazyn zdarzeń jest dziennikiem tylko-do-dołączania — żadne zdarzenie nigdy nie jest modyfikowane ani usuwane.
Konsekwencja operacyjna jest taka, że każda wersja każdej encji jest zawsze dostępna. «Co system wiedział o tym torze o 14:23:07?» — na to pytanie można odpowiedzieć, odtwarzając zdarzenia do tej sygnatury czasowej. Możliwość ta jest operacyjnie niezbędna dla systemów SZ RP i praktycznie bezkosztowa do wdrożenia, jeśli architektura jest projektowana z myślą o tym od początku.
Obronne przypadki użycia event sourcingu
Historia SITREP: Raporty sytuacyjne są często korygowane w miarę napływu nowego rozpoznania. W systemie CRUD bieżący SITREP odzwierciedla najnowszą ocenę, ale historia tego, jak ocena ewoluowała, jest tracona. W systemie event-sourcingowym każda rewizja jest zdarzeniem — SITREPCreated, SITREPRevised, SITREPApproved, SITREPDisseminated — a pełna historia jest zawsze dostępna do zapytania. Po operacji analitycy rozpoznania mogą odtworzyć dokładnie, co było wiadomo i kiedy, co jest niezbędne do oceny skutków bojowych i doskonalenia procesów rozpoznawczych.
Dziennik aktualizacji torów: Kinematyczna historia każdego toru w systemie — każda aktualizacja pozycji, każde przypisanie tożsamości, każda zmiana pewności — jest surowcem dla analizy wzorców aktywności, rekonstrukcji tras i analizy po operacji. Event sourcing sprawia, że ta historia jest nieodłączna od architektury, a nie dodatkiem. Zdarzenie TrackUpdated zawiera pełny stan toru w momencie aktualizacji, źródło aktualizacji, analityka lub algorytm odpowiedzialny oraz poprzedni stan, który jest zastępowany.
Odtwarzanie decyzji dowódczych dla AAR: Zaangażowanie bojowe wymagało decyzji o otwarciu ognia w momencie T na podstawie stanu systemu w momencie T. AAR musi odtworzyć stan systemu w momencie T: które tory były widoczne, które oceny zagrożeń były aktualne, które zasady zaangażowania obowiązywały, które rozkazy były aktywne. Event sourcing umożliwia to poprzez odtworzenie strumienia zdarzeń do momentu T i materializację stanu systemu w tym punkcie.
Technologie magazynów zdarzeń
EventStoreDB jest dedykowaną bazą danych magazynu zdarzeń, zaprojektowaną specjalnie dla architektur event-sourcingowych. Zapewnia natywne partycjonowanie strumieni (zdarzenia są organizowane według identyfikatora agregatu, więc wszystkie zdarzenia dla toru ID 12345 są w strumieniu «track-12345»), natywne kanały subskrypcji do budowania projekcji oraz wbudowane wsparcie dla optymistycznej kontroli współbieżności. EventStoreDB jest rozsądnym pierwszym wyborem dla nowych systemów obronnych z event sourcingiem, jeśli ograniczenia operacyjne pozwalają na dedykowany proces bazy danych.
Apache Kafka jako dziennik zdarzeń: Architektura dziennika Kafka z dołączaniem-tylko i partycjonowaniem ściśle odpowiada wymaganiom event sourcingu. Tematy Kafka partycjonują zdarzenia według typu agregatu; w ramach tematu zdarzenia są uporządkowane według partycji i przesunięcia. Mechanizm grup konsumentów umożliwia wielu projekcjom konsumowanie tego samego strumienia zdarzeń przy niezależnych przesunięciach. Rozproszony projekt Kafka zapewnia odporność na awarie, której EventStoreDB wymaga dodatkowej konfiguracji, aby osiągnąć. Dla systemów MON już używających Kafka dla potoków pozyskiwania danych, użycie Kafka jako magazynu zdarzeń unika wprowadzania drugiej specjalistycznej bazy danych.
PostgreSQL z tabelami tylko-do-dołączania JSONB: Dla systemów, w których wprowadzenie dedykowanego magazynu zdarzeń jest niewykonalne, PostgreSQL z tabelą tylko-do-dołączania i ładunkami zdarzeń JSONB jest praktyczną alternatywą. Schemat tabeli: event_id (UUID), aggregate_type (VARCHAR), aggregate_id (UUID), event_type (VARCHAR), event_data (JSONB), occurred_at (TIMESTAMPTZ), recorded_at (TIMESTAMPTZ), recorded_by (VARCHAR). Wyzwalacz lub ograniczenie na poziomie aplikacji uniemożliwia operacje UPDATE i DELETE na tabeli. Zapewnia to semantykę event sourcingu bez dedykowanej technologii.
Odbudowywanie stanu: projekcje, migawki i wydajność odtwarzania
Odbudowywanie bieżącego stanu encji poprzez odtwarzanie pełnej historii zdarzeń od początku jest obliczeniowo kosztowne dla encji z długą historią. Tor, który otrzymał 50 000 aktualizacji pozycji przez 30 dni, wymaga odtworzenia 50 000 zdarzeń, aby obliczyć jego bieżący stan. Jest to wyzwanie wydajnościowe event sourcingu.
Standardowym rozwiązaniem jest tworzenie migawek (snapshotting): okresowe materializowanie bieżącego stanu encji i przechowywanie go obok strumienia zdarzeń. Przy odbudowywaniu stanu system ładuje najnowszą migawkę i odtwarza tylko zdarzenia po sygnaturze czasowej migawki. Tor z 50 000 łącznymi zdarzeniami, ale migawką zrobioną po 49 900 zdarzeniach, wymaga odtworzenia tylko 100 zdarzeń. Częstotliwość migawek jest konfigurowalnym parametrem: częstsze migawki poprawiają opóźnienie odczytu kosztem większego magazynu.
Projekcje to zoptymalizowane pod kątem odczytu widoki wywiedzione ze strumienia zdarzeń. Projekcja «bieżące pozycje torów» materializuje najnowszą pozycję każdego toru konsumując zdarzenia TrackPositionUpdated. Projekcja «historia torów według jednostki» materializuje całą historię pozycji dla każdej jednostki. Projekcje mogą być odbudowywane od zera poprzez odtworzenie pełnego strumienia zdarzeń, co jest sposobem na odzyskanie danych po uszkodzonej bazie danych projekcji bez utraty danych.
Wymiary prawne i zgodności
Wymagania prawne dotyczące przechowywania danych obronnych różnią się znacznie w zależności od jurysdykcji krajowej i rodzaju operacji. Dla systemów MON/SZ RP minimum wymagane to: dowody integralności danych (przechowywany rekord nie był modyfikowany od momentu utworzenia), rejestry łańcucha przechowywania (kto miał dostęp i obsługiwał każdy element danych) oraz zgodność okresu przechowywania (dane są przechowywane przez wymagany okres i bezpiecznie usuwane po nim). Event sourcing zapewnia dowody integralności danych wewnętrznie — magazyn tylko-do-dołączania jest strukturalnie odporny na modyfikacje. Łańcuch przechowywania jest zapewniany przez metadane zdarzeń (pola recorded_by, processing_system_id). Zgodność okresu przechowywania wymaga jawnego egzekwowania polityki na poziomie infrastruktury.
Kluczowa obserwacja: Event sourcing w systemach obronnych to przede wszystkim nie wybór architektury oprogramowania — to operacyjna i prawna decyzja dotycząca zgodności. Dziennik audytu tylko-do-dołączania, który wytwarza, jest wymagany do analizy po operacji, odpowiedzialności prawnej i walidacji procesów rozpoznawczych MON. Systemy, którym go brakuje, są strukturalnie niezdolne do spełnienia tych wymagań, bez względu na to jak dobrze są zaprojektowane pod innymi względami.