Aller au contenu

Retour arrière

Les plans de retour arrière décrivent comment annuler des opérations de fusion sélectionnées après leur application. Ils sont créés avant l'application, à partir des lignes exactes présentes en temps réel juste avant l'écriture.

Ne générez pas un retour arrière à partir du seul instantané de base. La base est l'ancêtre commun, pas nécessairement l'état en temps réel qui est remplacé.

Créer un plan de retour arrière

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

Le plan stocke :

  • l'ID du plan de fusion,
  • les ID des opérations sélectionnées,
  • les tables concernées,
  • les opérations inverses,
  • les lignes avant,
  • les lignes après attendues,
  • les métadonnées,
  • un hachage de restauration,
  • une version du schéma.

Vérification de dérive

Avant d'appliquer la restauration, comparez les lignes actives actuelles aux lignes après attendues du plan de restauration. Si une ligne a changé depuis la promotion, annulez par défaut.

PHP
use Merql\Rollback\RollbackDrift;

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

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

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

La vérification de dérive compare les empreintes des lignes ; l'ordre des colonnes n'a donc pas d'importance.

Appliquer la restauration

En l'absence de dérive, appliquez les opérations inverses.

PHP
use Merql\Rollback\RollbackPlanApplier;

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

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

La restauration applique un MergeResult normal construit à partir des opérations inverses. Elle suit le même chemin d'application transactionnel que l'application d'une fusion ordinaire.

Sérialisation

Enregistrez les plans de restauration avant d'appliquer la fusion dans le sens direct. Cet artefact constitue la base durable des restaurations ultérieures.

PHP
use Merql\Rollback\RollbackPlanSerializer;

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

Les applications doivent enregistrer le plan sérialisé avec l'opération qui a effectué l'écriture active, ainsi que toute métadonnée d'audit propre à l'hôte.