
# Limity czasu przepływów pracy

Przepływom pracy można przypisać limit czasu. Jeśli uruchomiony przepływ pracy nie zakończy się w określonym czasie, Queuety oznaczy go jako nieudany i opcjonalnie wywoła procedurę obsługi. Przepływy pracy, które są wstrzymane lub czekają na sygnał albo inne przepływy pracy, nie wygasają w czasie oczekiwania. Limity czasu są sprawdzane mniej więcej raz na minutę przez długotrwale działający proces `wp queuety work`, a nie przez procesy robocze `--once` ani mechanizm awaryjny WP-Cron. Działa to jak wyłącznik czuwakowy dla długotrwałych przepływów pracy, które nie powinny działać bez końca.

## Ustawianie limitu czasu

Użyj `must_complete_within()` w konstruktorze przepływu pracy, aby ustawić maksymalny dozwolony czas trwania. Użyj `on_deadline()`, aby zarejestrować procedurę obsługi wywoływaną po przekroczeniu limitu czasu.

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

Metoda `must_complete_within()` przyjmuje nazwane parametry, których wartości są sumowane:

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

## Procedura obsługi limitu czasu

Klasa procedury obsługi `on_deadline()` musi implementować metodę `handle( array $state ): void`. Otrzymuje ona publiczny stan przepływu pracy (wszystkie klucze, które nie zaczynają się od `_`).

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

Procedura obsługi limitu czasu jest opcjonalna. Jeśli chcesz jedynie oznaczyć przepływ pracy jako nieudany bez uruchamiania własnej logiki, użyj `must_complete_within()` bez `on_deadline()`.

## Jak działa sprawdzanie limitu czasu

Proces roboczy sprawdza wygasłe limity czasu co 60 sekund w ramach pętli przetwarzania. Gdy znajdzie przepływ pracy, którego `status` nadal ma wartość `running`, a `deadline_at` wskazuje czas z przeszłości, wywołuje zarejestrowaną procedurę obsługi `on_deadline`, oznacza przepływ pracy jako nieudany z komunikatem błędu `Deadline exceeded` i zapisuje zdarzenie w dzienniku `workflow_deadline_exceeded`. Sam limit czasu jest przechowywany jako znacznik czasu `deadline_at` w wierszu przepływu pracy i obliczany w chwili uruchomienia na podstawie skonfigurowanego czasu trwania.

## Co się dzieje po wygaśnięciu limitu

Gdy przepływ pracy przekroczy limit czasu, jego status zmienia się na `failed`, komunikat błędu przyjmuje wartość `Deadline exceeded`, zarejestrowana procedura obsługi limitu czasu uruchamia się synchronicznie, a wpis `workflow_deadline_exceeded` zostaje dodany do dziennika. Uruchomione zadania nie są przerywane w trakcie wykonywania, ale przepływ pracy nie przejdzie poza granicę wygasłego kroku. Jeśli sama procedura obsługi limitu czasu zgłosi wyjątek, zostanie on po cichu przechwycony, a przepływ pracy i tak zakończy się niepowodzeniem.

## Metody WorkflowBuilder

| Metoda | Opis |
|---|---|
| `must_complete_within( int $seconds = 0, int $minutes = 0, int $hours = 0, int $days = 0 )` | Ustawia maksymalny dozwolony czas trwania. Wszystkie parametry są sumowane. |
| `on_deadline( string $handler_class )` | Rejestruje procedurę obsługi wywoływaną po przekroczeniu limitu czasu. |

## Przykład: limit czasu z ponawianiem

Ponawianie przepływu pracy, który zakończył się niepowodzeniem po przekroczeniu limitu czasu, rzadko ma sens. `retry_workflow()` resetuje go do `running` i ponownie umieszcza nieudany krok w kolejce, ale nie usuwa ani nie wydłuża limitu czasu, więc przy następnym sprawdzeniu, za około minutę, przepływ znów zakończy się niepowodzeniem. Zamiast tego uruchom nowy przepływ pracy.

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

## Limit czasu a opóźnienia uśpienia

Limity czasu dotyczą całkowitego czasu trwania przepływu pracy. Opóźnienia uśpienia (`->delay()`) wstrzymują przepływ na określony czas w ramach sekwencji kroków. Przepływ pracy z godzinnym opóźnieniem uśpienia i limitem czasu wynoszącym 2 godziny zakończy się niepowodzeniem, jeśli łączny czas wykonywania kroków innych niż uśpienie przekroczy 1 godzinę.
