From 2724746cb71efc99b9e021d74e90b32dd327cc40 Mon Sep 17 00:00:00 2001 From: Esdras Renan Date: Tue, 18 Nov 2025 11:58:58 -0300 Subject: [PATCH] =?UTF-8?q?docs:=20registrar=20corre=C3=A7=C3=A3o=20do=20e?= =?UTF-8?q?xport=20do=20convex?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/OPERATIONS.md | 3 + docs/convex-export-worker-loop.md | 125 ++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 docs/convex-export-worker-loop.md diff --git a/docs/OPERATIONS.md b/docs/OPERATIONS.md index 6900346..c451c2d 100644 --- a/docs/OPERATIONS.md +++ b/docs/OPERATIONS.md @@ -165,6 +165,9 @@ Depois disso, o job “Deploy Convex functions” funciona em modo não interati - Abra o DevTools (console) e filtre por `admin-machine-details`. Se o log mostrar `machineId: undefined`, o componente não recebeu o parâmetro da rota. - Verifique se o `page.tsx` está passando `params.id` corretamente ou se o componente client-side usa `useParams()` / `machineId` opcional. - Deploys antigos antes de `fix(machines): derive machine id from router params` precisam desse patch; sem ele o fallback nunca dispara e o skeleton permanece. +- Export do Convex em loop (`application::exports::worker`) + - Sintoma: WebSocket `1006`, logs com `Caught error ... shape_inference`, `Export beginning...` repetindo. + - Solução completa documentada em `docs/convex-export-worker-loop.md` (backup do SQLite, limpeza dos registros defeituosos e rerun do export). --- diff --git a/docs/convex-export-worker-loop.md b/docs/convex-export-worker-loop.md new file mode 100644 index 0000000..a9f3f5b --- /dev/null +++ b/docs/convex-export-worker-loop.md @@ -0,0 +1,125 @@ +# Convex — Loop do `application::exports::worker` (Nov/2025) + +Documento técnico descrevendo o incidente que derrubava o backend Convex em produção e o passo a passo adotado para corrigir e evitar recorrências. + +--- + +## 1. Resumo Executivo + +- **Sintoma visível:** o WebSocket `wss://convex.esdrasrenan.com.br/api/1.29.2/sync` caía em código 1006 a cada poucos segundos. +- **Causa raiz:** um export agendado automaticamente pelo próprio Convex (`application::exports::worker`) reiniciava toda vez que o backend subia. Durante o “replay” o worker lia documentos (principalmente máquinas e cron jobs antigos) cujo _shape_ já não batia com o esquema atual, causando panic em `shape_inference/src/object.rs:67`. +- **Impacto:** o container `sistema_convex_backend` reiniciava em loop. `npx convex deploy` e qualquer CLI que dependesse do backend ficavam presos em `start_push`/`wait_for_schema`. O frontend ficava sem sincronização em tempo real. +- **Correção aplicada:** saneamento manual do banco SQLite do Convex (limpeza de cron/exports/records incompatíveis) seguido de um restart completo. O export pendente finalizou com sucesso e o backend estabilizou. + +--- + +## 2. Detecção + +1. `docker service logs --tail 400 sistema_convex_backend` mostrava: + - Mensagens repetidas do export (`Export gg20vw5b... progress: ...`). + - Panics em `application::exports::worker` ou `common::errors` com mensagens `Object with shape ... not in Shape ...`. +2. No navegador e no `npx convex deploy`, as conexões WebSocket encerravam com código 1006. + +--- + +## 3. Diagnóstico / Root Cause Analysis + +1. O Convex self-hosted mantém **exports incrementais**. Quando o backend reinicia, o worker reprocessa o export pendente. +2. Em `sistema_convex_data`, a tabela `documents` possuía registros legados: + - Cron `hours-usage-alerts-hourly` (já removido do código). + - Documentos de máquinas com `metadata`/`customFields` maiores do que o shape compilado. +3. Assim que o export lia esses documentos “fora do shape”, o Convex fazia `panic!`, derrubando o processo principal. +4. Como o export jamais completava, o worker reiniciava e o ciclo se repetia. + +--- + +## 4. Procedimento de Recuperação (Runbook) + +> ⚠️ **Sempre trabalhar em cima do volume `sistema_convex_data`.** +> Todos os comandos abaixo devem ser executados como `root` na VPS. + +### 4.1. Parar o backend e fazer backup + +```bash +docker service scale sistema_convex_backend=0 + +# Guardar uma cópia datada +docker run --rm -v sistema_convex_data:/convex/data \ + busybox sh -c 'ts=$(date +%Y%m%d%H%M%S); cp /convex/data/db.sqlite3 /convex/data/db.sqlite3.backup-$ts' +``` + +### 4.2. Inspecionar o banco (SQLite) + +Usamos a imagem `nouchka/sqlite3`, montando o volume: + +```bash +docker run --rm -it -v sistema_convex_data:/convex/data nouchka/sqlite3 /convex/data/db.sqlite3 +``` + +Consultas úteis: + +```sql +-- Verificar o export pendente +SELECT json_value FROM documents +WHERE json_extract(json_value, '$.name') = 'hours-usage-alerts-hourly'; + +-- Identificar documentos de máquinas problemáticos +SELECT hex(id), hex(table_id), ts +FROM documents +WHERE json_extract(json_value, '$._id') = 'jn7aq2647e6g69qbrg7q9n6aas7sxqje'; +``` + +### 4.3. Sanear dados incompatíveis + +1. **Cron legado** + ```sql + DELETE FROM documents + WHERE hex(table_id) = 'C24DDDBFBA00025744D7672E2AC74F91' + AND json_extract(json_value, '$.name') = 'hours-usage-alerts-hourly'; + ``` +2. **Máquina fora do shape** + - Remover índices ligados ao documento: + ```sql + DELETE FROM indexes WHERE document_id = X'AB88C43B8D0326EBC40F74D4CA564F9E'; + ``` + - Remover o documento em si: + ```sql + DELETE FROM documents WHERE id = X'AB88C43B8D0326EBC40F74D4CA564F9E'; + ``` +3. (Opcional) Qualquer export/cron adicional pode ser limpado usando o mesmo padrão: `DELETE` na tabela `documents` e correspondentes em `indexes`. + +### 4.4. Subir o backend e validar + +```bash +docker service scale sistema_convex_backend=1 +docker service logs --tail 400 -f sistema_convex_backend +``` + +Critérios de sucesso: + +- Logs mostram `application::exports::worker ... completed` e, logo após, `No exports requested or in progress`. +- Não existem novas linhas `Caught error`/`shape_inference`. +- WebSocket `/api/1.29.2/sync` volta a responder **101 Switching Protocols**. + +--- + +## 5. Pós-incidente / Prevenção + +1. **Desabilitar jobs pesados por padrão:** já deixamos `REPORTS_CRON_ENABLED=false` e `AUTO_PAUSE_ENABLED=false` nas variáveis. Mantê-las assim até que o Convex publique um fix oficial. +2. **Sempre limpar exports antigos antes de alterar schema:** se um export for rodado manualmente, aguardá-lo completar antes de editar tabelas grandes (`machines`, `ticketWorkSessions` etc.). +3. **Monitorar logs após deploys:** `docker service logs sistema_convex_backend | rg exports::worker` ajuda a verificar se há novos exports presos. +4. **Documentar qualquer alteração direta no SQLite:** registrar no repositório (neste arquivo) os comandos executados, garantindo um histórico completo. + +--- + +## 6. Referências rápidas + +- Volume Convex: `sistema_convex_data` +- Banco: `/convex/data/db.sqlite3` +- Contêiner SQLite: `nouchka/sqlite3` +- Parar/Subir serviço: `docker service scale sistema_convex_backend=0|1` +- Arquivo anterior de referência: `/convex/data/db.sqlite3.pre-export-clean-20251118123551` + +--- + +Última revisão: **18/11/2025** — sanado por remoção dos registros incompatíveis e rerun bem-sucedido do export `gg20vw5b479d9a2jprjpe3pxg57vk9wa`.