Повтори
Queuety робочих процесів — це впорядковані ланцюжки кроків. Використовуйте керувальний крок повторення, щоб повернутися до попереднього іменованого кроку, замість того щоб вручну писати логіку _next_step.
Виберіть форму, яка відповідає робочому процесу:
- публічний
state_key, якщо умова проста condition_class, якщо для повтору потрібна складніша логікаmax_iterations, якщо для самого повтору потрібна жорстка межа
Обидва методи спрямовують виконання до попереднього іменованого кроку, тому повтор залишається серіалізованим і відтворюваним та обмежується тим самим середовищем виконання робочого процесу, що й усі інші кроки.
Умова повтору перевіряється за збереженим публічним станом робочого процесу після завершення попереднього кроку, тому кожна ітерація зберігається навіть після перезапуску виконавця.
repeat_until() із ключем стану
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 може звести дані для рішення до простого публічного ключа:
class NormalizeReviewOutcomeStep implements \Queuety\Step {
public function handle( array $state ): array {
return [
'review_approved' => 'approved' === ( $state['review']['outcome'] ?? null ),
];
}
public function config(): array {
return [];
}
}
Якщо review_approved усе ще не true, крок повторення повертається до draft. Щойно значення стає true, робочий процес переходить до PublishBriefStep.
Сигнали зберігаються, а не споживаються. Під час другого проходу через wait_for_decision() попередній сигнал rejected усе ще збігається, і очікування завершується негайно, тож цикл виконувався б безперервно, якби max_transitions() його не зупинив. Використовуйте для кожного циклу окремий ключ: нехай DraftBriefStep повертає лічильник review_round, передавайте correlation_key: 'review_round' у wait_for_decision(), а перевіряльник надсилає таке саме review_round у даних сигналу. Тоді очікування завершить лише сигнал, у якого review_round дорівнює поточному значенню стану.
repeat_until() із класом умови
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 );
}
}
Класи умов отримують публічний стан робочого процесу, тому предикат залишається серіалізованим і придатним для перевірки без залежності від замикань.
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 ] );
Цей шаблон корисний, коли крок записує просте логічне значення, наприклад should_poll_again, has_more_pages або needs_revision.
Чому повтори відокремлені від _next_step
Ви й далі можете виконувати розгалуження вручну, повертаючи _next_step зі звичайного кроку. Допоміжні засоби повторення призначені для вужчого випадку, коли:
- ціль — попередній крок
- умова визначається з публічного стану робочого процесу
- ви хочете, щоб логіка повторення залишалася видимою безпосередньо у визначенні робочого процесу
Завдяки цьому повтори легше перевіряти в експортах, журналах подій і документації, ніж логіку повернення, приховану в довільному коді кроку.
Обмеження повторів
Використовуйте max_iterations, коли потрібно встановити локальну жорстку межу для конкретного повтору:
Queuety::workflow( 'poll_remote_status' )
->then( PollRemoteStatusStep::class, 'poll' )
->repeat_while( 'poll', 'should_poll_again', true, max_iterations: 8 )
->dispatch();
Використовуйте 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();
Якщо повтор перевищує max_iterations або робочий процес перевищує max_transitions(), Queuety завершує запуск із помилкою, не дозволяючи йому тривати нескінченно.