Stavové automaty
Stavové automaty a pracovné postupy riešia odlišné problémy.
Pracovný postup odpovedá na otázku „aká práca sa vykoná ďalej?“. Stavový automat odpovedá na otázku „v akom stave sa táto vec nachádza a ktoré udalosti sú odtiaľto platné?“. Tento rozdiel je dôležitý, keď vytvárate niečo, čo nie je iba postupnosťou krokov, ale dlhotrvajúcou entitou, ktorá časom reaguje na vonkajšie vstupy, napríklad reláciu agenta, chatové vlákno, životný cyklus kontroly, tiket alebo proces schvaľovania.
Rýchly príklad
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' ]
);
Tento automat začína v stave awaiting_user, po príchode používateľskej správy prejde do stavu planning, zaradená akcia vyšle planned a potom čaká v stave awaiting_review, kým externé schválenie nedokončí reláciu. Podstatné nie je samotná syntax kódu, ale to, že životný cyklus je explicitný, kontrolovateľný a riadený udalosťami.
Ako automat funguje
Pri zaradení inštancie automatu Queuety uloží názov aktuálneho stavu, verejné dáta stavu, verziu a hash definície, platné prichádzajúce udalosti pre aktuálny stav aj trvalú časovú os udalostí.
Ak má vstupný stav akciu action(), Queuety zaradí úlohu vstupu do stavu. Táto akcia môže jednoducho aktualizovať verejný stav a ponechať automat čakať na ďalšiu udalosť, alebo môže vyslať _event a prípadne aj _event_payload, aby okamžite vykonala ďalší prechod. Ak stav nemá akciu ani koncový stav, automat iba čaká na externé udalosti odoslané pomocou Queuety::machine_event().
Kedy zvoliť pracovné postupy a kedy stavové automaty
Pracovný postup použite, keď je vykonávanie založené predovšetkým na krokoch: načítať údaje, pri každej úlohe počkať, syntetizovať a dokončiť. Tento model sa hodí, keď má proces jasný začiatok aj koniec a hlavnou otázkou je, aká práca sa má vykonať ďalej.
Stavový automat použite, keď platné správanie závisí od aktuálnej fázy životného cyklu. Hodí sa viac, keď môžu udalosti prichádzať v rôznom poradí, entita môže existovať dlho alebo potrebujete explicitne kontrolovať životný cyklus so stavmi ako awaiting_user, planning, running_agents, awaiting_review a completed.
Ako spolu tieto dva prístupy fungujú
Tieto dve stavebné súčasti fungujú najlepšie spolu, nie ako konkurenti. Akcia stavu môže pri prechode vyžadujúcom náročnejšie vykonanie spustiť pracovný postup a pracovný postup môže po dokončení práce odoslať udalosť späť do automatu. Stavový automat tak v praxi riadi životný cyklus, zatiaľ čo pracovné postupy vykonávajú náročné alebo vysoko štruktúrované úlohy.
Štruktúra zostavovača
StateMachineBuilder je zámerne jednoduchý. initial() a state() definujú graf životného cyklu. action() priraďuje zaradenú prácu k jednému stavu. on() určuje, ktoré udalosti môžu presunúť automat do ďalšieho stavu. on_queue(), with_priority() a max_attempts() riadia vykonávanie akcií stavov, zatiaľ čo version() a idempotency_key() pripájajú trvalé metadáta zaraďovania. dispatch() vytvorí inštanciu automatu.
Akcie stavov môžu sprístupniť aj voliteľnú metódu config(), ktorá používa rovnaké kľúče pravidiel zdrojov ako kroky a obslužné triedy pracovných postupov. Vďaka tomu možno náročný prechod stavu zaradiť do zdieľanej skupiny súbežného vykonávania alebo mu priradiť vyššiu váhu náročnosti, ak spotrebúva väčší limit než bežný krok.
Širší model zdrojov je opísaný v časti Správa zdrojov.
Kontrakty
Akcie vstupu do stavu implementujú Queuety\Contracts\StateAction:
namespace Queuety\Contracts;
interface StateAction {
public function handle( array $state, ?string $event = null, array $event_payload = [], array $payload = [] ): array|string;
}
$payload predstavuje štruktúrované dáta z definície akcie; ak bola akcia zadaná ako obyčajný názov triedy, je prázdne. Queuety vytvára akcie pomocou new $class(), preto trieda akcie musí mať konštruktor bez povinných argumentov.
Akcie stavov môžu definovať aj voliteľnú metódu config() s concurrency_group, concurrency_limit a cost_units, keď sa má akcia zaradená do frontu zapojiť do prijímania úloh pracovníkmi, limitov váženého frontu alebo poskytovateľa a ďalších zásad správy zdrojov.
Stráže prechodov implementujú Queuety\Contracts\StateGuard:
namespace Queuety\Contracts;
interface StateGuard {
public function allows( array $state, array $event_payload, string $event, array $payload = [] ): bool;
}
Rozhrania API na kontrolu
Na kontrolu bežiacich strojov použite fasádu:
$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 );
Stavové automaty nemajú príkazy WP-CLI: wp queuety workflow ... pokrýva iba pracovné postupy. Na kontrolu strojov z príkazového riadka použite tieto rozhrania API PHP, napríklad cez wp eval.
Tieto rozhrania API sprístupňujú aktuálny názov stavu, stav životného cyklu, verejný stav, dostupné udalosti, metadáta definície, úplnú časovú os prechodov a normalizovaný balík stôp pre používateľské rozhrania debuggerov. Riadky v zozname strojov obsahujú verziu definície, hash definície a idempotency key, takže obrazovky zoznamov môžu zobraziť zdrojovú a runtime verziu bez načítania každého stroja zvlášť. Balík stôp obsahuje zoskupené stavy, nespracované udalosti, priradené úlohy akcií, logy, odkazy na artefakty a časti, vstup a výstup obslužných funkcií, stav pred a po, kontext, časové údaje a štruktúrované chyby.
Relácie agentov
Stavové automaty sú obzvlášť užitočné pre systémy agentov, ktoré fungujú skôr ako relácie než ako postupnosti úloh. Reláciu, ktorá prechádza stavmi awaiting_user, planning, running_agents, awaiting_review a completed, možno zvyčajne jednoduchšie pochopiť ako explicitný životný cyklus než ako jednu veľmi dlhú definíciu pracovného postupu s mnohými čakaniami a spätnými prechodmi.