
# Būsenų mašinos

Būsenų mašinos ir darbo eigos sprendžia skirtingas problemas.

Darbo eiga atsako į klausimą „koks darbas bus atliekamas toliau?“. Būsenų mašina atsako į klausimą „kokios būsenos yra šis objektas ir kokie įvykiai galimi iš šios būsenos?“. Šis skirtumas svarbus, kai kuriate ne vien žingsnių seką, o ilgai gyvuojantį objektą, kuris laikui bėgant reaguoja į išorinę įvestį, pavyzdžiui, agento seansą, pokalbio giją, peržiūros gyvavimo ciklą, bilietą ar patvirtinimo procesą.

## Trumpas pavyzdys

```php
use Queuety\Enums\StateMachineStatus;
use Queuety\Queuety;

$machine_id = Queuety::machine( 'agent_session' )
    ->version( 'agent-session.v1' )
    ->state( 'awaiting_user' )
    ->on( 'user_message', 'planning' )
    ->state( 'planning' )
    ->action( PlanSessionAction::class )
    ->on( 'planned', 'awaiting_review' )
    ->state( 'awaiting_review' )
    ->on( 'approve', 'completed', ReviewApprovedGuard::class )
    ->on( 'reject', 'awaiting_user' )
    ->state( 'completed', StateMachineStatus::Completed )
    ->dispatch( [ 'thread_id' => 42 ] );

Queuety::machine_event(
    $machine_id,
    'user_message',
    [ 'message' => 'Find competitors for this product' ]
);

Queuety::machine_event(
    $machine_id,
    'approve',
    [ 'approved' => true, 'reviewer' => 'editor@example.com' ]
);
```

Ši mašina pradeda veikti būsenoje `awaiting_user`, naudotojui atsiuntus pranešimą pereina į `planning`, leidžia eilėje esančiam veiksmui išsiųsti `planned` ir tada laukia būsenoje `awaiting_review`, kol išorinis patvirtinimas užbaigs seansą. Svarbi ne vien kodo sintaksė. Svarbu tai, kad gyvavimo ciklas yra aiškiai apibrėžtas, jį galima patikrinti ir jis valdomas įvykių.

## Kaip veikia mašina

Išsiuntus mašinos egzempliorių, Queuety išsaugo dabartinės būsenos pavadinimą, viešus būsenos duomenis, aprašo versiją ir maišą, galiojančius dabartinės būsenos gaunamus įvykius bei patikimą įvykių seką.

Jei įeinanti būsena turi `action()`, Queuety į eilę įtraukia būsenos įvedimo užduotį. Šis veiksmas gali tiesiog atnaujinti viešąją būseną ir palikti mašiną laukti kito įvykio arba išsiųsti `_event` ir pasirinktinai `_event_payload`, kad iškart būtų atliktas kitas perėjimas. Jei būsena neturi veiksmo ir nėra galutinė, mašina tiesiog laukia išorinių įvykių, siunčiamų naudojant `Queuety::machine_event()`.

## Kaip pasirinkti tarp darbo eigų ir būsenų mašinų

Naudokite darbo eigą, kai vykdymas iš esmės susideda iš žingsnių: gauti duomenis, atlikti kiekvieną darbą, palaukti, apibendrinti, užbaigti. Šis modelis tinka, kai pradžia ir pabaiga aiškios, o pagrindinis klausimas – kokį darbą atlikti toliau.

Naudokite būsenų mašiną, kai galiojantis elgesys priklauso nuo dabartinio gyvavimo ciklo etapo. Ji labiau tinka, kai įvykiai gali ateiti įvairia tvarka, objektas gali egzistuoti ilgai arba reikia aiškiai tikrinti gyvavimo ciklą, apimantį tokias būsenas kaip `awaiting_user`, `planning`, `running_agents`, `awaiting_review` ir `completed`.

## Kaip šie būdai dera tarpusavyje

Šie du pagrindiniai įrankiai geriausiai veikia kartu. Kai perėjimui reikia daugiau išteklių, būsenos veiksmas gali išsiųsti darbo eigą, o atlikusi darbą darbo eiga gali grąžinti įvykį būsenų mašinai. Taip būsenų mašina valdo gyvavimo ciklą, o darbo eigos atlieka daug išteklių reikalaujančius arba griežtai struktūruotus darbus.

## Konstruktoriaus struktūra

`StateMachineBuilder` sąmoningai išlaikytas nedidelis. `initial()` ir `state()` apibrėžia gyvavimo ciklo grafą. `action()` susieja eilėje esantį darbą su viena būsena. `on()` nurodo, kurie įvykiai gali perkelti mašiną į kitą būseną. `on_queue()`, `with_priority()` ir `max_attempts()` valdo būsenos veiksmų vykdymą, o `version()` ir `idempotency_key()` prideda išsaugomus siuntimo metaduomenis. `dispatch()` sukuria mašinos egzempliorių.

