
# Крайни срокове за работни потоци

На работните потоци може да се зададе краен срок. Ако изпълняващ се работен поток не завърши в зададения период, Queuety го маркира като неуспешен и по избор извиква обработчик. Работните потоци, които са на пауза или чакат сигнал или други работни потоци, не изтичат, докато чакат. Крайните срокове се проверяват приблизително веднъж в минута от дълго работещ процес `wp queuety work`, а не от `--once` работници или резервния механизъм WP-Cron. Това действа като прекъсвач за дълго изпълнявани работни потоци, които не бива да продължават безкрайно.

## Задаване на краен срок

Използвайте `must_complete_within()` в конструктора на работния поток, за да зададете максимално допустимата продължителност. Използвайте `on_deadline()`, за да регистрирате обработчик, който се изпълнява при превишаване на крайния срок.

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

Методът `must_complete_within()` приема именувани параметри, които се сумират:

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

## Обработчик за краен срок

Класът на обработчика `on_deadline()` трябва да реализира метод `handle( array $state ): void`. Той получава публичното състояние на работния поток (всички ключове, които не започват с `_`).

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

Обработчикът за краен срок е незадължителен. Ако искате само работният поток да завърши неуспешно без изпълнение на собствена логика, използвайте `must_complete_within()` без `on_deadline()`.

## Как се проверяват крайните срокове

Работникът проверява за изтекли крайни срокове на всеки 60 секунди като част от цикъла си на обработка. Когато открие работен поток, чийто `status` все още е `running` и чийто `deadline_at` е в миналото, извиква обработчика `on_deadline`, ако е регистриран, маркира работния поток като неуспешен със съобщение за грешка `Deadline exceeded` и записва събитие `workflow_deadline_exceeded` в журнала. Крайният срок се съхранява като времеви маркер `deadline_at` в реда на работния поток и се изчислява при изпращането въз основа на зададената продължителност.

## Какво се случва при изтичане

Когато работен поток превиши крайния си срок, състоянието му се променя на `failed`, съобщението за грешка се задава на `Deadline exceeded`, обработчикът за краен срок се изпълнява синхронно, ако е регистриран, и се записва `workflow_deadline_exceeded` в журнала. Изпълняваните задачи не се прекъсват по средата, но работният поток няма да продължи след границата на изтеклата стъпка. Ако самият обработчик за краен срок хвърли изключение, то се улавя безшумно и работният поток все пак завършва като неуспешен.

## Методи на WorkflowBuilder

| Метод | Описание |
|---|---|
| `must_complete_within( int $seconds = 0, int $minutes = 0, int $hours = 0, int $days = 0 )` | Задава максимално допустимата продължителност. Всички параметри се сумират. |
| `on_deadline( string $handler_class )` | Регистрира обработчик, който се извиква при превишаване на крайния срок. |

## Пример: краен срок с повторен опит

Рядко има смисъл да опитвате отново работен поток, който е завършил неуспешно поради изтекъл краен срок. `retry_workflow()` го връща в състояние `running` и поставя отново неуспешната стъпка в опашката, но не изчиства и не удължава крайния срок, така че следващата проверка — в рамките на около минута — отново ще го провали. Вместо това изпратете нов работен поток.

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

## Краен срок срещу забавяния с изчакване

Крайните срокове се отнасят за цялата продължителност на работния поток. Забавянията с изчакване (`->delay()`) спират работния поток за фиксиран период като част от последователността му от стъпки. Работен поток с едночасово забавяне и краен срок от 2 часа ще се провали, ако стъпките без изчакване продължат общо над 1 час.
