Signali poteka dela
Poteki dela se lahko začasno ustavijo in počakajo na zunanji vnos s pomočjo signalov. Gradniški metodi wait_for_signal() in wait_for_signals() dodata korake, ki blokirajo potek dela, dokler vaša aplikacija, operater ali drug sistem prek Queuety::signal() ne pošlje pričakovanega signala.
Za poteke dela s človeškim posredovanjem Queuety vključuje tudi:
wait_for_approval()za odobritvene podatke z imenskim prostoromwait_for_input()za strukturiran človeški vnoswait_for_decision()za izrecne izide odobritve/zavrnitve
Za obsežnejši primer od začetka do konca, ki združuje izvajanja agentov s človeškimi potrditvami, glejte Orkestracija agentov.
Metoda ->wait_for_signal()
V potek dela dodajte korak čakanja na signal:
use Queuety\Queuety;
$workflow_id = Queuety::workflow( 'content_approval' )
->then( DraftContentHandler::class )
->wait_for_signal( 'approved' )
->then( PublishContentHandler::class )
->dispatch( [ 'post_id' => 99 ] );
Ko potek dela doseže korak wait_for_signal, se njegovo stanje nastavi na waiting_for_signal in se začasno ustavi. Med čakanjem se opravila ne izvajajo in viri se ne porabljajo.
Privzeto se podatkovni niz enega signala združi v stanje poteka dela na najvišji ravni. Če želite podatkovni niz umestiti pod imenski prostor, podajte result_key:
$workflow_id = Queuety::workflow( 'content_approval' )
->then( DraftContentHandler::class )
->wait_for_signal( 'approved', 'approval' )
->then( PublishContentHandler::class )
->dispatch( [ 'post_id' => 99 ] );
Ko prispe signal, $state['approval'] vsebuje polje podatkovnih nizov signalov.
Čakanje na več signalov
Uporabite wait_for_signals(), kadar naj se potek dela odblokira ob enem od več možnih signalov ali kadar mora pred nadaljevanjem zbrati vse zahtevane signale.
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čaka, dokler niso zabeleženi vsi nastavljeni signali.WaitMode::Anynadaljuje takoj, ko prispe prvi nastavljeni signal.
Z result_key čakanje na več signalov shrani asociativno polje, indeksirano z imenom signala:
[
'editor_approved' => [ 'by' => 'editor@example.com' ],
'legal_approved' => [ 'by' => 'legal@example.com' ],
]
Brez result_key se ustrezni podatkovni nizi signalov združijo v stanje na najvišji ravni v vrstnem redu, v katerem so bili koraki nastavljeni.
Ujemanje in povezovanje
Čakanja na signal lahko prezrejo nepovezane dogodke z ujemanjem vsebine podatkovnega niza ali povezovanjem prek skupnega ključ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 tem primeru se čakanje nadaljuje le, ko:
- je ime signala
review_ready - podatkovni niz vsebuje
source: editorial - se vrednost
task_idv podatkovnem nizu ujema z$state['task_id']
To je uporabno, kadar več zunanjih sistemov ali agentov objavlja dogodke z istimi imeni, vendar le en podatkovni niz pripada trenutnemu izvajanju poteka dela.
Pomožne funkcije za človeško odobritev in vnos
wait_for_approval() in wait_for_input() sta priročna ovoja okoli čakanja na signal. Delujeta kot wait_for_signal(), vendar privzeto uporabljata rezultatni ključ z imenskim prostorom.
$workflow_id = Queuety::workflow( 'blog_review' )
->then( GenerateDraftHandler::class )
->wait_for_approval()
->wait_for_input()
->then( HandleDecisionHandler::class )
->dispatch();
Po signalu approval vsebuje $state['approval'] podatke o odobritvi. Po signalu input vsebuje $state['input'] podatke o vnosu.
Uporabite wait_for_decision(), kadar želite, da en korak nadaljuje ob odobritvi ali zavrnitvi:
$workflow_id = Queuety::workflow( 'legal_review' )
->then( DraftContractHandler::class )
->wait_for_decision( result_key: 'review' )
->then( HandleReviewDecisionHandler::class )
->dispatch();
Ko prispe signal, $state['review'] vsebuje:
[
'outcome' => 'approved', // or 'rejected'
'signal' => 'approved', // or 'rejected'
'data' => [ 'reviewer' => 'ops@example.com' ],
]
Pošiljanje signala
Pošljite signal poteku dela z uporabo Queuety::signal():
Queuety::signal( $workflow_id, 'approved' );
Ko se signal ujema s tistim, na katerega čaka potek dela, se ta nadaljuje in preide na naslednji korak.
Za poteke dela s človeškim posredovanjem fasada ponuja tudi semantične pomožne funkcije:
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' ] );
Podatki signala
Signalu lahko posredujete polje s podatki. Ti se združijo s stanjem poteka dela in so na voljo naslednjim korakom:
Queuety::signal( $workflow_id, 'approved', [
'approved_by' => 'admin@example.com',
'approved_at' => time(),
] );
V naslednjem koraku:
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 [];
}
}
Ključi, ki se začnejo z _ (podčrtajem), so rezervirani za interno uporabo in se ne združijo s stanjem.
Že obstoječi signali
Signale je mogoče poslati, še preden potek dela doseže korak čakanja. Ko prispe signal, se zabeleži v tabeli queuety_signals, ne glede na trenutno stanje poteka dela. Ko ta pozneje doseže korak wait_for_signal, preveri, ali obstajajo že poslani signali, in takoj nadaljuje, če jih najde.
To pomeni, da vrstni red ni pomemben:
// 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.
Stanje poteka dela med čakanjem na signal
Med čakanjem na signal je stanje poteka dela 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, ...
Primer uporabe: človeška odobritev
Sestavite potek dela za odobritev, v katerem mora človeški pregledovalec odobriti vsebino, preden postane javno dostopna:
$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 pošlje e-pošto ali sporočilo Slack s povezavama za odobritev ali zavrnitev. Povezavi pokličeta vaš krmilnik, ki pošlje signal:
// In your approval controller
Queuety::approve_workflow(
$workflow_id,
[
'reviewer' => $current_user->user_email,
'reviewed_at' => time(),
],
'approved'
);
Korak HandleDecisionHandler prebere $state['review']['outcome'] ter osnutek objavi ali arhivira.
Primer uporabe: povratni klic zunanjega API
Počakajte na webhook zunanje storitve:
$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 ] );
Ko zunanja storitev pošlje zahtevo na vašo končno točko webhooka:
// 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'],
] );
Več vrat za signale v enem poteku dela
Potek dela lahko čaka na signale na več mestih:
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 ] );
Vsak korak čakanja na signal je neodvisen. V istem poteku dela lahko kombinirate wait_for_signal(), wait_for_signals(), wait_for_approval(), wait_for_input() in wait_for_decision().