
# Termíny workflowov

Workflowom možno nastaviť termín. Ak sa spustený workflow nedokončí v určenom čase, Queuety ho označí ako neúspešný a môže zavolať obslužnú funkciu. Workflowy, ktoré sú pozastavené alebo čakajú na signál či iné workflowy, počas čakania nevypršia. Termíny kontroluje približne raz za minútu dlho bežiaci proces `wp queuety work`, nie pracovníci `--once` ani záložný mechanizmus WP-Cron. Funguje to ako bezpečnostný mechanizmus pre dlho bežiace workflowy, ktoré by nemali bežať neobmedzene.

## Nastavenie termínu

Pomocou `must_complete_within()` na tvorbe workflowu nastavte maximálne povolené trvanie. Pomocou `on_deadline()` zaregistrujte obslužnú funkciu, ktorá sa spustí po prekročení termínu.

```php
use Queuety\Queuety;

Queuety::workflow( 'data_import' )
    ->then( FetchDataHandler::class )
    ->then( TransformDataHandler::class )
    ->then( LoadDataHandler::class )
    ->must_complete_within( hours: 24 )
    ->on_deadline( ImportTimeoutHandler::class )
    ->dispatch( [ 'source' => $url ] );
```

Metóda `must_complete_within()` prijíma pomenované parametre, ktorých hodnoty sa sčítajú:

```php
->must_complete_within( hours: 2, minutes: 30 )  // 2.5 hours
->must_complete_within( days: 1 )                 // 24 hours
->must_complete_within( seconds: 3600 )           // 1 hour
->must_complete_within( days: 1, hours: 12 )      // 36 hours
```

## Obslužná funkcia termínu

Trieda obslužnej funkcie termínu `on_deadline()` musí implementovať metódu `handle( array $state ): void`. Dostane verejný stav workflowu (všetky kľúče, ktoré sa nezačínajú na `_`).

```php
class ImportTimeoutHandler {

    public function handle( array $state ): void {
        // Alert the team.
        wp_mail(
            'ops@example.com',
            'Import workflow timed out',
            'Workflow for source ' . ( $state['source'] ?? 'unknown' ) . ' exceeded its deadline.'
        );

        // Clean up partial work.
        if ( isset( $state['temp_file'] ) ) {
            unlink( $state['temp_file'] );
        }
    }
}
```

Obslužná funkcia termínu je voliteľná. Ak chcete workflow iba označiť ako neúspešný bez spustenia vlastnej logiky, použite `must_complete_within()` bez `on_deadline()`.

## Ako funguje kontrola termínov

Pracovník kontroluje uplynuté termíny každých 60 sekúnd v rámci cyklu spracovania. Keď nájde workflow, ktorého `status` je stále `running` a ktorého `deadline_at` už uplynul, zavolá zaregistrovanú obslužnú funkciu `on_deadline`, označí workflow ako neúspešný s chybovou správou `Deadline exceeded` a zaznamená udalosť `workflow_deadline_exceeded` do denníka. Samotný termín sa uloží ako časová pečiatka `deadline_at` v riadku workflowu a vypočíta sa pri odoslaní na základe nastaveného trvania.

## Čo sa stane po uplynutí termínu

Keď workflow prekročí svoj termín, jeho stav sa zmení na `failed`, chybová správa sa nastaví na `Deadline exceeded`, zaregistrovaná obslužná funkcia termínu sa spustí synchrónne a zaznamená sa položka `workflow_deadline_exceeded` v denníku. Spustené úlohy sa neprerušia uprostred vykonávania, workflow však nepokročí za hranicu kroku, ktorého termín uplynul. Ak obslužná funkcia termínu sama vyhodí výnimku, výnimka sa potichu zachytí a workflow aj tak skončí ako neúspešný.

## Metódy WorkflowBuilder

| Metóda | Opis |
|---|---|
| `must_complete_within( int $seconds = 0, int $minutes = 0, int $hours = 0, int $days = 0 )` | Nastaví maximálne povolené trvanie. Všetky parametre sa sčítajú. |
| `on_deadline( string $handler_class )` | Zaregistruje obslužnú funkciu, ktorá sa zavolá po prekročení termínu. |

## Príklad: termín a opakovanie

Opakovanie workflowu, ktorému uplynul termín, je zriedka užitočné. `retry_workflow()` obnoví jeho stav na `running` a znova zaradí neúspešný krok do frontu, termín však nevymaže ani nepredĺži, takže pri najbližšej kontrole, približne do minúty, workflow opäť zlyhá. Namiesto toho odošlite nový workflow.

```php
$status = Queuety::workflow_status( $workflow_id );

if ( 'failed' === $status->status->value ) {
    // Check if it was a deadline failure.
    // You may want to dispatch a new workflow instead of retrying.
    Queuety::retry_workflow( $workflow_id );
}
```

## Termín a oneskorenie spánku

Termíny sa vzťahujú na celkové trvanie workflowu. Oneskorenia spánku (`->delay()`) pozastavia workflow na pevne stanovený čas v rámci postupnosti krokov. Workflow s hodinovým oneskorením spánku a dvojhodinovým termínom zlyhá, ak kroky mimo spánku trvajú spolu viac ako hodinu.
