
# 워크플로 시간 되감기

Queuety을 사용하면 워크플로를 이전 단계로 되감아 해당 지점부터 실행을 재개할 수 있습니다. 단계에서 잘못된 출력이 생성되었거나, 다른 구성으로 재시도하려는 경우 또는 워크플로 전체를 처음부터 다시 시작하지 않고 손상된 데이터에서 복구해야 할 때 유용합니다.

되감기는 [워크플로 이벤트 로그](https://queuety.inline0.dev/ko/docs/workflows/event-log)를 사용합니다. 대상 단계의 `state_after` 데이터가 이벤트 로그에 있어야 합니다.

## 워크플로 되감기

### PHP API

워크플로 ID와 되감을 단계 인덱스를 지정해 `Queuety::rewind_workflow()`을 호출합니다:

```php
use Queuety\Queuety;

// Rewind workflow 42 to step 1.
// The state is restored to the snapshot taken after step 1 completed,
// and step 2 is enqueued for re-execution.
Queuety::rewind_workflow( $workflow_id, to_step: 1 );
```

`to_step` 매개변수는 완료 상태를 복원할 단계의 0부터 시작하는 인덱스입니다. 실행은 _다음_ 단계(to_step + 1)부터 재개됩니다.

### CLI

```bash
wp queuety workflow rewind <id> <step>
```

| 옵션 | 설명 |
|---|---|
| `<id>` | 워크플로 ID(필수) |
| `<step>` | 되돌릴 단계 인덱스, 0부터 시작(필수) |

```bash
wp queuety workflow rewind 42 1
```

## 작동 방식

워크플로를 N단계로 되감으면:

1. 이벤트 로그에서 단계 N이 완료된 후 기록된 `state_after` 값을 조회합니다.
2. 스냅샷이 없으면 `RuntimeException`을 던집니다.
3. 워크플로 행을 잠급니다.
4. 현재 워크플로 행의 모든 예약 키(`_steps`, `_queue`, `_priority` 등)를 보존하면서 워크플로 상태를 스냅샷으로 교체합니다.
5. `current_step`을 N + 1로 설정하고 `status`을 `running`로 설정합니다.
6. `error_message` 및 `failed_at` 필드를 모두 비웁니다.
7. 인덱스 N + 1의 단계를 처리 대기열에 넣습니다.
8. `workflow_rewound` 로그 이벤트를 기록합니다.

그러면 작업자가 대기열에 들어간 단계를 가져오고, 그 시점부터 워크플로가 정상적으로 계속됩니다.

## 요구 사항

되감기하려면 이벤트 로그에 `state_after` 데이터가 있어야 합니다. 이벤트 로그는 모든 `step_completed` 이벤트에 대해 해당 데이터를 자동으로 기록합니다. 이벤트 로그가 `WorkflowEventLog::prune()`을 통해 정리되어 대상 단계의 상태가 더 이상 존재하지 않으면 되감기에 실패합니다.

되감아야 할 수 있는 기간을 이벤트 로그 보존 기간에 포함하세요.

## 사용 사례

### 버그가 있는 단계 핸들러 수정

단계 핸들러의 버그로 잘못된 출력이 생성된 경우, 수정 사항을 배포한 다음 되감을 수 있습니다.

```php
// Step 2 (CallLLMHandler) produced garbled output due to a prompt bug.
// After fixing CallLLMHandler, rewind to step 1 so step 2 runs again
// with the corrected handler.
Queuety::rewind_workflow( $workflow_id, to_step: 1 );
```

### 다른 설정으로 재시도

외부 요인(API 속도 제한, 잘못된 인증 정보)으로 단계가 실패한 경우, 설정을 수정하고 되감아 다시 실행하세요.

```php
// Step 3 failed because the API key was expired.
// After updating the key, rewind to step 2 so step 3 retries.
Queuety::rewind_workflow( $workflow_id, to_step: 2 );
```

### 잘못된 데이터 복구

이전 단계에서 상태에 잘못된 데이터가 들어간 경우, 정상 상태의 스냅샷으로 되감으세요.

```php
// Step 0 fetched correct data, but step 1 corrupted it.
// Rewind to step 0 to restore the good state and re-run step 1.
Queuety::rewind_workflow( $workflow_id, to_step: 0 );
```

## 재시도와 비교

| 항목 | `retry_workflow()` | `rewind_workflow()` |
|---|---|---|
| 재개 지점 | 실패한 단계 | 이전 단계 중 임의의 단계 |
| 상태 | 현재 워크플로 상태 | 이벤트 로그 `state_after`에서 복원 |
| 필요 조건 | 워크플로 상태가 `failed`이어야 함 | 대상 단계의 이벤트 로그 스냅샷 |
| 이후 상태 | `running` | `running` |
| 로그 이벤트 | 없음 | `workflow_rewound` |
