-
Notifications
You must be signed in to change notification settings - Fork 0
docs(session-2026-05-12): audit types drift + backup procedures + DBA session report #130
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d47fa32
c07f097
838d89d
d18c547
3b0bb1f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| # Backups Supabase Self-Hosted — Documentação | ||
|
|
||
| Última atualização: 2026-05-12 — testado e validado. | ||
|
|
||
| ## Estrutura no container `supabase-backup_backup` | ||
|
|
||
| ``` | ||
| /backups/ | ||
| ├── supabase_selfhosted_YYYYMMDD_HHMMSS.dump # backup oficial automático | ||
| ├── supabase_selfhosted_YYYYMMDD_HHMMSS.dump.sha256 | ||
| ├── archive/ # históricos pré-migração (não tocar) | ||
| ├── manual/ # snapshots manuais pré-mudança | ||
| ├── restore-test.sh # ← este script (deploy de docs/backups/) | ||
| ├── restore-test.log | ||
| └── last_error.log | ||
| ``` | ||
|
|
||
| ## Configuração atual do backup automático | ||
|
|
||
| | Variável | Valor | Significado | | ||
| |---|---|---| | ||
| | PGHOST | supabase_db | Host alvo (container interno) | | ||
| | PGUSER | supabase_admin | Usuário com acesso a tudo | | ||
| | PGDATABASE | postgres | BD principal | | ||
| | RETENTION_DAYS | 14 | Manter 14 dias | | ||
| | MIN_SIZE_BYTES | 104857600 (100 MB) | Backup menor = REJEITADO | | ||
| | Formato | --format=custom | Permite restore parcial | | ||
| | Compressão | --compress=6 | Bom tradeoff tamanho/CPU | | ||
| | Frequência | 24h (sleep 86400) | Diário | | ||
|
|
||
| ## Disaster Recovery — procedure VALIDADO em 2026-05-12 | ||
|
|
||
| IMPORTANTE: o dump contém a extensão pg_cron que SÓ roda no BD chamado 'postgres'. | ||
| Filtrar antes de restaurar em BD com outro nome. | ||
|
|
||
| ```bash | ||
| # 1. Acessar o container de backup | ||
| docker exec -it $(docker ps -qf name=supabase-backup_backup) sh | ||
|
|
||
|
Comment on lines
+38
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Comandos de Nos Lines [38], [87] e [89], o filtro sem âncora pode retornar múltiplos IDs e quebrar Diff sugerido-docker exec -it $(docker ps -qf name=supabase-backup_backup) sh
+docker exec -it $(docker ps -q --filter "name=^/supabase-backup_backup$") sh
@@
-docker cp docs/backups/restore-test.sh \
- $(docker ps -qf name=supabase-backup_backup):/backups/restore-test.sh
+docker cp docs/backups/restore-test.sh \
+ $(docker ps -q --filter "name=^/supabase-backup_backup$"):/backups/restore-test.sh
@@
-docker exec $(docker ps -qf name=supabase-backup_backup) \
+docker exec $(docker ps -q --filter "name=^/supabase-backup_backup$") \
chmod +x /backups/restore-test.shAlso applies to: 86-90 🤖 Prompt for AI Agents |
||
| # 2. Validar checksum | ||
| cd /backups | ||
| sha256sum -c supabase_selfhosted_YYYYMMDD_HHMMSS.dump.sha256 | ||
|
|
||
| # 3. Criar BD destino | ||
| psql -c "CREATE DATABASE restore_test;" | ||
|
|
||
| # 4. Gerar TOC e filtrar pg_cron | ||
| pg_restore -l /backups/supabase_selfhosted_YYYYMMDD_HHMMSS.dump > /tmp/toc.list | ||
| grep -Ev '(pg_cron|cron\.)' /tmp/toc.list > /tmp/toc.filtered | ||
|
|
||
| # 5. Restore (tempo médio: 2 minutos) | ||
| pg_restore -d restore_test --no-owner --no-acl \ | ||
| --use-list=/tmp/toc.filtered --jobs=4 \ | ||
| /backups/supabase_selfhosted_YYYYMMDD_HHMMSS.dump | ||
|
|
||
| # 6. Validar contagens (esperado: 600+ tables, 17k+ contacts, 1.8M+ messages) | ||
| psql -d restore_test -c "SELECT count(*) FROM information_schema.tables WHERE table_schema='public';" | ||
| psql -d restore_test -c "SELECT count(*) FROM public.evolution_contacts;" | ||
| psql -d restore_test -c "SELECT count(*) FROM public.evolution_messages;" | ||
| ``` | ||
|
|
||
| ### Resultado do dry-run validado em 2026-05-12 19:54 UTC | ||
|
|
||
| | Métrica | Valor | | ||
| |---|---| | ||
| | Tempo de restore | 121s | | ||
| | Warnings ignorados | 23 (todos pg_cron-related, não-bloqueantes) | | ||
| | Tamanho restaurado | 1921 MB | | ||
| | Tabelas restauradas | 600 | | ||
| | evolution_contacts | 17.340 (match com produção) | | ||
| | evolution_messages | 1.838.351 (match) | | ||
| | profiles | 6 (match) | | ||
|
|
||
| ## Scripts neste diretório | ||
|
|
||
| - **`restore-test.sh`** — Script de teste de restore automatizado. Deve ser deployado | ||
| em `/backups/restore-test.sh` dentro do container `supabase-backup_backup`. | ||
| - **`install-restore-test-cron.sh`** — Helper que adiciona um cron mensal no HOST da | ||
| VPS para executar o restore-test via `docker exec`. Roda dia 1 de cada mês às | ||
| 04:00 UTC. | ||
|
|
||
| ## Deploy | ||
|
|
||
| ```bash | ||
| # 1. Copiar scripts para o container | ||
| docker cp docs/backups/restore-test.sh \ | ||
| $(docker ps -qf name=supabase-backup_backup):/backups/restore-test.sh | ||
|
|
||
| docker exec $(docker ps -qf name=supabase-backup_backup) \ | ||
| chmod +x /backups/restore-test.sh | ||
|
|
||
| # 2. Instalar cron no HOST (não no container) | ||
| bash docs/backups/install-restore-test-cron.sh | ||
| ``` | ||
|
|
||
| ## Pendências conhecidas | ||
|
|
||
| - [ ] **CRÍTICO**: Off-site backup (R2 Cloudflare). Atualmente SPOF — apenas local na VPS. | ||
| - Worker `backup-upload-r2.adm01.workers.dev` existe mas retorna 401 (secret incorreto). | ||
| - Script `/workspace/scripts/backup-to-r2.sh` no host falhando desde 04-mai-2026. | ||
| - Próximo passo: regenerar secret no Cloudflare Dashboard OU criar R2 API Token S3-compat. | ||
| - [ ] **ALTO**: Alerta de falha (webhook Slack/n8n se BACKUP_FAILED_* aparecer). | ||
| - [ ] **MÉDIO**: Validação periódica de checksum (cron `sha256sum -c`). | ||
| - [x] **MÉDIO**: Restore test agendado mensal — script pronto, cron documentado. | ||
|
|
||
| ## Histórico | ||
|
|
||
| - 2026-04-30 a 2026-05-04: backups FATOR X cloud (5 arquivos arquivados em `/backups/archive/`). | ||
| - 2026-05-05 a 2026-05-11: 7 backups quebrados (20 bytes cada, PGHOST apontando para | ||
| FATOR X que caiu). DELETADOS em 2026-05-12. | ||
| - 2026-05-12 10:32: primeiro backup self-hosted válido (606 MB). | ||
| - 2026-05-12 19:54: dry-run de restore validado em produção com sucesso (121s). | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| #!/bin/bash | ||
| # Instala cron pra rodar restore-test mensalmente | ||
| # Executa dentro do container supabase-backup_backup via docker exec | ||
| # Roda no HOST da VPS (não dentro do container) | ||
|
|
||
| set -e | ||
|
|
||
| BACKUP_CONTAINER="supabase-backup_backup" | ||
|
|
||
| # Pré-flight: o container precisa existir (e ser único) no momento da instalação. | ||
| # `docker ps -qf name=...` pode retornar múltiplos IDs com prefixo igual ou | ||
| # zero IDs — qualquer caso faria o cron falhar silenciosamente em produção. | ||
| RUNNING_IDS=$(docker ps -q --filter "name=^/${BACKUP_CONTAINER}$" || true) | ||
| if [ -z "$RUNNING_IDS" ]; then | ||
| echo "❌ Container ${BACKUP_CONTAINER} não está rodando." | ||
| echo " Inicie o Supabase Self-Hosted antes de instalar o cron." | ||
| exit 1 | ||
| fi | ||
| if [ "$(printf '%s\n' "$RUNNING_IDS" | wc -l)" -gt 1 ]; then | ||
| echo "❌ Mais de um container ${BACKUP_CONTAINER} rodando — abortando." | ||
| echo "$RUNNING_IDS" | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Comando a executar: usa o NOME exato do container (não filter por ID), | ||
| # para que o cron continue funcionando mesmo se o container reiniciar e | ||
| # obtiver outro ID. Falha clara se o container não existir naquele momento. | ||
| CRON_LINE="0 4 1 * * /usr/bin/docker exec ${BACKUP_CONTAINER} /backups/restore-test.sh >> /var/log/restore-test-cron.log 2>&1" | ||
|
|
||
|
Comment on lines
+8
to
+29
|
||
| # Verifica se já existe | ||
| if crontab -l 2>/dev/null | grep -qF 'restore-test.sh'; then | ||
| echo "✅ Cron já instalado:" | ||
| crontab -l | grep restore-test | ||
| exit 0 | ||
| fi | ||
|
Comment on lines
+30
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Validação de cron está ampla demais. No Line [31], buscar só por Diff sugerido-if crontab -l 2>/dev/null | grep -qF 'restore-test.sh'; then
+if crontab -l 2>/dev/null | grep -qF "$CRON_LINE"; then
echo "✅ Cron já instalado:"
- crontab -l | grep restore-test
+ crontab -l | grep -F "$CRON_LINE"
exit 0
fi🤖 Prompt for AI Agents |
||
|
|
||
| # Adiciona ao crontab | ||
| (crontab -l 2>/dev/null; echo "$CRON_LINE") | crontab - | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
With Useful? React with 👍 / 👎. |
||
| echo "✅ Cron instalado: roda dia 1 de cada mês às 04:00 UTC" | ||
| echo "$CRON_LINE" | ||
| echo "" | ||
| echo "Logs em /var/log/restore-test-cron.log (host) + /backups/restore-test.log (container)" | ||
| echo "Pra rodar agora manualmente:" | ||
| echo " docker exec ${BACKUP_CONTAINER} /backups/restore-test.sh" | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,126 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #!/bin/sh | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Restore test automatizado | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Roda mensalmente via cron (cron 0 4 1 * *) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Pega o backup mais recente, restaura em BD temporário, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # valida contagens, dropa, e loga resultado | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # DEPLOY: este script deve ser copiado para /backups/restore-test.sh | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # dentro do container supabase-backup_backup | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Validado em produção em 2026-05-12: PASSOU em 121s | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # - 600 tables restauradas | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # - 17.340 evolution_contacts (match) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # - 1.838.351 evolution_messages (match) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # - 1921 MB | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| set -e | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| LOG=/backups/restore-test.log | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Timestamp avaliado no momento de cada log line (não no startup), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # para que restores longos tenham logs com horário real de cada evento. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "[$(date -Iseconds)] $*" | tee -a "$LOG" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log "==================== RESTORE TEST INICIADO ====================" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 1. Identificar backup mais recente. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # `ls` com `set -e`: append `|| true` na substituição para que ausência | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # de match não derrube o script antes do check `[ -z "$LATEST" ]`. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| LATEST=$(ls -t /backups/supabase_selfhosted_*.dump 2>/dev/null | head -1 || true) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ -z "$LATEST" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log "ERRO: nenhum backup encontrado em /backups/supabase_selfhosted_*.dump" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| touch "/backups/RESTORE_TEST_FAILED_$(date +%Y%m%d_%H%M%S)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+16
to
+37
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log "Backup alvo: $LATEST ($(du -h "$LATEST" | cut -f1))" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 2. Validar SHA256 — subshell + if direto evita que `set -e` interrompa | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # antes do bloco de erro (caso `cd` falhe ou checksum não bater). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ -f "${LATEST}.sha256" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (cd /backups && sha256sum -c "$(basename "$LATEST").sha256" >/dev/null 2>&1); then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log "OK: SHA256 válido" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log "ERRO: SHA256 FALHOU - backup corrompido!" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| touch "/backups/RESTORE_TEST_FAILED_$(date +%Y%m%d_%H%M%S)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exit 2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
coderabbitai[bot] marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log "AVISO: sem arquivo .sha256 para validar" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 3. Criar BD temporário (identificador é seguro: composto só por timestamp). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DBNAME="restore_test_$(date +%Y%m%d_%H%M%S)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log "Criando BD temporário: $DBNAME" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+56
to
+58
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # DROP com FORCE (PG13+) termina conexões pendentes em vez de falhar. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Fallback para variante sem FORCE em PG<13: termina backends manualmente. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| psql -c "DROP DATABASE IF EXISTS \"$DBNAME\" WITH (FORCE);" >/dev/null 2>&1 \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| || { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| psql -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '$DBNAME' AND pid <> pg_backend_pid();" >/dev/null 2>&1 || true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| psql -c "DROP DATABASE IF EXISTS \"$DBNAME\";" >/dev/null 2>&1 || true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| psql -c "CREATE DATABASE \"$DBNAME\";" >/dev/null 2>&1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 4. Gerar TOC filtrada (sem pg_cron que requer BD chamado postgres). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # `grep -E` com alternação `|` é portável; o antigo `grep -v 'pg_cron\|cron\.'` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # depende de extensão GNU e silenciosamente passa pg_cron em outros greps. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pg_restore -l "$LATEST" > "/tmp/toc-${DBNAME}.list" 2>/dev/null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| grep -Ev '(pg_cron|cron\.)' "/tmp/toc-${DBNAME}.list" > "/tmp/toc-${DBNAME}.filtered" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+71
to
+72
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
After creating the temporary database, Useful? React with 👍 / 👎. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+55
to
+73
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Falta cleanup garantido em falhas intermediárias com Se falhar antes da etapa final, o banco temporário e TOCs podem ficar órfãos. Coloque cleanup em Diff sugerido set -e
LOG=/backups/restore-test.log
+DBNAME=""
+TOC_LIST=""
+TOC_FILTERED=""
+
+cleanup() {
+ if [ -n "$DBNAME" ]; then
+ psql -c "DROP DATABASE IF EXISTS \"$DBNAME\" WITH (FORCE);" >/dev/null 2>&1 \
+ || psql -c "DROP DATABASE IF EXISTS \"$DBNAME\";" >/dev/null 2>&1 \
+ || true
+ fi
+ [ -n "$TOC_LIST" ] && rm -f "$TOC_LIST" "$TOC_FILTERED"
+}
+trap cleanup EXIT
@@
DBNAME="restore_test_$(date +%Y%m%d_%H%M%S)"
@@
-pg_restore -l "$LATEST" > "/tmp/toc-${DBNAME}.list" 2>/dev/null
-grep -Ev '(pg_cron|cron\.)' "/tmp/toc-${DBNAME}.list" > "/tmp/toc-${DBNAME}.filtered"
+TOC_LIST="/tmp/toc-${DBNAME}.list"
+TOC_FILTERED="/tmp/toc-${DBNAME}.filtered"
+pg_restore -l "$LATEST" > "$TOC_LIST" 2>/dev/null
+grep -Ev '(pg_cron|cron\.)' "$TOC_LIST" > "$TOC_FILTERED"
@@
-# 8. Cleanup (idempotente — DROP IF EXISTS WITH FORCE limpa mesmo se algo
-# ficar pendente no BD temporário).
-log "Dropping BD temporário"
-psql -c "DROP DATABASE IF EXISTS \"$DBNAME\" WITH (FORCE);" >/dev/null 2>&1 \
- || psql -c "DROP DATABASE IF EXISTS \"$DBNAME\";" >/dev/null 2>&1 \
- || true
-rm -f "/tmp/toc-${DBNAME}.list" "/tmp/toc-${DBNAME}.filtered"
+# 8. Cleanup automático via trap EXIT.
+log "Cleanup automático finalizado"Also applies to: 118-124 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 5. Restore com tempo medido + captura de exit code real. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Antes `|| true` mascarava falhas/timeouts; agora RESTORE_OK entra como | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # primeira condição obrigatória no check de sucesso. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| START=$(date +%s) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log "Iniciando pg_restore (timeout 10min)..." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| RESTORE_OK=1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ! timeout 600 pg_restore -d "$DBNAME" --no-owner --no-acl \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --use-list="/tmp/toc-${DBNAME}.filtered" --jobs=4 \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "$LATEST" >> "$LOG" 2>&1; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| RESTORE_OK=0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log "ERRO: pg_restore falhou (exit != 0 ou timeout 600s atingido)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| END=$(date +%s) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DURATION=$((END - START)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log "Restore concluído em ${DURATION}s (RESTORE_OK=${RESTORE_OK})" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 6. Validar contagens chave | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TABLE_COUNT=$(psql -d "$DBNAME" -tAc "SELECT count(*) FROM information_schema.tables WHERE table_schema='public';" 2>/dev/null || echo "0") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CONTACTS=$(psql -d "$DBNAME" -tAc "SELECT count(*) FROM public.evolution_contacts;" 2>/dev/null || echo "0") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MESSAGES=$(psql -d "$DBNAME" -tAc "SELECT count(*) FROM public.evolution_messages;" 2>/dev/null || echo "0") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PROFILES=$(psql -d "$DBNAME" -tAc "SELECT count(*) FROM public.profiles;" 2>/dev/null || echo "0") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SIZE=$(psql -d "$DBNAME" -tAc "SELECT pg_size_pretty(pg_database_size('$DBNAME'));" 2>/dev/null || echo "unknown") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log "Resultado:" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log " - tables públicas: $TABLE_COUNT" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log " - evolution_contacts: $CONTACTS" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log " - evolution_messages: $MESSAGES" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log " - profiles: $PROFILES" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log " - tamanho restaurado: $SIZE" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 7. Avaliar sucesso. RESTORE_OK == 1 é condição obrigatória primeiro; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # thresholds são guard adicional contra restore parcial que sobe alguma | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # coisa mas não o suficiente para considerar válido. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ "$RESTORE_OK" -eq 1 ] && [ "$TABLE_COUNT" -ge 400 ] && [ "$CONTACTS" -ge 10000 ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log "✅ RESTORE TEST PASSOU" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| STATUS="PASSED" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log "❌ RESTORE TEST FALHOU - exit do pg_restore != 0 ou threshold não atingido" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| STATUS="FAILED" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| touch "/backups/RESTORE_TEST_FAILED_$(date +%Y%m%d_%H%M%S)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+113
to
+115
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When validation fails, this branch only logs and creates Useful? React with 👍 / 👎. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+106
to
+116
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Evite No Line [109], o sucesso exige só Diff sugerido-if [ "$RESTORE_OK" -eq 1 ] && [ "$TABLE_COUNT" -ge 400 ] && [ "$CONTACTS" -ge 10000 ]; then
+if [ "$RESTORE_OK" -eq 1 ] \
+ && [ "$TABLE_COUNT" -ge 400 ] \
+ && [ "$CONTACTS" -ge 10000 ] \
+ && [ "$MESSAGES" -ge 1000000 ] \
+ && [ "$PROFILES" -ge 1 ]; then📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 8. Cleanup (idempotente — DROP IF EXISTS WITH FORCE limpa mesmo se algo | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # ficar pendente no BD temporário). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log "Dropping BD temporário" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| psql -c "DROP DATABASE IF EXISTS \"$DBNAME\" WITH (FORCE);" >/dev/null 2>&1 \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| || psql -c "DROP DATABASE IF EXISTS \"$DBNAME\";" >/dev/null 2>&1 \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| || true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rm -f "/tmp/toc-${DBNAME}.list" "/tmp/toc-${DBNAME}.filtered" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log "==================== RESTORE TEST $STATUS ====================" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bloco de estrutura sem linguagem no fence (MD040).
Adicionar linguagem evita warning de lint.
Diff sugerido
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 7-7: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents