Treci la conținut

Repetări

Queuety fluxurile de lucru sunt lanțuri ordonate de pași. Folosiți un pas de control al repetării pentru a reveni la un pas anterior cu nume, în loc să scrieți manual logica _next_step.

Alegeți forma potrivită pentru fluxul de lucru:

  • un state_key public când condiția este simplă
  • o condition_class când repetarea necesită o logică mai complexă
  • max_iterations când repetarea în sine are nevoie de o limită strictă

Ambele metode vizează un pas anterior cu nume, astfel încât repetarea rămâne serializabilă, reexecutabilă și protejată de același motor de fluxuri de lucru ca orice alt pas.

Condiția de repetare este evaluată pe baza stării publice persistate a fluxului de lucru după încheierea pasului precedent, astfel încât fiecare iterație rezistă la repornirea lucrătorului.

repeat_until() cu o cheie de stare

PHP
Queuety::workflow( 'approval_revision_loop' )
    ->max_transitions( 12 )
    ->then( DraftBriefStep::class, 'draft' )
    ->wait_for_decision( result_key: 'review' )
    ->then( NormalizeReviewOutcomeStep::class, 'review_outcome' )
    ->repeat_until( 'draft', 'review_approved', true, 'repeat_draft_until_approved' )
    ->then( PublishBriefStep::class )
    ->dispatch( [ 'brief_id' => 42 ] );

NormalizeReviewOutcomeStep poate aplatiza datele deciziei într-o cheie publică simplă:

PHP
class NormalizeReviewOutcomeStep implements \Queuety\Step {
    public function handle( array $state ): array {
        return [
            'review_approved' => 'approved' === ( $state['review']['outcome'] ?? null ),
        ];
    }

    public function config(): array {
        return [];
    }
}

Dacă review_approved încă nu este true, pasul de repetare revine la draft. Când devine true, fluxul de lucru trece la PublishBriefStep.

Semnalele sunt stocate, nu consumate. La a doua trecere prin wait_for_decision(), semnalul rejected anterior se potrivește în continuare, iar așteptarea se încheie imediat, astfel încât bucla s-ar repeta la nesfârșit până când max_transitions() o oprește. Dați fiecărei runde propria cheie: faceți ca DraftBriefStep să returneze un review_round incrementat, transmiteți correlation_key: 'review_round' către wait_for_decision() și solicitați evaluatorului să trimită aceeași review_round în datele utile ale semnalului. Așteptarea se încheie apoi numai dacă review_round semnalului este egală cu valoarea curentă a stării.

repeat_until() cu o clasă de condiție

PHP
use App\Workflows\ReviewApprovedCondition;

Queuety::workflow( 'approval_revision_loop' )
    ->then( DraftBriefStep::class, 'draft' )
    ->wait_for_decision( result_key: 'review' )
    ->repeat_until(
        target_step: 'draft',
        condition_class: ReviewApprovedCondition::class,
        max_iterations: 5,
        name: 'repeat_draft_until_approved',
    )
    ->then( PublishBriefStep::class )
    ->dispatch( [ 'brief_id' => 42 ] );
PHP
namespace App\Workflows;

use Queuety\Contracts\RepeatCondition;

final class ReviewApprovedCondition implements RepeatCondition {
    public function matches( array $state ): bool {
        return 'approved' === ( $state['review']['outcome'] ?? null );
    }
}

Clasele de condiție primesc starea publică a fluxului de lucru, astfel încât predicatul rămâne serializabil și inspectabil fără a depinde de închideri.

repeat_while()

PHP
Queuety::workflow( 'poll_remote_status' )
    ->max_transitions( 20 )
    ->then( PollRemoteStatusStep::class, 'poll' )
    ->delay( seconds: 30 )
    ->repeat_while( 'poll', 'should_poll_again', true, 'repeat_poll' )
    ->then( FinalizeImportStep::class )
    ->dispatch( [ 'import_id' => 99 ] );

Acest tipar este util când un pas scrie o valoare booleană simplă, cum ar fi should_poll_again, has_more_pages sau needs_revision.

De ce repetările sunt separate de _next_step

Puteți ramifica în continuare manual returnând _next_step dintr-un pas obișnuit. Funcțiile auxiliare de repetare sunt pentru cazul mai restrâns în care:

  • ținta este un pas anterior
  • condiția provine din starea publică a fluxului de lucru
  • doriți ca logica de repetare să rămână vizibilă chiar în definiția fluxului de lucru

Astfel, repetările sunt mai ușor de inspectat în exporturi, jurnalele de evenimente și documentație decât dacă ascundeți bucla de revenire în cod arbitrar al unui pas.

Protejarea repetărilor

Folosiți max_iterations când o anumită repetare are nevoie de o limită strictă locală:

PHP
Queuety::workflow( 'poll_remote_status' )
    ->then( PollRemoteStatusStep::class, 'poll' )
    ->repeat_while( 'poll', 'should_poll_again', true, max_iterations: 8 )
    ->dispatch();

Folosiți max_transitions() când întregul flux de lucru are nevoie de un mecanism general de oprire de urgență:

PHP
Queuety::workflow( 'safe_revision_loop' )
    ->max_transitions( 10 )
    ->then( DraftBriefStep::class, 'draft' )
    ->wait_for_decision( result_key: 'review' )
    ->then( NormalizeReviewOutcomeStep::class )
    ->repeat_until( 'draft', 'review_approved', true )
    ->dispatch();

Dacă o repetare depășește max_iterations sau fluxul de lucru depășește max_transitions(), Queuety oprește execuția cu eroare, în loc să o lase să se repete la nesfârșit.