
# Tidsgränser för arbetsflöden

Arbetsflöden kan tilldelas en tidsgräns. Om ett pågående arbetsflöde inte har slutförts inom den angivna tiden markerar Queuety det som misslyckat och anropar eventuellt en hanterare. Arbetsflöden som är pausade eller väntar på en signal eller på andra arbetsflöden löper inte ut medan de väntar. Tidsgränser kontrolleras ungefär en gång i minuten av en långkörande `wp queuety work`-process, inte av `--once`-arbetare eller WP-Cron-reservlösningen. Det fungerar som en dödmansknapp för långkörande arbetsflöden som inte ska köras på obestämd tid.

## Ange en tidsgräns

Använd `must_complete_within()` på arbetsflödesbyggaren för att ange den maximalt tillåtna varaktigheten. Använd `on_deadline()` för att registrera en hanterare som körs när tidsgränsen överskrids.

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

Metoden `must_complete_within()` tar emot namngivna parametrar som summeras:

```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
```

## Hanterare för tidsgräns

Hanterarklassen `on_deadline()` måste implementera en `handle( array $state ): void`-metod. Den tar emot arbetsflödets publika tillstånd (alla nycklar som inte börjar med `_`).

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

Hanteraren för tidsgränsen är valfri. Om du bara vill att arbetsflödet ska misslyckas utan att anpassad logik körs använder du `must_complete_within()` utan `on_deadline()`.

## Så fungerar kontrollen av tidsgränser

Arbetaren kontrollerar utgångna tidsgränser var 60:e sekund som en del av sin bearbetningsloop. När den hittar ett arbetsflöde där `status` fortfarande är `running` och `deadline_at` ligger i det förflutna anropar den hanteraren `on_deadline` om en sådan är registrerad, markerar arbetsflödet som misslyckat med felmeddelandet `Deadline exceeded` och registrerar en logghändelse av typen `workflow_deadline_exceeded`. Tidsgränsen lagras som en tidsstämpel av typen `deadline_at` på arbetsflödesraden och beräknas vid utskick utifrån den konfigurerade varaktigheten.

## Vad som händer när tiden löper ut

När ett arbetsflöde överskrider sin tidsgräns ändras dess status till `failed`, felmeddelandet sätts till `Deadline exceeded`, hanteraren för tidsgränsen körs synkront om en sådan är registrerad och en loggpost av typen `workflow_deadline_exceeded` registreras. Pågående jobb avbryts inte mitt i körningen, men arbetsflödet går inte vidare förbi gränsen för det utgångna steget. Om hanteraren för tidsgränsen själv kastar ett undantag fångas det tyst, och arbetsflödet slutar ändå som misslyckat.

## WorkflowBuilder-metoder

| Metod | Beskrivning |
|---|---|
| `must_complete_within( int $seconds = 0, int $minutes = 0, int $hours = 0, int $days = 0 )` | Anger den maximalt tillåtna varaktigheten. Alla parametrar summeras. |
| `on_deadline( string $handler_class )` | Registrerar en hanterare som anropas när tidsgränsen överskrids. |

## Exempel: tidsgräns med återförsök

Det är sällan meningsfullt att försöka igen med ett arbetsflöde som misslyckades på grund av sin tidsgräns. `retry_workflow()` återställer det till `running` och köar det misslyckade steget igen, men rensar eller förlänger inte tidsgränsen. Därför misslyckas arbetsflödet igen vid nästa kontroll av tidsgränsen, inom ungefär en minut. Skicka i stället ett nytt arbetsflöde.

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

## Tidsgräns jämfört med fördröjningar med sleep

Tidsgränser gäller hela arbetsflödets varaktighet. Fördröjningar med sleep (`->delay()`) pausar arbetsflödet en fast tid som en del av dess stegsekvens. Ett arbetsflöde med en fördröjning på 1 timme och en tidsgräns på 2 timmar misslyckas om stegen utan sleep tar mer än 1 timme sammanlagt.
