Pereiti prie turinio

Darbo sekos signalai

Darbo sekos gali būti pristabdytos ir laukti išorinių duomenų naudodamos signalus. Kūrimo metodai wait_for_signal() ir wait_for_signals() įterpia veiksmus, kurie sustabdo darbo seką, kol jūsų programa, operatorius arba kita sistema per Queuety::signal() atsiunčia laukiamą signalą.

Žmogaus įsitraukimo reikalaujančioms darbo eigoms Queuety taip pat siūlo:

  • wait_for_approval() vardų srityje apibrėžtiems patvirtinimo duomenims
  • wait_for_input() struktūrizuotiems žmogaus pateikiamiems duomenims
  • wait_for_decision() aiškiems patvirtinimo arba atmetimo rezultatams

Išsamesnį pavyzdį nuo pradžios iki pabaigos, kuriame agentų vykdymas derinamas su žmogaus atliekamais patikrinimais, rasite puslapyje Agentų orkestravimas.

Metodas ->wait_for_signal()

Pridėkite signalų laukimo veiksmą prie darbo sekos:

PHP
use Queuety\Queuety;

$workflow_id = Queuety::workflow( 'content_approval' )
    ->then( DraftContentHandler::class )
    ->wait_for_signal( 'approved' )
    ->then( PublishContentHandler::class )
    ->dispatch( [ 'post_id' => 99 ] );

Kai darbo seka pasiekia veiksmą wait_for_signal, jos būsena nustatoma į waiting_for_signal ir ji pristabdoma. Laukiant nevykdomos jokios užduotys ir nenaudojami jokie ištekliai.

Pagal numatytąją nuostatą vieno signalo duomenys sujungiami su aukščiausio lygmens darbo sekos būsena. Jei norite juos įdėti į vardų sritį, perduokite result_key:

PHP
$workflow_id = Queuety::workflow( 'content_approval' )
    ->then( DraftContentHandler::class )
    ->wait_for_signal( 'approved', 'approval' )
    ->then( PublishContentHandler::class )
    ->dispatch( [ 'post_id' => 99 ] );

Gavus signalą, $state['approval'] pateikiamas signalo duomenų masyvas.

Kelių signalų laukimas

Naudokite wait_for_signals(), kai darbo seka turėtų tęstis gavusi vieną iš kelių galimų signalų arba kai prieš tęsdama turi surinkti visus reikalingus signalus.

PHP
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 laukia, kol bus užregistruoti visi sukonfigūruoti signalai.
  • WaitMode::Any tęsia vykdymą, kai tik gaunamas pirmasis sukonfigūruotas signalas.

Naudojant result_key, kelių signalų laukimo rezultatas saugomas susietajame masyve, kurio raktai yra signalų pavadinimai:

PHP
[
    'editor_approved' => [ 'by' => 'editor@example.com' ],
    'legal_approved' => [ 'by' => 'legal@example.com' ],
]

Nenaudojant result_key, atitinkančių signalų duomenys sujungiami su aukščiausio lygmens būsena tokia tvarka, kokia buvo sukonfigūruotas veiksmas.

Atitikmenų paieška ir koreliacija

Signalų laukimo veiksmai gali ignoruoti nesusijusius įvykius, tikrindami duomenų turinį arba susiedami juos pagal bendrą raktą.

PHP
$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' ] );

Šiame pavyzdyje laukimas baigiasi tik tada, kai:

  • signalo pavadinimas yra review_ready
  • duomenyse yra source: editorial
  • duomenų task_id atitinka $state['task_id']

Tai naudinga, kai kelios išorinės sistemos ar agentai skelbia įvykius tais pačiais pavadinimais, tačiau tik vieno iš jų duomenys priklauso dabartiniam darbo sekos vykdymui.

Pagalbinės funkcijos žmogaus patvirtinimui ir duomenų įvedimui

wait_for_approval() ir wait_for_input() yra patogios signalų laukimo apvalkalinės funkcijos. Jos veikia kaip wait_for_signal(), bet pagal numatytąją nuostatą grąžina rezultatą į vardų sritį.

