Přejít k obsahu

Opakování

Queuety workflow jsou uspořádané řetězce kroků. Pomocí řídicího kroku opakování se vrátíte k dřívějšímu pojmenovanému kroku, místo abyste ručně psali logiku _next_step.

Zvolte podobu, která odpovídá vašemu workflow:

  • veřejné state_key, pokud je podmínka jednoduchá
  • condition_class, pokud opakování vyžaduje složitější logiku
  • max_iterations, pokud opakování potřebuje pevný limit

Obě metody cílí na dřívější pojmenovaný krok, takže opakování zůstává serializovatelné, přehratelné a podléhá stejnému běhovému prostředí workflow jako každý jiný krok.

Podmínka opakování se vyhodnocuje z uloženého veřejného stavu workflow po dokončení předchozího kroku, takže každá iterace zůstává trvalá i po restartu workeru.

repeat_until() se stavovým klíčem

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 může převést data pro rozhodnutí na jednoduchý veřejný klíč:

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

Pokud review_approved stále není true, krok opakování se vrátí na draft. Jakmile se změní na true, workflow přejde na PublishBriefStep.

Signály se ukládají, nespotřebovávají. Při druhém průchodu krokem wait_for_decision() se dřívější signál rejected stále shoduje a čekání se ihned vyřídí, takže by se smyčka opakovala, dokud by ji nezastavilo max_transitions(). Každému kolu přiřaďte vlastní klíč: nechte DraftBriefStep vrátit inkrementující se review_round, předejte correlation_key: 'review_round' do wait_for_decision() a nechte kontrolora poslat ve výsledném signálu stejné review_round. Čekání pak vyřídí pouze signál, jehož review_round odpovídá aktuální hodnotě stavu.

repeat_until() s třídou podmínky

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 );
    }
}

Třídy podmínek přijímají veřejný stav workflow, takže predikát zůstává serializovatelný a kontrolovatelný bez závislosti na uzávěrech.

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

Tento vzor se hodí, když krok zapisuje jednoduchou booleovskou hodnotu, například should_poll_again, has_more_pages nebo needs_revision.

Proč jsou opakování oddělená od _next_step

Větvení můžete stále řídit ručně tak, že z běžného kroku vrátíte _next_step. Pomocné funkce pro opakování jsou určeny pro užší případy, kdy:

  • cílem je dřívější krok
  • podmínka vychází z veřejného stavu workflow
  • chcete, aby logika opakování zůstala viditelná přímo v definici workflow

Díky tomu lze opakování snáze kontrolovat v exportech, protokolech událostí a dokumentaci, než když je zpětná vazba skrytá v libovolném kódu kroku.

Omezení opakování

Použijte max_iterations, když potřebujete pevný limit pro konkrétní opakování:

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

Použijte max_transitions(), když celé workflow potřebuje širší pojistku:

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();

Pokud opakování překročí max_iterations nebo workflow překročí max_transitions(), Queuety běh ukončí chybou, místo aby se nechalo nekonečně opakovat.