
# Tekrarlar

Queuety iş akışları sıralı adım zincirleridir. Mantığı elle yazmak yerine daha önce adlandırılmış bir adıma dönmek için bir tekrar denetimi adımı kullanın: `_next_step`.

İş akışına uygun biçimi seçin:

- koşul basitse herkese açık bir `state_key`
- tekrar daha zengin bir mantık gerektiriyorsa bir `condition_class`
- tekrarın kendisi için kesin bir durma noktası gerekiyorsa `max_iterations`

Her iki yöntem de daha önce adlandırılmış bir adımı hedefler; böylece tekrar serileştirilebilir, yeniden oynatılabilir ve diğer tüm adımlarla aynı iş akışı çalışma zamanı tarafından denetlenir.

Tekrar koşulu, önceki adım tamamlandıktan sonra kalıcı hâle getirilmiş herkese açık iş akışı durumundan değerlendirilir; böylece her yineleme, çalışan yeniden başlatmalarında da kalıcı olur.

## `repeat_until()` ve durum anahtarı

```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`, karar yükünü basit bir herkese açık anahtara dönüştürebilir:

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

`review_approved` hâlâ `true` değilse tekrar adımı `draft` adımına geri döner. `true` olduğunda iş akışı `PublishBriefStep` adımına geçer.

Sinyaller tüketilmez, saklanır. `wait_for_decision()` adımından ikinci geçişte önceki `rejected` sinyali hâlâ eşleşir ve bekleme hemen sona erer; bu nedenle `max_transitions()` durdurana kadar döngü çalışmaya devam eder. Her tur için ayrı bir anahtar kullanın: `DraftBriefStep` artan bir `review_round` döndürsün, `correlation_key: 'review_round'` değerini `wait_for_decision()` öğesine iletin ve inceleyenin sinyal yükünde aynı `review_round` değerini göndermesini sağlayın. Böylece beklemeyi yalnızca `review_round` değeri mevcut durum değeriyle eşleşen sinyal sona erdirir.

## `repeat_until()` ve koşul sınıfı

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

Koşul sınıfları herkese açık iş akışı durumunu alır; böylece koşul, kapatmalara bağlı kalmadan serileştirilebilir ve incelenebilir.

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

Bu düzen, bir adım `should_poll_again`, `has_more_pages` veya `needs_revision` gibi basit bir boole değeri yazdığında kullanışlıdır.

## Tekrarlar neden `_next_step` öğesinden ayrıdır

Normal bir adımdan `_next_step` döndürerek dallanmayı yine elle yapabilirsiniz. Tekrar yardımcıları, şu daha sınırlı durum için vardır:

- hedef daha önceki bir adımdır
- koşul herkese açık iş akışı durumundan gelir
- tekrar mantığının iş akışı tanımında görünür kalmasını istersiniz

Bu sayede tekrarları dışa aktarımlarda, olay günlüklerinde ve belgelerde incelemek, geri dönüş bağlantısını gelişigüzel adım kodunun içine gömmekten daha kolaydır.

## Tekrarları sınırlama

Belirli bir tekrar için yerel bir kesin durma noktası gerektiğinde `max_iterations` kullanın:

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

İş akışının tamamında daha geniş kapsamlı bir acil durdurma gerektiğinde `max_transitions()` kullanın:

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

Bir tekrar `max_iterations` sınırını aşarsa veya iş akışı `max_transitions()` sınırını aşarsa Queuety, sonsuza kadar çalışmasına izin vermek yerine yürütmeyi başarısız kılar.

## İlgili belgeler

- [Koşullu Dallanma](https://queuety.inline0.dev/tr/docs/workflows/conditional)
- [Sinyaller](https://queuety.inline0.dev/tr/docs/workflows/signals)
- [Koruyucu Önlemler](https://queuety.inline0.dev/tr/docs/workflows/guardrails)
- [PHP API](https://queuety.inline0.dev/tr/docs/api)
