Pular para o conteúdo

Reversão

Os planos de reversão descrevem como desfazer operações de mesclagem selecionadas depois que elas são aplicadas. Eles são criados antes da aplicação, usando as linhas ativas exatas que existem imediatamente antes da gravação.

Não gere a reversão apenas a partir do snapshot base. A base é o ancestral comum, não necessariamente o estado ativo que está sendo sobrescrito.

Criar um plano de reversão

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

O plano armazena:

  • o ID do plano de mesclagem,
  • os IDs das operações selecionadas,
  • as tabelas afetadas,
  • as operações inversas,
  • as linhas anteriores,
  • as linhas posteriores esperadas,
  • os metadados,
  • um hash de reversão,
  • uma versão do esquema.

Verificação de divergências

Antes de aplicar a reversão, compare as linhas ativas atuais com as linhas posteriores esperadas no plano de reversão. Se alguma linha mudou desde a promoção, aborte por padrão.

PHP
use Merql\Rollback\RollbackDrift;

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

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

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

A verificação de divergências compara impressões digitais das linhas, portanto a ordem das colunas não importa.

Aplicar reversão

Quando não houver divergências, aplique as operações inversas.

PHP
use Merql\Rollback\RollbackPlanApplier;

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

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

A reversão aplica um MergeResult normal criado a partir de operações inversas. Ela é executada pelo mesmo fluxo transacional de aplicação usado para mesclagens comuns.

Serialização

Persista os planos de reversão antes de aplicar a mesclagem direta. Esse artefato é a base duradoura para uma reversão posterior.

PHP
use Merql\Rollback\RollbackPlanSerializer;

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

Os aplicativos devem armazenar o plano serializado junto à operação que realizou a gravação ativa, juntamente com quaisquer metadados de auditoria específicos do host.