Treci la conținut

For-Each dinamic

Folosiți ->for_each() când numărul de ramuri din fluxul de lucru nu este cunoscut în momentul construirii. Queuety citește un tablou din starea fluxului de lucru, expediază o sarcină de ramură pentru fiecare element și avansează numai când este îndeplinită condiția de finalizare configurată.

Metoda ->for_each()

PHP
use Queuety\Contracts\ForEachHandler;
use Queuety\Contracts\ForEachReducer;
use Queuety\Enums\ForEachMode;
use Queuety\Queuety;

Queuety::workflow( 'index_site' )
    ->then( PlanPagesStep::class )
    ->for_each(
        items_key: 'pages',
        handler_class: IndexPageStep::class,
        result_key: 'page_results',
        mode: ForEachMode::Quorum,
        quorum: 2,
        reducer_class: IndexSummaryReducer::class,
        name: 'index_pages',
    )
    ->then( PublishIndexStep::class )
    ->dispatch( [ 'site_id' => 42 ] );

Pasul planificatorului scrie pages în starea fluxului de lucru. Pasul for-each citește tabloul și expediază o sarcină de ramură pentru fiecare element.

Gestionarele ramurilor

Gestionarele ramurilor for-each implementează Contracts\ForEachHandler:

PHP
use Queuety\Contracts\ForEachHandler;

final class IndexPageStep implements ForEachHandler {
    public function handle_item( array $state, mixed $item, int $index ): array {
        $page = is_array( $item ) ? $item : [ 'url' => (string) $item ];

        return [
            'url' => $page['url'],
            'title' => fetch_title( $page['url'] ),
            'index' => $index,
        ];
    }

    public function config(): array {
        return [
            'max_attempts' => 3,
            'backoff' => 'exponential',
        ];
    }
}

În config(), backoff primește un nume de strategie: exponential, linear sau fixed. O listă de întârzieri per încercare este în prezent eliminată și devine o serie de reîncercări imediate (#16); plasați întârzierile per încercare în backoff din definiția pasului.

$state conține întreaga stare a fluxului de lucru, $item este elementul for-each individual, iar $index este poziția sa indexată de la zero.

Moduri de finalizare

ForEachMode::All

Pasul se încheie numai după ce toate ramurile reușesc. Orice eșec permanent al unei ramuri provoacă eșecul pasului for-each.

ForEachMode::FirstSuccess

Pasul se încheie de îndată ce prima ramură reușește. Ramurile active rămase sunt îngropate ca fiind înlocuite.

ForEachMode::Quorum

Pasul se încheie când reușesc cel puțin quorum ramuri. Dacă ramurile rămase nu mai pot îndeplini cvorumul, fluxul de lucru eșuează.

Reducătoare

În mod implicit, Queuety stochează un agregat structurat în result_key:

  • mode
  • quorum
  • total
  • succeeded
  • failed
  • settled
  • winner
  • results
  • failures

Dacă doriți un rezumat personalizat, transmiteți o clasă de reducător care implementează Contracts\ForEachReducer. Agregatul este stocat în continuare în result_key, iar cheile returnate de reducător sunt îmbinate în starea fluxului de lucru alături de acesta:

PHP
use Queuety\Contracts\ForEachReducer;

final class IndexSummaryReducer implements ForEachReducer {
    public function reduce( array $state, array $for_each ): array {
        return [
            'indexed_count' => count( $for_each['results'] ),
            'winning_url' => $for_each['winner']['output']['url'] ?? null,
        ];
    }
}

Rezultatul reducătorului este îmbinat în starea fluxului de lucru la fel ca rezultatul oricărui alt pas. Reducătorul poate returna și _next_step pentru a ramifica fluxul după încheierea pasului for-each.

Comportamentul reîncercărilor

Ramurile for-each se reîncearcă independent, conform config() al gestionarului ramurii. Dacă pasul for-each eșuează și apelați retry_workflow(), Queuety extinde din nou pasul for-each și repune în coadă numai ramurile care lipsesc sau au eșuat. Rezultatele ramurilor reușite rămân în starea fluxului de lucru.

Alegerea între parallel() și for_each()

Folosiți parallel() când lista ramurilor este fixată în cod.

Folosiți for_each() când lista ramurilor este descoperită în timpul execuției din starea fluxului de lucru și aveți nevoie de moduri de finalizare precum prima reușită sau cvorumul.