Reescrita completa das secoes 10-13 do OPERATIONS.md: - Secao 10: Historico completo do problema de memoria OOM - Cronologia do problema (Nov/2025 ate 10/12/2025) - Causa raiz identificada (versoes de documentos em memoria) - Solucao em 3 partes: crons, limpeza, codigo do heartbeat - Resultados: 450MB -> 17MB banco, 19GB -> 395MB memoria - Secao 11: Erros shape_inference marcados como RESOLVIDOS - Problema eliminado pela limpeza do banco - Crons movidos = nenhum novo registro problematico - Secao 12: Arquitetura final dos crons - Diagrama da nova arquitetura (Linux crontab -> Next.js -> Convex) - Mapeamento completo dos crons migrados - Configuracao atual do crontab na VPS - Secao 13 (NOVA): Guia de monitoramento pos-correcao - Metricas esperadas para sistema saudavel - Comandos de verificacao - Procedimento de limpeza (se necessario) - Resumo de commits e backups disponiveis 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
25 KiB
Operações — Sistema de Chamados (Prod)
Este documento consolida as mudanças recentes, o racional por trás delas e o procedimento de operação/deploy (Web e Convex self‑hosted) do ambiente em produção.
1) Mudanças Funcionais (Front + Server)
-
Empresas (admin)
- “Slug” renomeado para “Apelido” (mensagens e placeholders ajustados).
-
Fila padrão ao criar tickets
- Todo novo ticket entra na fila “Chamados”.
- Implementado no backend (fallback) e pré‑seleção na UI.
-
Status de tickets e interações
- Nomes/cores atualizados:
- Pendente (cinza), Em andamento (azul), Pausado (amarelo), Resolvido (verde).
- Transições automáticas:
- Iniciar (play) → status “Em andamento”.
- Pausar → status “Pausado”.
- “Encerrar” permanece manual. O dropdown foi substituído por badge + botão “Encerrar”.
- Diálogo de encerramento: botão “Cancelar” adicionado (além de “Limpar mensagem”/“Encerrar ticket”).
- Nomes/cores atualizados:
-
Dashboard — Últimos chamados
- Prioridade: sem responsável primeiro (dos mais antigos para os mais recentes), depois demais chamados.
-
Filtros de tickets
- Filtro por “Responsável” (agente/admin) adicionado.
- Salvar filtro como padrão por usuário (localStorage) + “Limpar padrão”.
- Empresas no filtro: lista completa via API admin (não só empresas presentes em tickets).
- Produção: filtro “Responsável” agora é feito no servidor (assigneeId); o front não envia mais parâmetros inválidos.
-
Editor de comentários (Tiptap)
- Correção: reativar edição quando um responsável é atribuído (o editor agora reflete mudanças em
disabledviasetEditable).
- Correção: reativar edição quando um responsável é atribuído (o editor agora reflete mudanças em
2) Convex (Self‑Hosted) — Ajustes e Motivo
-
Problema observado: deploy do Convex falhava no CI por:
- Ausência de
convex.json(link do projeto) no servidor. - Uso incorreto de
CONVEX_DEPLOYMENTjunto aCONVEX_SELF_HOSTED_URL+CONVEX_SELF_HOSTED_ADMIN_KEY(não suportado pelo CLI ao usar self‑hosted). - Divergência de schema (campo
provisioningCodejá existente nos dados, mas ausente no schema do Convex no servidor).
- Ausência de
-
Medidas aplicadas:
- Atualização do schema do Convex no servidor: inclusão de
provisioningCode?: stringna tabelacompanies(e índice opcionalby_provisioning_code). - Criação do link de projeto (
convex.json) no servidor via wizard do CLI (ver Passo a passo abaixo). - Ajustes no workflow do GitHub Actions para self‑hosted:
- Adicionado passo “Acquire Convex admin key” no job de deploy do Convex.
- Removido
CONVEX_DEPLOYMENTquandoCONVEX_SELF_HOSTED_URL+CONVEX_SELF_HOSTED_ADMIN_KEYestão definidos. - Cópia automática do
convex.jsonde/srv/apps/sistemapara o diretório de build temporário.
- Forçar redeploy das funções: tocar arquivos sob
convex/**para acionar o filtro do job “Deploy Convex functions”.
- Atualização do schema do Convex no servidor: inclusão de
3) CI/CD — Visão Geral
- Pipeline “CI/CD Web + Desktop” (GitHub Actions)
- Job “Detect changes” usa filtros por paths.
- Job “Deploy (VPS Linux)” cuida do Web (Next.js) e stack do Swarm.
- Job “Deploy Convex functions” roda quando há mudanças em
convex/**ou viaworkflow_dispatch.- Passos relevantes:
- “Acquire Convex admin key” (via container
sistema_convex_backend). - “Bring convex.json from live app if present” (usa o arquivo de link do projeto em
/srv/apps/sistema). - “convex env list” e “convex deploy” com
CONVEX_SELF_HOSTED_URL+CONVEX_SELF_HOSTED_ADMIN_KEY.
- “Acquire Convex admin key” (via container
- Passos relevantes:
4) Troca de colaborador / reaproveitamento de dispositivo
Quando um computador muda de dono (ex.: João entrega o equipamento antigo para Maria e recebe uma dispositivo nova), siga este checklist para manter o inventário consistente:
-
No painel (Admin → Dispositivos)
- Abra os detalhes da dispositivo que será reaproveitada (ex.: a “amarela” que passará da TI/João para a Maria).
- Clique em Resetar agente. Isso revoga todos os tokens gerados para aquele equipamento; ele precisará ser reprovisionado antes de voltar a reportar dados.
- Abra Ajustar acesso e altere o e-mail para o do novo usuário (Maria). Assim, quando o agente se registrar novamente, o painel já mostrará a responsável correta.
-
Na dispositivo física que ficará com o novo colaborador
- Desinstale o desktop agent (Painel de Controle → remover programas).
- Instale novamente o desktop agent. Use o mesmo código da empresa/tenant e informe o e-mail do novo usuário (Maria). O backend emite um token novo e reaproveita o registro da dispositivo, mantendo o histórico.
-
Dispositivo nova para o colaborador antigo
- Instale o desktop agent do zero na dispositivo que o João vai usar (ex.: a “azul”). Utilize o mesmo código da empresa e o e-mail do João.
- A dispositivo azul aparecerá como um novo registro no painel (inventário/tickets começarão do zero). Renomeie/associe conforme necessário.
-
Verificação final
- A dispositivo antiga (amarela) continua listada, agora vinculada à Maria, com seus tickets históricos.
- A dispositivo nova (azul) aparece como um segundo registro para o João. Ajuste hostname/descrição para facilitar a identificação.
Não é necessário excluir registros. Cada dispositivo mantém seu histórico; o reset garante apenas que o token antigo não volte a sobrescrever dados quando o hardware mudar de mãos. - Importante: não usar
CONVEX_DEPLOYMENTem conjunto com URL + ADMIN_KEY.
- Como forçar o deploy do Convex
- Faça uma alteração mínima em
convex/**(ex.: comentário emconvex/tickets.ts) ou rode o workflow em “Run workflow” (workflow_dispatch).
- Faça uma alteração mínima em
4) Convex — Provisionamento inicial (self‑hosted)
Executar apenas 1x na VPS para criar o link do projeto (convex.json):
cd /srv/apps/sistema
export CONVEX_SELF_HOSTED_URL="https://convex.esdrasrenan.com.br"
CID=$(docker ps --format '{{.ID}} {{.Names}}' | awk '/sistema_convex_backend/{print $1; exit}')
export CONVEX_SELF_HOSTED_ADMIN_KEY="$(docker exec -i "$CID" /bin/sh -lc './generate_admin_key.sh' | tr -d '\r' | grep -o 'convex-self-hosted|[^ ]*' | tail -n1)"
npx convex dev --once --configure=new
# Siga o wizard (self-hosted) e vincule/crie o projeto/deployment (ex.: "sistema" / "default").
# Isso gera /srv/apps/sistema/convex.json
Depois disso, o job “Deploy Convex functions” funciona em modo não interativo.
5) VPS — Acesso e Servicos
-
Acesso
- Host:
154.12.253.40 - Usuario:
root - Chave SSH (repo raiz):
./codex_ed25519(Atencao: manter permissoes 600)- Exemplo (Git Bash/Linux):
# Preparar chave (copiar e ajustar permissoes) cp "./codex_ed25519" ~/.ssh/codex_ed25519 sed -i 's/\r$//' ~/.ssh/codex_ed25519 chmod 600 ~/.ssh/codex_ed25519 # Conectar ssh -i ~/.ssh/codex_ed25519 root@154.12.253.40
- Exemplo (Git Bash/Linux):
- Opcional (endurecimento): desabilitar login por senha após validar a chave.
- Host:
-
Diretórios principais
- Código do app:
/srv/apps/sistema - Arquivo do projeto Convex:
/srv/apps/sistema/convex.json - Stack do Swarm:
stack.yml(no repositório; aplicado no servidor via CI).
- Código do app:
-
Serviços (Docker Swarm + Traefik)
- Web (Next.js): serviço
sistema_web, exposto emtickets.esdrasrenan.com.br. - Convex backend: serviço
sistema_convex_backend, exposto emconvex.esdrasrenan.com.br. - Convex dashboard:
convex-admin.esdrasrenan.com.br. - Comandos úteis:
docker service lsdocker service ps sistema_webdocker service update --force sistema_web(reiniciar)docker service update --force sistema_convex_backend(reiniciar Convex)
- Web (Next.js): serviço
-
Convex admin key (diagnóstico)
docker exec -i $(docker ps | awk '/sistema_convex_backend/{print $1; exit}') /bin/sh -lc './generate_admin_key.sh'- Usada no CI para
convex env listeconvex deploy.
6) Notas de Segurança
- A chave privada
codex_ed25519está na raiz do repo (ambiente atual). Em produção, recomenda‑se:- Remover a chave do repositório ou armazená‑la em Secrets/Deploy keys do provedor.
- Desabilitar login por senha no SSH (apenas chave).
- Manter permissões:
chmod 600 ./codex_ed25519.
7) Testes, Build e Lint
-
Local
bun run build:bun(Next + typecheck)bun run lintbun test
-
CI garante build, lint e testes antes do deploy.
8) Troubleshooting Rápido
-
“No CONVEX_DEPLOYMENT set” durante o deploy do Convex
- Certifique‑se de que
/srv/apps/sistema/convex.jsonexiste (rodar wizardnpx convex dev --once --configure=new). - Não usar
CONVEX_DEPLOYMENTcomCONVEX_SELF_HOSTED_URL+CONVEX_SELF_HOSTED_ADMIN_KEY.
- Certifique‑se de que
-
Login quebrando com erro de
better_sqlite3(NODE_MODULE_VERSION)- Sintoma: HTTP 500 em
/api/auth/sign-in/emaile logs dosistema_webcom “Could not locate the bindings file” ou “compiled against NODE_MODULE_VERSION 115”. - Causa: o
better-sqlite3precisa ser recompilado para a versão de Node em uso (rodamos Node 22 dentro do container). - Correção (uma vez, após trocar versão de Node/Bun ou limpar
node_modules):
Isso grava o binário emdocker run --rm -v /apps/sistema:/app sistema_web:node22-bun \ bash -lc "cd /app && npm rebuild better-sqlite3" docker service update --force sistema_web/apps/sistema/node_modules/.bun/better-sqlite3@11.10.0/...(path montado pelo serviço). - Flags no serviço (stack.yml):
SKIP_APT_BOOTSTRAP=trueevita apt-get no boot (imagem já tem toolchain).SKIP_SQLITE_REBUILD=truedeixa o boot rápido; deixe comotruedepois de recompilar manualmente como acima.
- Sintoma: HTTP 500 em
-
“Schema validation failed” (campo extra
provisioningCode)- Atualize o schema do Convex no servidor para incluir
provisioningCode?: stringemcompanies. - Refaça o deploy.
- Atualize o schema do Convex no servidor para incluir
-
Filtro “Responsável” não funciona
- Front envia
assigneeIde o backend Convex deve aceitar esse parâmetro (funçãotickets.list). - Se necessário, forçar redeploy das funções (
convex/**).
- Front envia
-
Admin ▸ Dispositivos travado em skeleton infinito
- Abra o DevTools (console) e filtre por
admin-machine-details. Se o log mostrarmachineId: undefined, o componente não recebeu o parâmetro da rota. - Verifique se o
page.tsxestá passandoparams.idcorretamente ou se o componente client-side usauseParams()/machineIdopcional. - Deploys antigos antes de
fix(machines): derive machine id from router paramsprecisam desse patch; sem ele o fallback nunca dispara e o skeleton permanece.
- Abra o DevTools (console) e filtre por
-
Export do Convex em loop (
application::exports::worker)- Sintoma: WebSocket
1006, logs comCaught error ... shape_inference,Export <id> beginning...repetindo. - Solução completa documentada em
docs/convex-export-worker-loop.md(backup do SQLite, limpeza dos registros defeituosos e rerun do export).
- Sintoma: WebSocket
Última atualização: sincronizado após o deploy bem‑sucedido do Convex e do Front (20/10/2025).
9) Admin ▸ Usuários e Dispositivos — Unificação e UX
Resumo das mudanças aplicadas no painel administrativo para simplificar “Usuários” e “Agentes de dispositivo” e melhorar o filtro em Dispositivos:
-
Unificação de “Usuários” e “Agentes de dispositivo”
- Antes: abas separadas “Usuários” (pessoas) e “Agentes de dispositivo”.
- Agora: uma só aba “Usuários” com filtro de tipo (Todos | Pessoas | Dispositivos).
- Onde:
src/components/admin/admin-users-manager.tsx:923, abavalue="users"em:1147. - Motivo: evitar confusão entre “usuário” e “agente”; agentes são um tipo especial de usuário (role=machine). A unificação torna “Convites e Acessos” mais direta.
-
Dispositivos ▸ Filtro por Empresa com busca e remoção do filtro de SO
- Adicionado dropdown de “Empresa” com busca (Popover + Input) e removido o filtro por Sistema Operacional.
- Onde:
src/components/admin/devices/admin-devices-overview.tsx:1038e:1084. - Motivo: fluxo real usa empresas com mais frequência; filtro por SO era menos útil agora.
-
Windows ▸ Rótulo do sistema sem duplicidade do “major”
- Exemplo: “Windows 11 Pro (26100)” em vez de “Windows 11 Pro 11 (26100)”.
- Onde:
src/components/admin/devices/admin-devices-overview.tsx(funçãoformatOsVersionDisplay). - Motivo: legibilidade e padronização em chips/cartões.
-
Vínculos visuais entre dispositivos e pessoas
- Cards de dispositivos mostram “Usuário vinculado” quando disponível (assignment/metadata):
src/components/admin/devices/admin-devices-overview.tsx:3198. - Editor de usuário exibe “Dispositivos vinculadas” (derivado de assign/metadata):
src/components/admin/admin-users-manager.tsx(seção “Dispositivos vinculadas” no sheet de edição). - Observação: por ora é leitura; ajustes detalhados de vínculo permanecem em Admin ▸ Dispositivos.
- Cards de dispositivos mostram “Usuário vinculado” quando disponível (assignment/metadata):
Identidade, e‑mail e histórico (reinstalação)
- Identificador imutável: o histórico (tickets, eventos) referencia o
userId(imutável). O e‑mail é um atributo mutável. - Reinstalação do desktop para o mesmo colaborador: reutilize a mesma conta de usuário (mesmo
userId); se o e‑mail mudou, atualize o e‑mail dessa conta no painel. O histórico permanece, pois ouserIdnão muda. - Novo e‑mail como nova conta: se criar um usuário novo (novo
userId), será considerado um colaborador distinto e não herdará o histórico. - Caso precise migrar histórico entre contas diferentes (merge), recomendamos endpoint/rotina de “fusão de contas” (remapear
userIdantigo → novo). Não é necessário para a troca de e‑mail da mesma conta.
Vínculos múltiplos de usuários por dispositivo (Fase 2)
- Estrutura (Convex):
machines.linkedUserIds: Id<"users">[]— lista de vínculos adicionais além doassignedUserId(principal).- Mutations:
machines.linkUser(machineId, email),machines.unlinkUser(machineId, userId). - APIs admin:
POST /api/admin/devices/links(body:{ machineId, email }),DELETE /api/admin/devices/links?machineId=..&userId=...
- UI:
- Detalhes da dispositivo mostram “Usuários vinculados” com remoção por item e campo para adicionar por e‑mail.
- Editor de usuário mostra “Dispositivos vinculadas” consolidando assignment, metadata e
linkedUserIds.
- Racional: permitir que uma dispositivo tenha mais de um colaborador/gestor associado, mantendo um “principal” (persona) para políticas e contexto.
Onde editar
- Usuários (pessoas): editar nome, e‑mail, papel, tenant e empresa; redefinir senha pelo painel. Arquivo:
src/components/admin/admin-users-manager.tsx. - Agentes (dispositivos): provisionamento automático; edição detalhada/vínculo principal em Admin ▸ Dispositivos. Arquivo:
src/components/admin/devices/admin-devices-overview.tsx.
Observação operacional: mantivemos o provisionamento de dispositivos inalterado (token/e‑mail técnico), e o acesso web segue apenas para pessoas. A unificação é de UX/gestão.
10) Convex Self-Hosted — Problema de Memoria OOM (Historico Completo)
STATUS: RESOLVIDO DEFINITIVAMENTE em 10/12/2025
Cronologia do Problema
| Data | Evento | Memoria |
|---|---|---|
| Nov/2025 | Problema detectado - exports em loop | ~10GB |
| 09/12/2025 | Tentativa 1: separar heartbeats em tabela dedicada | ~8GB |
| 10/12/2025 | 12 OOM kills em 12 horas | 19-20GB (limite) |
| 10/12/2025 | Solucao definitiva aplicada | 395MB |
Causa Raiz Identificada (10/12/2025)
O Convex self-hosted carrega TODAS as versoes de TODOS os documentos em memoria (SQLite in-memory para OCC - Optimistic Concurrency Control). Isso significa:
- Cada
patch()cria uma nova versao do documento (nao substitui) - Versoes antigas permanecem no banco e na memoria
- Heartbeats a cada 5 min com inventory de ~92KB por maquina
- 6 maquinas x 288 heartbeats/dia = 1.728 versoes/dia
- Banco de 450MB expandia para 19GB+ em RAM (~42x)
Solucao Definitiva (10/12/2025)
Parte 1: Mover Crons para Linux (evitar acumulo de _scheduled_job_logs)
# Crons do Convex COMENTADOS em convex/crons.ts
# Substituidos por endpoints HTTP + crontab Linux
Ver secao 12 para detalhes.
Parte 2: Limpeza Manual do Banco (remover versoes antigas)
# 1. Parar Convex
docker service scale sistema_convex_backend=0
# 2. Backup
cd /var/lib/docker/volumes/sistema_convex_data/_data
cp db.sqlite3 db.sqlite3.backup-$(date +%Y%m%d-%H%M%S)
# 3. Limpar versoes antigas (manter apenas a mais recente de cada documento)
sqlite3 db.sqlite3 "DELETE FROM documents WHERE (id, ts) NOT IN (SELECT id, MAX(ts) FROM documents GROUP BY id);"
# 4. Compactar banco
sqlite3 db.sqlite3 "VACUUM;"
# 5. Reiniciar
docker service scale sistema_convex_backend=1
Parte 3: Corrigir Codigo do Heartbeat (evitar novas versoes desnecessarias)
Arquivo: convex/machines.ts (linhas 857-895)
Problema: O codigo original adicionava inventory/metrics ao patch se eles EXISTIAM, nao se MUDARAM:
// ANTES (criava versao mesmo com dados identicos)
if (args.inventory) {
metadataPatch.inventory = mergeInventory(...)
}
Solucao: Comparar dados antes de incluir no patch:
// DEPOIS (so cria versao se dados MUDARAM)
if (args.inventory && typeof args.inventory === "object") {
const currentInventory = currentMetadata.inventory
const newInventoryStr = JSON.stringify(args.inventory)
const currentInventoryStr = JSON.stringify(currentInventory ?? {})
if (newInventoryStr !== currentInventoryStr) {
metadataPatch.inventory = mergeInventory(currentInventory, args.inventory)
}
}
Resultado Final
| Metrica | ANTES (10/12 08:00) | DEPOIS (10/12 14:30) | Reducao |
|---|---|---|---|
| Banco SQLite | 450MB | 17MB | 96% |
| Memoria Convex | 19GB+ (OOM) | 395MB | 98% |
| RAM livre servidor | 404MB | 15GB | +15GB |
| Registros no banco | 56.247 | 21.001 | -63% |
| OOM kills/dia | 12+ | 0 | -100% |
Por que a Solucao Funciona
- Crons movidos: Zero novos registros em
_scheduled_job_logs - Versoes antigas removidas: Banco limpo, sem historico desnecessario
- Codigo corrigido: Heartbeats com dados identicos = 0 versoes novas
Estimativa de crescimento futuro:
- Antes: ~1.728 versoes/dia (6 maquinas x 288 heartbeats)
- Depois: ~30 versoes/dia (so quando inventory/metrics MUDA de verdade)
- Reducao de 98% no crescimento do banco
11) Convex Self-Hosted — Erros de shape_inference (RESOLVIDO)
STATUS: RESOLVIDO em 10/12/2025 pela limpeza do banco
Problema Original
O Convex usa shape inference para otimizar queries. Quando documentos da mesma tabela tem campos com tipos incompativeis, o sistema falha.
Causa: A tabela _scheduled_job_logs tinha registros com:
logLines: [](Array)logLines: ["mensagem"](Array)
O shape inference nao consegue unificar esses tipos.
Solucao Aplicada
A limpeza completa do banco (secao 10, Parte 2) removeu todos os registros problematicos:
-- Isso removeu 4.227 registros de _scheduled_job_logs
DELETE FROM documents WHERE (id, ts) NOT IN (SELECT id, MAX(ts) FROM documents GROUP BY id);
Status Atual
- Zero erros de shape_inference nos logs desde 10/12/2025
- Crons movidos para Linux = nenhum novo registro em
_scheduled_job_logs - Problema nao deve recorrer com a arquitetura atual
Nota Historica
Os console.log() adicionados em 09/12/2025 nos handlers de cron (para garantir logLines nao vazio) nao sao mais necessarios pois os crons foram movidos para Linux. Porem, foram mantidos no codigo por seguranca caso os crons sejam reativados no futuro.
12) Cron Jobs — Arquitetura Final
STATUS: MIGRADO para Linux crontab em 10/12/2025
Por que Migrar
Os cron jobs do Convex criam registros em _scheduled_job_logs que:
- Acumulam versoes em memoria (nunca sao removidos automaticamente)
- Cron de 1 minuto = 1.440 registros/dia = 43.200/mes
- Cada registro ocupa espaco no SQLite in-memory
Arquitetura Atual
┌─────────────────┐ ┌──────────────────────┐ ┌─────────────────┐
│ Linux crontab │────▶│ Next.js API Route │────▶│ Convex Mutation│
│ (VPS) │ │ /api/cron/* │ │ (funcao real) │
└─────────────────┘ └──────────────────────┘ └─────────────────┘
│ │
│ curl a cada X min │ ConvexHttpClient
▼ ▼
Nao cria logs Executa a logica
no Convex sem criar _scheduled_job_logs
Mapeamento de Crons
| Funcao Original | Endpoint HTTP | Frequencia | Status |
|---|---|---|---|
auto-end-inactive-chat-sessions |
/api/cron/chat-cleanup |
1 min | ATIVO |
cleanup-stale-usb-policies |
/api/cron/usb-cleanup |
30 min | ATIVO |
report-export-runner |
- | 15 min | DESABILITADO (flag) |
auto-pause-internal-lunch |
- | diario | DESABILITADO (flag) |
Configuracao na VPS
# Crontab atual (root@154.12.253.40)
CRON_SECRET="reports-cron-938fa2e0f663b43bb43203413783d6415e6d0cdfb58c25a749b4c90241c4017b"
# Chat cleanup - a cada minuto
* * * * * curl -s "https://tickets.esdrasrenan.com.br/api/cron/chat-cleanup" -H "x-cron-secret: $CRON_SECRET" >/dev/null 2>&1
# USB policy cleanup - a cada 30 minutos
*/30 * * * * curl -s "https://tickets.esdrasrenan.com.br/api/cron/usb-cleanup" -H "x-cron-secret: $CRON_SECRET" >/dev/null 2>&1
Arquivos Relacionados
src/app/api/cron/chat-cleanup/route.ts- Endpoint para encerrar chats inativossrc/app/api/cron/usb-cleanup/route.ts- Endpoint para limpar policies USBconvex/crons.ts- Crons originais (COMENTADOS, mantidos para referencia)
13) Monitoramento e Manutencao — Guia Pos-Correcao (10/12/2025)
Status Esperado (Sistema Saudavel)
| Metrica | Valor Esperado | Alerta Se |
|---|---|---|
| Memoria Convex | < 1GB | > 5GB |
| Banco SQLite | < 50MB | > 200MB |
| OOM kills/dia | 0 | > 0 |
| Erros shape_inference | 0 | > 0 |
Comandos de Verificacao
# Verificar memoria do Convex
ssh -i ~/.ssh/codex_ed25519 root@154.12.253.40 \
"docker stats --no-stream --format 'table {{.Name}}\t{{.MemUsage}}\t{{.MemPerc}}' | grep convex"
# Verificar tamanho do banco
ssh -i ~/.ssh/codex_ed25519 root@154.12.253.40 \
"ls -lh /var/lib/docker/volumes/sistema_convex_data/_data/db.sqlite3"
# Verificar OOM kills (desde meia-noite)
ssh -i ~/.ssh/codex_ed25519 root@154.12.253.40 \
"journalctl --since '00:00:00' -k | grep -c 'Killed process.*convex'"
# Verificar erros nos logs
ssh -i ~/.ssh/codex_ed25519 root@154.12.253.40 \
"docker service logs sistema_convex_backend --tail 50 2>&1 | grep -E 'ERROR|shape_inference'"
Quando Fazer Limpeza Manual
NAO e necessario fazer limpeza periodica com a correcao de codigo aplicada. O sistema deve se manter estavel indefinidamente.
Fazer limpeza manual apenas se:
- Banco SQLite ultrapassar 200MB
- Memoria Convex ultrapassar 5GB
- Ocorrerem OOM kills
Procedimento de Limpeza (Se Necessario)
# 1. Verificar estado atual
ssh root@154.12.253.40 "ls -lh /var/lib/docker/volumes/sistema_convex_data/_data/db.sqlite3"
# 2. Se > 200MB, fazer limpeza:
ssh root@154.12.253.40 << 'EOF'
docker service scale sistema_convex_backend=0
cd /var/lib/docker/volumes/sistema_convex_data/_data
cp db.sqlite3 db.sqlite3.backup-$(date +%Y%m%d-%H%M%S)
sqlite3 db.sqlite3 "DELETE FROM documents WHERE (id, ts) NOT IN (SELECT id, MAX(ts) FROM documents GROUP BY id); VACUUM;"
docker service scale sistema_convex_backend=1
EOF
Resumo das Correcoes Aplicadas
| Problema | Solucao | Arquivo | Commit |
|---|---|---|---|
| Crons acumulando logs | Mover para Linux crontab | convex/crons.ts, src/app/api/cron/* |
178c7d7 |
| Heartbeat criando versoes | Comparar dados antes de patch | convex/machines.ts:857-895 |
b6f69d7 |
| Versoes antigas no banco | Limpeza manual + VACUUM | N/A (operacao manual) | N/A |
Backups Disponiveis (VPS)
/var/lib/docker/volumes/sistema_convex_data/_data/
├── db.sqlite3 17MB (atual, limpo)
├── db.sqlite3.backup-20251210-084225 452MB (antes dos crons)
├── db.sqlite3.backup-pre-cleanup-20251210-100336 450MB (antes da limpeza final)
├── db.sqlite3.backup-20251209-234720 447MB (09/12)
└── db.sqlite3.pre-vacuum-20251209 449MB (antes do primeiro vacuum)
Ultima atualizacao: 10/12/2025 — Problema de OOM resolvido definitivamente. Sistema estavel com 395MB de memoria (1.93% do limite de 20GB)