Връщане назад
Плановете за връщане назад описват как да отмените избрани операции за сливане след прилагането им. Създават се преди прилагането, като използват точните активни редове, налични непосредствено преди записването.
Не създавайте план за връщане назад само от базовата моментна снимка. Базата е общият предшественик, а не непременно активното състояние, което се презаписва.
Създаване на план за връщане назад
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 на избраните операции,
- засегнати таблици,
- обратни операции,
- редове преди промяната,
- очаквани редове след промяната,
- метаданни,
- хеш за връщане назад,
- версия на схемата.
Проверка за промени
Преди да приложите връщането назад, сравнете текущите активни редове с очакваните редове след промяната в плана. Ако някой ред се е променил след промотирането, по подразбиране операцията се прекратява.
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);
Приложенията трябва да съхраняват сериализирания план заедно с операцията, извършила записването в активната база, както и с всички специфични за хост приложението данни за одит.