Opakovania
Queuety sú usporiadané reťazce krokov. Pomocou riadiaceho kroku opakovania sa môžete vrátiť k predchádzajúcemu pomenovanému kroku namiesto ručného písania logiky _next_step.
Vyberte formu, ktorá zodpovedá pracovnému postupu:
- verejné
state_key, ak je podmienka jednoduchá condition_class, ak opakovanie vyžaduje zložitejšiu logikumax_iterations, ak opakovanie potrebuje pevný limit
Obe metódy smerujú na predchádzajúci pomenovaný krok, takže opakovanie zostáva serializovateľné, prehrateľné a podlieha rovnakému modulu runtime pracovného postupu ako všetky ostatné kroky.
Podmienka opakovania sa vyhodnotí z uloženého verejného stavu pracovného postupu po dokončení predchádzajúceho kroku, takže každé opakovanie zostáva trvalé aj po reštarte pracovníka.
repeat_until() s kľúčom stavu
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 môže zjednodušiť údaje o rozhodnutí na jednoduchý verejný kľúč:
class NormalizeReviewOutcomeStep implements \Queuety\Step {
public function handle( array $state ): array {
return [
'review_approved' => 'approved' === ( $state['review']['outcome'] ?? null ),
];
}
public function config(): array {
return [];
}
}
Ak review_approved stále nie je true, krok opakovania sa vráti na draft. Keď sa zmení na true, pracovný postup pokračuje krokom PublishBriefStep.
Signály sa ukladajú, nespotrebúvajú sa. Pri druhom prechode cez wait_for_decision() sa stále zhoduje predchádzajúci signál rejected a čakanie sa okamžite skončí, takže slučka by sa opakovala, kým ju nezastaví max_transitions(). Každému kolu priraďte vlastný kľúč: nech DraftBriefStep vráti rastúce review_round, odovzdajte correlation_key: 'review_round' funkcii wait_for_decision() a nech kontrolór odošle rovnaké review_round v údajoch signálu. Čakanie sa potom ukončí iba vtedy, keď sa review_round signálu rovná aktuálnej hodnote stavu.
repeat_until() s triedou podmienky
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 ] );
namespace App\Workflows;
use Queuety\Contracts\RepeatCondition;
final class ReviewApprovedCondition implements RepeatCondition {
public function matches( array $state ): bool {
return 'approved' === ( $state['review']['outcome'] ?? null );
}
}
Triedy podmienok dostávajú verejný stav pracovného postupu, takže predikát zostáva serializovateľný a kontrolovateľný bez závislosti od uzáverov.
repeat_while()
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 ] );
Tento vzor je užitočný, keď krok zapíše jednoduchú booleovskú hodnotu, napríklad should_poll_again, has_more_pages alebo needs_revision.
Prečo sú opakovania oddelené od _next_step
Vetviť môžete aj ručne tak, že z bežného kroku vrátite _next_step. Pomocné funkcie na opakovanie slúžia na užší prípad, keď:
- cieľom je predchádzajúci krok
- podmienka vychádza z verejného stavu pracovného postupu
- chcete, aby logika opakovania zostala viditeľná priamo v definícii pracovného postupu
Vďaka tomu sa opakovania ľahšie kontrolujú v exportoch, protokoloch udalostí a dokumentácii než pri skrytí spätného prepojenia v ľubovoľnom kóde kroku.
Ochrana pred nekonečným opakovaním
Ak jedno konkrétne opakovanie potrebuje miestny pevný limit, použite max_iterations:
Queuety::workflow( 'poll_remote_status' )
->then( PollRemoteStatusStep::class, 'poll' )
->repeat_while( 'poll', 'should_poll_again', true, max_iterations: 8 )
->dispatch();
Ak celý pracovný postup potrebuje širšiu poistku, použite max_transitions():
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();
Ak opakovanie prekročí max_iterations alebo pracovný postup prekročí max_transitions(), Queuety zlyhaním ukončí beh, aby sa nikdy neopakoval donekonečna.