반복
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가 무한 반복을 허용하지 않고 실행을 실패 처리합니다.