Upprepningar
Queuety arbetsflöden består av ordnade stegkedjor. Använd ett upprepningssteg för att återgå till ett tidigare namngivet steg i stället för att skriva _next_step-logik för hand.
Välj den form som passar arbetsflödet:
- en offentlig
state_keynär villkoret är enkelt - en
condition_classnär upprepningen kräver mer avancerad logik max_iterationsnär själva upprepningen behöver en tydlig gräns
Båda metoderna riktar sig mot ett tidigare namngivet steg, så upprepningen förblir serialiserbar, återspelningsbar och skyddad av samma arbetsflödeskörmiljö som alla andra steg.
Upprepningsvillkoret utvärderas från det beständiga offentliga arbetsflödestillståndet när det föregående steget har slutförts, så varje iteration förblir beständig även efter omstarter av arbetare.
repeat_until() med en tillståndsnyckel
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 kan platta till beslutsnyttolasten till en enkel offentlig nyckel:
class NormalizeReviewOutcomeStep implements \Queuety\Step {
public function handle( array $state ): array {
return [
'review_approved' => 'approved' === ( $state['review']['outcome'] ?? null ),
];
}
public function config(): array {
return [];
}
}
Om review_approved fortfarande inte är true hoppar upprepningssteget tillbaka till draft. När det blir true fortsätter arbetsflödet till PublishBriefStep.
Signaler lagras, de förbrukas inte. Vid den andra genomgången av wait_for_decision() matchar den tidigare rejected-signalen fortfarande och väntan avslutas omedelbart, så loopen skulle snurra tills max_transitions() stoppar den. Ge varje omgång en egen nyckel: låt DraftBriefStep returnera ett inkrementerande review_round, skicka correlation_key: 'review_round' till wait_for_decision() och låt granskaren skicka samma review_round i signalens nyttolast. Då avslutas väntan bara när en signal vars review_round motsvarar det aktuella tillståndsvärdet tas emot.
repeat_until() med en villkorsklass
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 );
}
}
Villkorsklasser får det offentliga arbetsflödestillståndet, så predikatet förblir serialiserbart och granskningsbart utan att vara beroende av closures.
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 ] );
Mönstret är användbart när ett steg skriver ett enkelt booleskt värde som should_poll_again, has_more_pages eller needs_revision.
Varför upprepningar är separata från _next_step
Du kan fortfarande skapa grenar manuellt genom att returnera _next_step från ett vanligt steg. Hjälpfunktionerna för upprepning finns för det mer avgränsade fallet när:
- målet är ett tidigare steg
- villkoret kommer från det offentliga arbetsflödestillståndet
- du vill att upprepningslogiken ska vara synlig i själva arbetsflödesdefinitionen
Det gör upprepningar enklare att granska i exporter, händelseloggar och dokumentation än om återkopplingen göms i godtycklig stegspecifik kod.
Begränsa upprepningar
Använd max_iterations när en viss upprepning behöver en lokal gräns:
Queuety::workflow( 'poll_remote_status' )
->then( PollRemoteStatusStep::class, 'poll' )
->repeat_while( 'poll', 'should_poll_again', true, max_iterations: 8 )
->dispatch();
Använd max_transitions() när hela arbetsflödet behöver en bredare nödbrytare:
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();
Om en upprepning överskrider max_iterations, eller arbetsflödet överskrider max_transitions(), avbryter Queuety körningen i stället för att låta den snurra för alltid.