Відкат
Плани відкату описують скасування вибраних операцій злиття після їх застосування. Їх створюють до застосування, використовуючи точні поточні рядки безпосередньо перед записом.
Не створюйте відкат лише на основі базового знімка. Base — це спільний предок, а не обов’язково поточний стан, який перезаписують.
Створення плану відкату
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'],
);
План зберігає:
- ідентифікатор плану злиття,
- ідентифікатори вибраних операцій,
- таблиці, яких торкнулися зміни,
- зворотні операції,
- рядки до змін,
- очікувані рядки після змін,
- метадані,
- хеш відкату,
- версію схеми.
Перевірка розбіжностей
Перед застосуванням відкату порівняйте поточні рядки з очікуваними рядками після змін із плану відкату. Якщо після перенесення змінився будь-який рядок, за замовчуванням зупиніть операцію.
use Merql\Rollback\RollbackDrift;
$currentRows = [
$operationId => $currentLiveRow,
];
$drifted = (new RollbackDrift())->driftedOperationIds($rollback, $currentRows);
if ($drifted !== []) {
throw new RuntimeException('Rollback drifted: ' . implode(', ', $drifted));
}
Перевірка розбіжностей порівнює відбитки рядків, тому порядок стовпців не має значення.
Застосування відкату
Якщо розбіжностей немає, застосуйте зворотні операції.
use Merql\Rollback\RollbackPlanApplier;
$applied = (new RollbackPlanApplier($connection))->apply($rollback);
if ($applied->hasErrors()) {
foreach ($applied->errors() as $error) {
echo $error . "\n";
}
}
Відкат застосовує звичайний MergeResult, побудований зі зворотних операцій. Він проходить тим самим шляхом застосування в межах транзакції, що й звичайне застосування злиття.
Серіалізація
Збережіть плани відкату до застосування прямого злиття. Цей артефакт слугуватиме надійною основою для подальшого відкату.
use Merql\Rollback\RollbackPlanSerializer;
$json = RollbackPlanSerializer::toJson($rollback);
$restored = RollbackPlanSerializer::fromJson($json);
Застосункам слід зберігати серіалізований план разом з операцією, що виконала запис у робочу базу, а також із будь-якими специфічними для хоста даними аудиту.