Signály pracovného postupu
Pracovné postupy možno pozastaviť a čakať na externý vstup pomocou signálov. Metódy nástroja na tvorbu wait_for_signal() a wait_for_signals() vkladajú kroky, ktoré zablokujú pracovný postup, kým vaša aplikácia, operátor alebo iný systém neodošle očakávaný signál cez Queuety::signal().
Pri procesoch s účasťou človeka obsahuje Queuety aj:
wait_for_approval()pre menný priestor údajov schváleniawait_for_input()pre štruktúrovaný vstup od človekawait_for_decision()pre explicitné výsledky schválenia alebo zamietnutia
Väčší ucelený príklad, ktorý spája behy agentov s kontrolnými bodmi pre človeka, nájdete v téme Orchestrácia agentov.
Metóda ->wait_for_signal()
Pridajte do pracovného postupu krok čakania na signál:
use Queuety\Queuety;
$workflow_id = Queuety::workflow( 'content_approval' )
->then( DraftContentHandler::class )
->wait_for_signal( 'approved' )
->then( PublishContentHandler::class )
->dispatch( [ 'post_id' => 99 ] );
Keď pracovný postup dosiahne krok wait_for_signal, nastaví svoj stav na waiting_for_signal a pozastaví sa. Počas čakania nebežia žiadne úlohy a nespotrebúvajú sa žiadne prostriedky.
Jeden obsah signálu sa predvolene zlúči s najvyššou úrovňou stavu pracovného postupu. Ak chcete obsah namiesto toho uložiť pod vlastným menným priestorom, odovzdajte result_key:
$workflow_id = Queuety::workflow( 'content_approval' )
->then( DraftContentHandler::class )
->wait_for_signal( 'approved', 'approval' )
->then( PublishContentHandler::class )
->dispatch( [ 'post_id' => 99 ] );
Po prijatí signálu $state['approval'] obsahuje pole s údajmi signálu.
Čakanie na viacero signálov
Použite wait_for_signals(), keď sa má pracovný postup odblokovať po prijatí niektorého z viacerých možných signálov alebo keď musí pred pokračovaním zhromaždiť všetky požadované signály.
use Queuety\Enums\WaitMode;
$workflow_id = Queuety::workflow( 'moderation_gate' )
->then( SubmitForReviewHandler::class )
->wait_for_signals(
[ 'editor_approved', 'legal_approved' ],
WaitMode::All,
'approvals'
)
->then( PublishContentHandler::class )
->dispatch();
WaitMode::Allčaká, kým sa zaznamenajú všetky nastavené signály.WaitMode::Anypokračuje hneď po prijatí prvého nastaveného signálu.
Ak použijete result_key, čakanie na viacero signálov uloží asociatívne pole indexované názvom signálu:
[
'editor_approved' => [ 'by' => 'editor@example.com' ],
'legal_approved' => [ 'by' => 'legal@example.com' ],
]
Bez result_key sa údaje zodpovedajúcich signálov zlúčia s najvyššou úrovňou stavu v poradí, v akom boli kroky nastavené.
Párovanie a korelácia
Čakanie na signál môže ignorovať nesúvisiace udalosti párovaním obsahu údajov alebo koreláciou na základe zdieľaného kľúča.
$workflow_id = Queuety::workflow( 'review_gate' )
->wait_for_signal(
name: 'review_ready',
result_key: 'review',
match_payload: [ 'source' => 'editorial' ],
correlation_key: 'task_id',
)
->dispatch( [ 'task_id' => 'task-42' ] );
V tomto príklade sa čakanie skončí iba vtedy, keď:
- názov signálu je
review_ready - údaje obsahujú
source: editorial - hodnota
task_idv údajoch sa zhoduje s$state['task_id']
Hodí sa to, keď viacero externých systémov alebo agentov zverejňuje udalosti s rovnakými názvami, no iba jedny údaje patria k aktuálnemu behu pracovného postupu.
Pomocné funkcie na schválenie a vstup od človeka
wait_for_approval() a wait_for_input() sú praktické obaly okolo čakania na signál. Fungujú ako wait_for_signal(), ale predvolene ukladajú výsledok pod vlastným menným priestorom.
$workflow_id = Queuety::workflow( 'blog_review' )
->then( GenerateDraftHandler::class )
->wait_for_approval()
->wait_for_input()
->then( HandleDecisionHandler::class )
->dispatch();
Po signále approval obsahuje $state['approval'] údaje o schválení. Po signále input obsahuje $state['input'] údaje vstupu.
Ak chcete, aby jeden krok pokračoval po schválení aj zamietnutí, použite wait_for_decision():
$workflow_id = Queuety::workflow( 'legal_review' )
->then( DraftContractHandler::class )
->wait_for_decision( result_key: 'review' )
->then( HandleReviewDecisionHandler::class )
->dispatch();
Po prijatí signálu obsahuje $state['review']:
[
'outcome' => 'approved', // or 'rejected'
'signal' => 'approved', // or 'rejected'
'data' => [ 'reviewer' => 'ops@example.com' ],
]
Odoslanie signálu
Odošlite signál pracovnému postupu pomocou Queuety::signal():
Queuety::signal( $workflow_id, 'approved' );
Keď sa signál zhoduje so signálom, na ktorý pracovný postup čaká, pracovný postup pokračuje ďalším krokom.
Pri procesoch s účasťou človeka ponúka fasáda aj sémantické pomocné funkcie:
Queuety::approve_workflow( $workflow_id, [ 'reviewer' => 'editor@example.com' ] );
Queuety::reject_workflow( $workflow_id, [ 'reason' => 'needs citations' ] );
Queuety::submit_workflow_input( $workflow_id, [ 'notes' => 'Ship after copy edit' ] );
Údaje signálu
So signálom môžete odovzdať pole údajov. Údaje sa zlúčia so stavom pracovného postupu, takže budú k dispozícii v nasledujúcich krokoch:
Queuety::signal( $workflow_id, 'approved', [
'approved_by' => 'admin@example.com',
'approved_at' => time(),
] );
V nasledujúcom kroku:
class PublishContentHandler implements Step {
public function handle( array $state ): array {
// $state['approved_by'] is 'admin@example.com'
// $state['approved_at'] is the timestamp
// $state['post_id'] is 99
wp_update_post( [
'ID' => $state['post_id'],
'post_status' => 'publish',
] );
return [ 'published' => true ];
}
public function config(): array {
return [];
}
}
Kľúče začínajúce znakom _ (podčiarkovník) sú vyhradené na interné použitie a nezlučujú sa so stavom.
Vopred prijaté signály
Signály možno odoslať ešte predtým, ako pracovný postup dosiahne krok čakania. Po prijatí sa signál zaznamená v tabuľke queuety_signals bez ohľadu na aktuálny stav pracovného postupu. Keď pracovný postup neskôr dosiahne krok wait_for_signal, skontroluje, či už boli prijaté nejaké signály, a ak áno, okamžite pokračuje.
To znamená, že na poradí nezáleží:
// Dispatch workflow
$workflow_id = Queuety::workflow( 'order_fulfillment' )
->then( PrepareOrderHandler::class )
->wait_for_signal( 'payment_confirmed' )
->then( ShipOrderHandler::class )
->dispatch( [ 'order_id' => 123 ] );
// Signal arrives before the workflow reaches the wait step
Queuety::signal( $workflow_id, 'payment_confirmed', [ 'transaction_id' => 'txn_abc' ] );
// When the workflow finishes PrepareOrderHandler and reaches the wait step,
// it sees the pre-existing signal and continues immediately.
Stav pracovného postupu počas čakania na signál
Počas čakania na signál má pracovný postup stav WorkflowStatus::WaitingForSignal (waiting_for_signal):
$state = Queuety::workflow_status( $workflow_id );
echo $state->status->value; // 'waiting_for_signal'
echo $state->wait_type; // 'signal'
echo $state->wait_mode; // 'all' or 'any'
print_r( $state->waiting_for ); // ['approved']
print_r( $state->wait_details ); // matched/remaining, correlation info, result key, ...
Prípad použitia: schválenie človekom
Vytvorte pracovný postup schvaľovania, v ktorom musí kontrolór pred zverejnením obsahu udeliť súhlas:
$workflow_id = Queuety::workflow( 'blog_review' )
->then( GenerateDraftHandler::class )
->then( NotifyReviewerHandler::class )
->wait_for_decision( result_key: 'review' )
->then( HandleDecisionHandler::class )
->dispatch( [ 'topic' => 'PHP middleware patterns' ] );
NotifyReviewerHandler odošle e-mail alebo správu Slack s odkazmi na schválenie alebo zamietnutie. Tieto odkazy zavolajú váš kontrolér, ktorý odošle signál:
// In your approval controller
Queuety::approve_workflow(
$workflow_id,
[
'reviewer' => $current_user->user_email,
'reviewed_at' => time(),
],
'approved'
);
Krok HandleDecisionHandler načíta $state['review']['outcome'] a koncept buď zverejní, alebo archivuje.
Prípad použitia: externé spätné volanie API
Počkajte na webhook z externej služby:
$workflow_id = Queuety::workflow( 'generate_video' )
->then( SubmitToRenderServiceHandler::class )
->wait_for_signal( 'render_complete' )
->then( DownloadVideoHandler::class )
->then( NotifyUserHandler::class )
->dispatch( [ 'template_id' => 'promo_v2', 'user_id' => 42 ] );
Keď externá služba odošle požiadavku na váš koncový bod webhooku:
// In your webhook handler
$payload = json_decode( file_get_contents( 'php://input' ), true );
$workflow_id = (int) $payload['metadata']['workflow_id'];
Queuety::signal( $workflow_id, 'render_complete', [
'video_url' => $payload['output_url'],
'duration' => $payload['duration_seconds'],
] );
Viacero kontrolných bodov pre signály v jednom pracovnom postupe
Pracovný postup môže čakať na signály na viacerých miestach:
Queuety::workflow( 'multi_approval' )
->then( CreateProposalHandler::class )
->wait_for_signal( 'manager_approval' )
->then( EscalateToDirectorHandler::class )
->wait_for_signal( 'director_approval' )
->then( ExecuteProposalHandler::class )
->dispatch( [ 'proposal_id' => 7 ] );
Každý krok čakania na signál je nezávislý. V jednom pracovnom postupe môžete kombinovať wait_for_signal(), wait_for_signals(), wait_for_approval(), wait_for_input() a wait_for_decision().