PHP
$workflow_id = Queuety::workflow( 'blog_review' )
    ->then( GenerateDraftHandler::class )
    ->wait_for_approval()
    ->wait_for_input()
    ->then( HandleDecisionHandler::class )
    ->dispatch();

Gavus signalą approval, $state['approval'] pateikiami patvirtinimo duomenys. Gavus signalą input, $state['input'] pateikiami įvesties duomenys.

Naudokite wait_for_decision(), kai norite, kad vienas veiksmas būtų tęsiamas gavus patvirtinimą arba atmetimą:

PHP
$workflow_id = Queuety::workflow( 'legal_review' )
    ->then( DraftContractHandler::class )
    ->wait_for_decision( result_key: 'review' )
    ->then( HandleReviewDecisionHandler::class )
    ->dispatch();

Gavus signalą, $state['review'] pateikiama:

PHP
[
    'outcome' => 'approved', // or 'rejected'
    'signal'  => 'approved', // or 'rejected'
    'data'    => [ 'reviewer' => 'ops@example.com' ],
]

Signalo siuntimas

Siųskite signalą darbo sekai naudodami Queuety::signal():

PHP
Queuety::signal( $workflow_id, 'approved' );

Kai signalas atitinka tą, kurio laukia darbo seka, ji tęsiama nuo kito veiksmo.

Žmogaus dalyvavimo darbo sekose fasadas taip pat pateikia semantinių pagalbinių funkcijų:

PHP
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' ] );

Signalo duomenys

Kartu su signalu galite perduoti duomenų masyvą. Duomenys sujungiami su darbo sekos būsena, todėl vėlesni veiksmai gali juos pasiekti:

PHP
Queuety::signal( $workflow_id, 'approved', [
    'approved_by' => 'admin@example.com',
    'approved_at' => time(),
] );

Kitame veiksme:

PHP
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 [];
    }
}

Raktai, prasidedantys _ (apatiniu pabraukimo ženklu), skirti vidiniam naudojimui ir su būsena nejungiami.

Iš anksto gauti signalai

Signalus galima siųsti anksčiau, nei darbo seka pasiekia laukimo veiksmą. Gavus signalą, jis įrašomas į queuety_signals lentelę, nepaisant dabartinės darbo sekos būsenos. Vėliau pasiekusi veiksmą wait_for_signal, darbo seka patikrina, ar yra anksčiau gautų signalų, ir, radusi atitinkamą, iškart tęsia vykdymą.

Tai reiškia, kad tvarka nesvarbi:

PHP
// 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.

Darbo sekos būsena laukiant signalo

Laukiant signalo, darbo sekos būsena yra WorkflowStatus::WaitingForSignal (waiting_for_signal):

PHP
$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, ...

Naudojimo atvejis: žmogaus patvirtinimas

Sukurkite patvirtinimo darbo seką, kurioje žmogus turi patvirtinti turinį prieš jį paskelbiant:

PHP
$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 siunčia el. laišką arba Slack žinutę su patvirtinimo ir atmetimo nuorodomis. Šios nuorodos iškviečia jūsų valdiklį, kuris siunčia signalą:

PHP
// In your approval controller
Queuety::approve_workflow(
    $workflow_id,
    [
        'reviewer'    => $current_user->user_email,
        'reviewed_at' => time(),
    ],
    'approved'
);

Veiksmas HandleDecisionHandler nuskaito $state['review']['outcome'] ir paskelbia arba archyvuoja juodraštį.

Naudojimo atvejis: išorinės API atgalinis iškvietimas

Laukite išorinės paslaugos siunčiamo žiniatinklio kablio užklausos:

PHP
$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 ] );

Kai išorinė paslauga siunčia užklausą jūsų žiniatinklio kablio adresu:

PHP
// 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'],
] );

Keli signalų laukimo veiksmai vienoje darbo sekoje

Darbo seka gali laukti signalų keliose vietose:

PHP
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 ] );

Kiekvienas signalų laukimo veiksmas yra nepriklausomas. Toje pačioje darbo sekoje galite derinti wait_for_signal(), wait_for_signals(), wait_for_approval(), wait_for_input() ir wait_for_decision().