JX / Junexis StateRola w platformie →
Menu State

Poznaj State

WprowadzenieProsty przykładZadania StateKiedy wybrać State?Zakres i dostępność

State / wykonanie i komunikacja

Co zostaje po zakończonym kroku?

Wyobraź sobie komponent, który wykonał krok pracy. Zanim rozpocznie się dalszy etap, zapisuje fakt: „pierwszy krok zakończony”.

Nowe uruchomienie nie musi zaczynać od zgadywania.

Może odczytać zachowany fakt i odwołać się do wcześniej zatwierdzonego wyniku.

1. Zapisujemy fakt

W prostym przykładzie informacja o zakończonym kroku zostaje zatwierdzona w State. Żądanie ma własny identyfikator, aby można było rozpoznać jego późniejsze ponowienie.

2. Uruchamiamy komponent ponownie

Nowy proces odczytuje ten sam fakt. Informacja nie znika wraz z zakończeniem pierwszego procesu.

3. Rozpoznajemy ponowienie

Ten sam zapis zostaje przesłany jeszcze raz z tym samym identyfikatorem. Przykład odzyskuje wcześniej zatwierdzony wynik zamiast traktować go jako nową zmianę.

Sukces: zachowany fakt i wynik żądania są dostępne po ponownym uruchomieniu.

Mały fragment szerszej roli State

State nie wykonuje kroku za komponent. Zachowuje przekazaną informację o wykonaniu. To, kiedy i na jakiej podstawie wolno ją zapisać, jest częścią konkretnej integracji. Ten zachowany fakt jest przykładem stanu potrzebnego do kontynuacji; szersza rola State obejmuje też uzgadnianie aktualnego stanu i rozliczanie niepewności.

Ten mały przykład pokazuje mechanizm istniejącego kodu. Nie jest pełnym scenariuszem wznowienia systemu rozproszonego ani dowodem skutku w zewnętrznym urządzeniu.

Dla zainteresowanych: kod i wynik lokalnej próby

Rzeczywisty konsument Rust używa lokalnego magazynu State. Uruchomiono dwa osobne procesy: zapis oraz odczyt z ponowieniem. Nie uruchamia to Scheduler Runtime, sieci ani kontroli uprawnień.

Zatwierdzono: execution/first-step = completed, wersja 1
Po ponownym uruchomieniu: execution/first-step = completed, wersja 1
To samo zadanie zapisu: zachowano wersje 1

use junexis_state::{ExpectedVersion, RequestId, storage::{DurableStore, file::FileMedia}};
use std::path::PathBuf;

fn main() {
    let mut args = std::env::args().skip(1);
    let mode = args.next().expect("podaj write albo read");
    let path = PathBuf::from(args.next().expect("podaj prywatny katalog proby"));
    let key = "execution/first-step";
    if mode == "write" {
        let media = FileMedia::create(&path).expect("nowy, prywatny nosnik");
        let mut store = DurableStore::initialize(media, [7; 16], 1).expect("inicjalizacja");
        let version = store.put(RequestId::new(1), key.into(), "completed".into(), ExpectedVersion::Missing)
            .expect("zatwierdzenie").expect("wynik zapisu");
        println!("Zatwierdzono: {key} = completed, wersja {}", version.as_u64());
    } else {
        assert_eq!(mode, "read");
        let media = FileMedia::open(&path).expect("otwarcie tego samego nosnika");
        let mut store = DurableStore::open(media, [7; 16], 1).expect("odtworzenie");
        let found = store.get(key).expect("odczyt").expect("zapisany fakt");
        assert_eq!(found.value, "completed");
        let version = found.version;
        println!("Po ponownym uruchomieniu: {key} = {}, wersja {}", found.value, version.as_u64());
        let repeated = store.put(RequestId::new(1), key.into(), "completed".into(), ExpectedVersion::Missing)
            .expect("ponowienie").expect("zachowany wynik");
        assert_eq!(repeated, version);
        println!("To samo zadanie zapisu: zachowano wersje {}", repeated.as_u64());
    }
}

Otwórz kod Rust · Otwórz wynik

Zadania State · Kiedy go wybrać?.