
# ロールバック

ロールバック計画は、適用済みの選択されたマージ操作を取り消す方法を示します。適用前に、書き込み直前に存在する正確なライブ行を使って作成します。

baseスナップショットだけからロールバックを生成しないでください。baseは共通の祖先であり、上書き対象のライブ状態とは限りません。

## ロールバック計画の作成

```php
use Merql\Plan\ChangeGroupSelection;
use Merql\Rollback\RollbackPlanBuilder;
use Merql\Snapshot\SnapshotStore;

$selection = ChangeGroupSelection::fromIds([$plan->changeGroups[0]->id]);
$operationSelection = $selection->toOperationSelection($plan);
$expectedLive = SnapshotStore::load($plan->theirsSnapshot);

$liveBeforeRows = [];
foreach ($plan->operations as $operation) {
    if (!$operationSelection->contains($operation->id)) {
        continue;
    }

    $liveBeforeRows[$operation->id] = $expectedLive
        ->getTable($operation->table)
        ?->getRow($operation->rowKey);
}

$rollback = (new RollbackPlanBuilder())->build(
    'rollback-1',
    $plan,
    $operationSelection,
    $liveBeforeRows,
    metadata: ['promotion_id' => 'promotion-1'],
);
```

計画には次の情報が保存されます:

- マージ計画ID
- 選択した操作ID
- 変更対象のテーブル
- 逆操作
- 変更前の行
- 想定される変更後の行
- メタデータ
- ロールバックハッシュ
- スキーマバージョン

## 変更の確認

ロールバックを適用する前に、現在のライブ行とロールバック計画で想定される変更後の行を比較します。昇格後に行が変更されていれば、既定では中止します。

```php
use Merql\Rollback\RollbackDrift;

$currentRows = [
    $operationId => $currentLiveRow,
];

$drifted = (new RollbackDrift())->driftedOperationIds($rollback, $currentRows);

if ($drifted !== []) {
    throw new RuntimeException('Rollback drifted: ' . implode(', ', $drifted));
}
```

変更の確認では行のフィンガープリントを比較するため、列の順序は影響しません。

## ロールバックの適用

変更がなければ、逆操作を適用します。

```php
use Merql\Rollback\RollbackPlanApplier;

$applied = (new RollbackPlanApplier($connection))->apply($rollback);

if ($applied->hasErrors()) {
    foreach ($applied->errors() as $error) {
        echo $error . "\n";
    }
}
```

ロールバックでは、逆操作から作成した通常の`MergeResult`を適用します。通常のマージ適用と同じトランザクション処理経路で実行されます。

## シリアライズ

順方向のマージを適用する前に、ロールバック計画を永続化してください。この成果物が、後でロールバックする際の永続的な基礎になります。

```php
use Merql\Rollback\RollbackPlanSerializer;

$json = RollbackPlanSerializer::toJson($rollback);
$restored = RollbackPlanSerializer::fromJson($json);
```

アプリケーションでは、シリアライズした計画をライブ書き込みを実行した操作とともに保存し、ホスト固有の監査メタデータも添付してください。
