
# 영구 대기 지연

`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은 현재 시간에 지연 시간을 더한 값을 `available_at` 열에 설정해 내부 `__queuety_delay` 작업을 디스패치합니다. 해당 작업은 데이터베이스에 저장되며 지연 시간이 끝날 때까지 어떤 작업자도 가져가지 않습니다.

따라서 다음과 같은 결과가 생깁니다:

- **폴링 없음.** 작업자는 지연 시간을 반복해서 확인하지 않습니다. 시간이 되면 작업을 사용할 수 있게 됩니다.
- **메모리 사용 없음.** 대기 중에는 실행 중인 항목이 없습니다. 지연은 데이터베이스 행으로만 존재합니다.
- **재시작 후에도 유지.** 작업자가 재시작되어도 지연 작업은 올바른 `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/ko/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 );
```
