
# Трайни забавяния

Работните потоци могат да бъдат спирани за фиксиран период между стъпките чрез метода на конструктора `delay()`. Стъпките за забавяне са трайни: забавянето се съхранява в базата данни и се запазва при рестартиране на работници, внедрявания и рестартиране на сървъра.

## Методът `->delay()`

Добавете стъпка за забавяне навсякъде във веригата на работния поток:

```php
use Queuety\Queuety;

Queuety::workflow( 'drip_campaign' )
    ->then( SendWelcomeEmailHandler::class )
    ->delay( days: 1 )
    ->then( SendFollowUpEmailHandler::class )
    ->delay( days: 3 )
    ->then( SendFinalEmailHandler::class )
    ->dispatch( [ 'user_id' => 42 ] );
```

Работният поток ще:

1. Изпълни `SendWelcomeEmailHandler`
2. Изчака 1 ден
3. Изпълни `SendFollowUpEmailHandler`
4. Изчака 3 дни
5. Изпълни `SendFinalEmailHandler`

## Параметри за продължителност

Методът `delay()` приема произволна комбинация от именувани параметри за продължителност:

| Параметър | Тип | Описание |
|---|---|---|
| `$seconds` | `int` | Секунди за изчакване |
| `$minutes` | `int` | Минути за изчакване |
| `$hours` | `int` | Часове за изчакване |
| `$days` | `int` | Дни за изчакване |

Всички стойности се сумират. Следните варианти са равностойни:

```php
->delay( seconds: 3600 )
->delay( minutes: 60 )
->delay( hours: 1 )
```

Можете да ги комбинирате:

```php
->delay( hours: 1, minutes: 30 ) // 90 minutes total
```

## Как работят стъпките за забавяне

Когато работен поток достигне стъпка за забавяне, Queuety изпраща вътрешна задача `__queuety_delay` с колона `available_at`, зададена на текущото време плюс продължителността на забавянето. Задачата остава в базата данни и никой работник не я поема, докато забавянето не изтече.

Това означава:

- **Без периодични проверки.** Работниците не проверяват многократно забавянето. Задачата просто става достъпна, когато настъпи зададеното време.
- **Без използване на памет.** По време на изчакването нищо не се изпълнява. Забавянето съществува само като ред в базата данни.
- **Запазва се при рестартиране.** Ако работникът се рестартира, задачата за забавяне остава в опашката с правилния времеви маркер `available_at`.

Когато задачата за забавяне бъде поета след изтичането му, работният поток автоматично продължава със следващата стъпка.

## Пример: отложени известия

Изпратете напомняне 1 час след регистрацията на потребител, но само ако той не е завършил въвеждането:

```php
Queuety::workflow( 'onboarding_reminder' )
    ->then( CreateAccountHandler::class )
    ->delay( hours: 1 )
    ->then( CheckOnboardingHandler::class )
    ->then( SendReminderHandler::class )
    ->dispatch( [ 'email' => 'user@example.com' ] );
```

Стъпката `CheckOnboardingHandler` може да провери състоянието и да използва [условно разклоняване](https://queuety.inline0.dev/bg/docs/workflows/conditional), за да пропусне напомнянето, ако въвеждането вече е завършено.

## Пример: повторен опит със забавяне

Добавете умишлени забавяния между стъпки с повторен опит:

```php
Queuety::workflow( 'poll_external_api' )
    ->then( CheckStatusHandler::class, 'check' )
    ->delay( minutes: 5 )
    ->then( CheckStatusHandler::class, 'recheck' )
    ->delay( minutes: 15 )
    ->then( CheckStatusHandler::class, 'final_check' )
    ->then( ProcessResultHandler::class )
    ->dispatch( [ 'external_id' => 'abc-123' ] );
```

## Няколко забавяния

Работният поток може да съдържа произволен брой стъпки за забавяне. Всяко забавяне е независимо и се проследява чрез последователно име (`delay_0`, `delay_1` и т.н.) в състоянието на работния поток.

```php
Queuety::workflow( 'multi_step_drip' )
    ->then( StepA::class )
    ->delay( hours: 2 )
    ->then( StepB::class )
    ->delay( days: 1 )
    ->then( StepC::class )
    ->delay( minutes: 30 )
    ->then( StepD::class )
    ->dispatch( $payload );
```
