
# Создание ответвления рабочего процесса

Queuety может создать полностью независимую копию выполняющегося рабочего процесса. Ответвление начинается с того же шага и в том же состоянии, что и исходный рабочий процесс, но затем они выполняются независимо друг от друга. Изменения в одном не влияют на другой.

## Создание ответвления рабочего процесса

### PHP API

Вызовите `Queuety::fork_workflow()`, указав ID рабочего процесса. Метод возвращает новый ID рабочего процесса:

```php
use Queuety\Queuety;

$forked_id = Queuety::fork_workflow( $workflow_id );
```

### CLI

```bash
wp queuety workflow fork <id>
```

| Параметр | Описание |
|---|---|
| `<id>` | ID рабочего процесса для создания копии (обязательно) |

```bash
wp queuety workflow fork 42
# Success: Workflow #42 forked. New workflow ID: 43.
```

## Как это работает

При создании ответвления рабочего процесса:

1. Исходная запись рабочего процесса блокируется и считывается
2. Создается новая запись с теми же состоянием, определениями шагов и текущим шагом
3. Имя нового рабочего процесса — `{original_name}_fork_{timestamp}`
4. Текущий шаг ставится в очередь для ответвленного рабочего процесса
5. Для исходного и ответвленного рабочего процесса записывается событие журнала `workflow_forked`
6. Исходный рабочий процесс продолжает выполняться как обычно

Ответвленный рабочий процесс полностью независим. У него свой ID, собственная копия состояния и отдельные задания в очереди. Начиная с точки ответвления, каждый рабочий процесс может развиваться по-своему.

## Сценарии использования

### A/B-тестирование обработчиков шагов

Создайте ответвление рабочего процесса, чтобы проверить две разные реализации будущего шага:

```php
// Original workflow will use the existing CallLLMHandler (GPT-4).
// Fork it to test with a different handler.
$forked_id = Queuety::fork_workflow( $workflow_id );

// Modify the forked workflow's state to use a different model.
// (Update the state via a custom step or direct DB update.)
```

### Анализ сценариев «что, если»

Создайте ответвление в точке принятия решения, чтобы изучить разные ветви:

```php
// Workflow is at step 3, about to process data.
// Fork it so we can try two different processing strategies.
$fork_a = Queuety::fork_workflow( $workflow_id );
$fork_b = Queuety::fork_workflow( $workflow_id );
```

Каждое ответвление начинается с тех же входных данных, но его можно изменить, чтобы выбрать другой путь.

### Параллельные эксперименты

Когда рабочий процесс достигает точки, в которой нужно попробовать несколько подходов параллельно, создайте отдельное ответвление для каждого подхода и сравните результаты после их завершения.

## Отслеживание ответвлений

Событие журнала каждого рабочего процесса содержит ссылку на другой:

- В исходном: `context.forked_workflow_id` указывает на новый рабочий процесс
- В ответвлении: `context.forked_from_workflow_id` указывает на исходный

Запросите журналы, чтобы найти все ответвления рабочего процесса:

```php
$logs = Queuety::logger()->for_workflow( $workflow_id );

foreach ( $logs as $entry ) {
    if ( 'workflow_forked' === $entry['event'] ) {
        $context = json_decode( $entry['context'] ?? '{}', true );
        // $context['forked_workflow_id'] is the new workflow
    }
}
```

## Ограничения

- Ответвленный рабочий процесс не наследует историю журнала событий исходного. Он начинает с пустого журнала событий.
- Связи запуска рабочих процессов не дублируются. Если исходный рабочий процесс запускал другой рабочий процесс, ответвление не получает его копию.
- Ответвление представляет собой снимок текущего состояния. Незавершенные задания исходного рабочего процесса не дублируются.
