
# ワークフローのタイムトラベル

Queuetyを使うと、ワークフローを前のステップに巻き戻し、その時点から実行を再開できます。ステップが不正な出力を生成した場合、別の設定で再試行したい場合、ワークフロー全体を再起動せずに破損データから復旧したい場合に便利です。

巻き戻しには[ワークフローイベントログ](https://queuety.inline0.dev/ja/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` |
