Przejdź do treści

Wycofywanie zmian

Plany wycofania opisują, jak cofnąć wybrane operacje scalania po ich zastosowaniu. Tworzy się je przed zastosowaniem zmian, na podstawie dokładnych danych bieżących wierszy istniejących bezpośrednio przed zapisem.

Nie twórz planu wycofania wyłącznie na podstawie zrzutu podstawowego. Stan podstawowy jest wspólnym przodkiem, a niekoniecznie bieżącym stanem, który jest nadpisywany.

Tworzenie planu wycofania

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'],
);

Plan przechowuje:

  • identyfikator planu scalania,
  • identyfikatory wybranych operacji,
  • zmienione tabele,
  • operacje odwrotne,
  • wiersze przed zmianą,
  • oczekiwane wiersze po zmianie,
  • metadane,
  • skrót wycofania,
  • wersję schematu.

Sprawdzanie rozbieżności

Przed zastosowaniem wycofania porównaj bieżące wiersze z oczekiwanymi wierszami po zmianie zapisanymi w planie wycofania. Jeśli którykolwiek wiersz zmienił się od czasu wdrożenia, domyślnie przerwij operację.

PHP
use Merql\Rollback\RollbackDrift;

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

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

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

Sprawdzanie rozbieżności porównuje odciski wierszy, więc kolejność kolumn nie ma znaczenia.

Stosowanie wycofania

Gdy nie ma rozbieżności, zastosuj operacje odwrotne.

PHP
use Merql\Rollback\RollbackPlanApplier;

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

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

Wycofanie stosuje zwykły wynik MergeResult utworzony z operacji odwrotnych. Działa na tej samej ścieżce stosowania transakcyjnego co zwykłe zastosowanie scalania.

Serializacja

Zapisz plany wycofania przed zastosowaniem scalania w przód. Ten artefakt stanowi trwałą podstawę późniejszego wycofania.

PHP
use Merql\Rollback\RollbackPlanSerializer;

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

Aplikacje powinny przechowywać serializowany plan razem z operacją, która wykonała zapis w bazie produkcyjnej, oraz wszelkimi metadanymi audytowymi specyficznymi dla aplikacji nadrzędnej.