
# Kordused

Queuety töövood koosnevad järjestatud sammude ahelatest. Kasutage korduse juhtsam sammu, et naasta varasema nimega sammu juurde, selle asemel et kirjutada `_next_step` loogika käsitsi.

Valige töövoole sobiv vorm:

- avalik `state_key`, kui tingimus on lihtne
- `condition_class`, kui kordus vajab keerukamat loogikat
- `max_iterations`, kui kordusele endale on vaja ranget piirangut

Mõlemad meetodid sihivad varasemat nimega sammu, nii et kordus jääb serialiseeritavaks ja taasesitatavaks ning seda kaitseb sama töövoo käituskeskkond nagu kõiki teisi samme.

Korduse tingimust hinnatakse salvestatud avaliku töövoo oleku põhjal pärast eelneva sammu lõppu, nii et iga iteratsioon säilib ka töötaja taaskäivitamisel.

## `repeat_until()` olekuvõtmega

```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` saab otsustuse andmed koondada lihtsaks avalikuks võtmeks:

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

Kui `review_approved` ei ole endiselt `true`, hüppab kordussamm tagasi sammu `draft` juurde. Kui sellest saab `true`, jätkub töövoog sammust `PublishBriefStep`.

Signaalid salvestatakse, mitte ei tarbita. Teisel korral sammust `wait_for_decision()` läbi minnes sobib varasem `rejected` signaal endiselt ning ooteolek lõpeb kohe, nii et tsükkel korduks, kuni `max_transitions()` selle peatab. Andke igale voorule oma võti: laske `DraftBriefStep` tagastada kasvav `review_round`, edastage `correlation_key: 'review_round'` objektile `wait_for_decision()` ning laske ülevaatajal saata signaaliandmetes sama `review_round`. Ooteoleku lõpetab siis ainult signaal, mille `review_round` võrdub praeguse oleku väärtusega.

## `repeat_until()` tingimusklassiga

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

Tingimusklassid saavad avaliku töövoo oleku, nii et predikaat jääb serialiseeritavaks ja uuritavaks ega sõltu sulunditest.

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

See muster on kasulik, kui samm kirjutab lihtsa tõeväärtuse, näiteks `should_poll_again`, `has_more_pages` või `needs_revision`.

## Miks kordused on `_next_step`-ist eraldi

Saate endiselt käsitsi hargneda, tagastades tavalisest sammust `_next_step`. Korduse abilised on mõeldud kitsamaks kasutusjuhuks, kus:

- sihtmärk on varasem samm
- tingimus pärineb avalikust töövoo olekust
- soovite, et kordusloogika oleks töövoo määratluses nähtaval

Nii on kordusi lihtsam uurida eksporditud failides, sündmuslogides ja dokumentatsioonis kui siis, kui tagasihüpe on peidetud suvalise sammu koodi sisse.

## Korduste piiramine

Kasutage `max_iterations`-i, kui ühele kindlale kordusele on vaja kohalikku ranget piirangut:

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

Kasutage `max_transitions()`-i, kui kogu töövoog vajab laiemat hädaseiskamist:

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

Kui kordus ületab `max_iterations` või töövoog ületab `max_transitions()`, nurjab Queuety käivituse, selle asemel et lasta sellel lõputult kesta.

## Seotud dokumentatsioon

- [Tingimuslik hargnemine](https://queuety.inline0.dev/et/docs/workflows/conditional)
- [Signaalid](https://queuety.inline0.dev/et/docs/workflows/signals)
- [Kaitsepiirded](https://queuety.inline0.dev/et/docs/workflows/guardrails)
- [PHP API](https://queuety.inline0.dev/et/docs/api)