Būsenos veiksmai taip pat gali pateikti pasirinktinį metodą `config()`, kuriame naudojami tie patys išteklių politikos raktai kaip darbo eigos žingsniuose ir apdorojimo metoduose. Taip galima brangiai kainuojantį būsenos perėjimą įtraukti į bendrą lygiagretaus vykdymo grupę arba priskirti jam didesnį svorį, kai veiksmui reikia daugiau išteklių nei įprastam žingsniui.

Platesnis išteklių modelis aprašytas skiltyje [Išteklių valdymas](https://queuety.inline0.dev/lt/docs/features/resource-management).

## Sąsajos

Būsenos įvedimo veiksmai įgyvendina `Queuety\Contracts\StateAction`:

```php
namespace Queuety\Contracts;

interface StateAction {
    public function handle( array $state, ?string $event = null, array $event_payload = [], array $payload = [] ): array|string;
}
```

`$payload` yra struktūruoti veiksmo aprašo duomenys. Jei veiksmas nurodytas kaip paprastas klasės pavadinimas, duomenys tušti. Queuety sukuria veiksmus naudodamas `new $class()`, todėl veiksmo klasei reikia konstruktoriaus, kuriam nereikia jokių privalomų argumentų.

State actions taip pat gali apibrėžti pasirenkamą `config()` metodą su `concurrency_group`, `concurrency_limit` ir `cost_units`, kai į eilę įtrauktas veiksmas turi dalyvauti darbuotojų priėmime, svertinės eilės ar teikėjo biudžetuose ir kitose išteklių politikose.

Perėjimų sąlygos įgyvendina `Queuety\Contracts\StateGuard`:

```php
namespace Queuety\Contracts;

interface StateGuard {
    public function allows( array $state, array $event_payload, string $event, array $payload = [] ): bool;
}
```

## Apžiūros API

Naudokite fasadą veikiančioms mašinoms apžiūrėti:

```php
$status   = Queuety::machine_status( $machine_id );
$machines = Queuety::list_machines();
$events   = Queuety::machine_timeline( $machine_id );
$trace    = Queuety::machine_trace( $machine_id );
$state    = Queuety::machine_state_at( $machine_id, $event_id );
```

Būsenų mašinos neturi WP-CLI komandų: `wp queuety workflow ...` apima tik darbo eigas. Naudokite šias PHP API, pavyzdžiui, per `wp eval`, kad apžiūrėtumėte mašinas komandinėje eilutėje.

Šios API pateikia dabartinės būsenos pavadinimą, gyvavimo ciklo būseną, viešąją būseną, galimus įvykius, aprašo metaduomenis, visą perėjimų laiko juostą ir normalizuotą pėdsakų rinkinį derintuvo sąsajoms. Mašinų sąrašo eilutėse pateikiama aprašo versija, aprašo maiša ir idempotentiškumo raktas, kad sąrašo ekranuose būtų galima rodyti šaltinio / vykdymo aplinkos versiją neįkeliant kiekvienos mašinos atskirai. Pėdsakų rinkinyje yra sugrupuotos būsenos, neapdoroti įvykiai, susietos veiksmų užduotys, žurnalai, artefaktų nuorodos, dalių nuorodos, apdorojimo priemonės įvestis / išvestis, būsena prieš ir po, kontekstas, laiko duomenys ir struktūrizuotos klaidos.

## Agentų sesijos

Būsenų mašinos ypač naudingos agentų sistemoms, kurios labiau primena sesijas nei konvejerius. Sesiją, kuri pereina per `awaiting_user`, `planning`, `running_agents`, `awaiting_review` ir `completed`, paprastai lengviau suprasti kaip aiškų gyvavimo ciklą, o ne kaip vieną labai ilgą darbo eigos apibrėžtį su daugybe laukimų ir grįžtamųjų perėjimų.

## Taip pat žr.

- [Neuron Sesijos būsenų mašina](https://queuety.inline0.dev/lt/docs/examples/neuron-session-state-machine)
- [Neuron Atminties ir peržiūros būsenų mašina](https://queuety.inline0.dev/lt/docs/examples/neuron-memory-review)
- [Agentų orkestravimas](https://queuety.inline0.dev/lt/docs/workflows/agent-orchestration)
- [Darbo eigos signalai](https://queuety.inline0.dev/lt/docs/workflows/signals)
- [Darbo eigos priklausomybės](https://queuety.inline0.dev/lt/docs/workflows/dependencies)
- [Kartojimai](https://queuety.inline0.dev/lt/docs/workflows/repeats)
- [Artefaktai](https://queuety.inline0.dev/lt/docs/features/artifacts)
- [PHP API](https://queuety.inline0.dev/lt/docs/api)
