
# Atrasos duráveis

Os workflows podem ser pausados por um período fixo entre etapas usando o método de construção `delay()`. As etapas de atraso são duráveis: o atraso é armazenado no banco de dados, então permanece após reinicializações de workers, implantações e reinicializações do servidor.

## O método `->delay()`

Adicione uma etapa de atraso em qualquer ponto da cadeia do workflow:

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

O workflow irá:

1. Executar `SendWelcomeEmailHandler`
2. Aguardar 1 dia
3. Executar `SendFollowUpEmailHandler`
4. Aguardar 3 dias
5. Executar `SendFinalEmailHandler`

## Parâmetros de duração

O método `delay()` aceita qualquer combinação de parâmetros de duração nomeados:

| Parâmetro | Tipo | Descrição |
|---|---|---|
| `$seconds` | `int` | Segundos de espera |
| `$minutes` | `int` | Minutos de espera |
| `$hours` | `int` | Horas de espera |
| `$days` | `int` | Dias de espera |

Todos os valores são somados. Estes exemplos são equivalentes:

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

Você pode combiná-los:

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

## Como funcionam as etapas de atraso

Quando um workflow chega a uma etapa de atraso, Queuety despacha um job interno `__queuety_delay` com a coluna `available_at` definida para o horário atual mais a duração do atraso. O job fica no banco de dados e não é reivindicado por nenhum worker até que o atraso termine.

Isso significa que:

- **Sem polling.** Os workers não verificam repetidamente o atraso. O job simplesmente fica disponível quando chega o momento.
- **Sem uso de memória.** Nada é executado durante a espera. O atraso existe apenas como uma linha no banco de dados.
- **Sobrevive a reinicializações.** Se o worker reiniciar, o job de atraso continuará na fila com o timestamp `available_at` correto.

Quando o job de atraso é reivindicado após o período de espera, o workflow avança automaticamente para a próxima etapa.

## Exemplo: notificações atrasadas

Envie um lembrete 1 hora após o cadastro de um usuário, mas somente se ele ainda não tiver concluído a integração:

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

A etapa `CheckOnboardingHandler` pode inspecionar o estado e usar a [ramificação condicional](https://queuety.inline0.dev/pt/docs/workflows/conditional) para ignorar o lembrete se a integração já estiver concluída.

## Exemplo: repetição com espera progressiva

Insira atrasos deliberados entre etapas semelhantes a tentativas repetidas:

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

## Vários atrasos

Um workflow pode conter qualquer número de etapas de atraso. Cada atraso é independente e rastreado por um nome sequencial (`delay_0`, `delay_1`, etc.) no estado do workflow.

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