Skip to content

fix: reverte automaticamente para a salvaguarda quando a reabertura falha na resolução de conflito use_remote - #458

Merged
johnlaff merged 1 commit into
mainfrom
impl/issue-451
Aug 14, 2026
Merged

fix: reverte automaticamente para a salvaguarda quando a reabertura falha na resolução de conflito use_remote#458
johnlaff merged 1 commit into
mainfrom
impl/issue-451

Conversation

@johnlaff

Copy link
Copy Markdown
Owner

O quê e por quê

resolve_conflict_use_remote_core (resolução de conflito do snapshot no Drive, escolha "usar o outro aparelho") faz o mesmo swap+reopen do check-out no boot: baixa o snapshot do outro aparelho, fecha o pool local, troca o arquivo do banco atomicamente e reabre um pool novo no arquivo trocado. Se a troca tivesse sucesso mas a reabertura do conteúdo recém-trocado falhasse (I/O transitório, disco cheio durante a migração), a função devolvia erro e o banco ativo ficava preso no conteúdo quebrado — mesmo havendo, ao lado, uma salvaguarda íntegra do conteúdo local de ANTES da troca, criada pela própria swap_active_db_atomically, pronta para reversão automática.

O mesmo problema já tinha sido corrigido no check-out do boot (#446), via checkout::reopen_after_swap_or_rollback. Este PR expõe essa função (antes privada ao módulo checkout) e a reusa aqui, em vez de duplicar a lógica.

Mudança

  • checkout::reopen_after_swap_or_rollback e o enum ReopenOutcome passam a ser pub(crate).
  • A mensagem de ReopenOutcome::RolledBack agora descreve só O QUE aconteceu (reabertura falhou, revertido com sucesso) — a cláusula de "o que fazer a seguir" é específica de cada chamador: commit_restore (boot) mantém a frase original ("o snapshot remoto será tentado de novo na próxima abertura"); resolve_conflict_use_remote_core (conflito) agora diz que a disputa segue pendente para o dono escolher de novo depois de reiniciar.
  • resolve_conflict_use_remote_core troca a chamada direta a open_migrated_pool por reopen_after_swap_or_rollback, tratando os três desfechos (Reopened, RolledBack, Err fatal).

Decisão registrada (issue #451, item 1): requires_restart continua sempre true nesta função, em qualquer desfecho — inclusive quando a reversão automática funciona. O pool que a função recebe já é fechado no ponto de não-retorno, antes da troca de arquivo, e não existe hoje um jeito de substituir o pool gerenciado pelo Tauri (State<SqlitePool>) no meio de uma sessão — só app.manage() dentro do setup() faz isso. Mudar esse contrato só para o caminho de reversão exigiria plumbing novo fora do escopo deste follow-up; a reversão evita deixar o dono com um banco corrompido/inutilizável após reiniciar, mas não evita o reinício em si. Escolhido pelo menor escopo, por simetria com o resto da função (que já sempre pede reinício, mesmo no caminho feliz).

Decisão registrada (issue #451, item 2): compartilhamento via exposição pub(crate) da função já existente e exaustivamente testada em checkout.rs, em vez de duplicar a lógica de reversão.

TDD

Teste novo em snapshot_cmds.rs: resolve_use_remote_rolls_back_to_the_local_safeguard_when_the_remote_content_wont_reopen. Constrói um snapshot remoto SQLite estruturalmente válido (passa PRAGMA integrity_check), mas com o checksum de uma migração corrompido de propósito — sqlx::migrate!().run() recusa reabrir (VersionMismatch) mesmo com o arquivo íntegro, reproduzindo de ponta a ponta (com HTTP mockado) a mesma classe de falha que a issue descreve ("I/O transitório, disco cheio na migração"). O teste confirma que, depois do erro, o banco ativo reaberto do zero contém o conteúdo LOCAL de antes da troca — nunca o remoto quebrado, nunca um banco vazio.

Como verificar

  • cargo test --lib snapshot — 112 testes do módulo, incluindo o novo.
  • cargo test --lib snapshot_cmds — 19 testes, incluindo o novo.
  • npm run check — gate completo (format, lint, typecheck, testes JS, build, rust:check, privacy:scan, comment:hygiene, ui:audit) verde.

Closes #451

…na resolução de conflito use_remote

resolve_conflict_use_remote_core trocava o arquivo do banco pelo snapshot do outro aparelho e, se a reabertura em seguida falhasse (I/O transitório, disco cheio na migração), devolvia erro deixando o banco ativo preso no conteúdo quebrado — mesmo com uma salvaguarda íntegra do conteúdo local ao lado, criada pela própria troca. O check-out no boot já resolvia essa mesma janela via reopen_after_swap_or_rollback (issue #446); esta mudança expõe essa função do módulo checkout e a reusa aqui, revertendo automaticamente para a salvaguarda em vez de deixar o dono com um banco inutilizável após reiniciar.

requires_restart continua sempre true nesta função, em qualquer desfecho: o pool recebido já foi fechado no ponto de não-retorno antes da troca de arquivo, e não há hoje como substituir o pool gerenciado pelo Tauri no meio de uma sessão — a reversão evita corrupção, não o reinício em si.
@johnlaff
johnlaff merged commit 16eaf08 into main Aug 14, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Snapshot no Drive: reversão automática do reopen-after-swap também no fluxo de resolução de conflito (use_remote)

1 participant