Hermes Insights — Sync Bug Fix (2026-06-26)
Bug Investigado: sync_v5.py — conversas não eram inseridas
Sessão: 20260625_202200_254284.jsonl (Rocha Sales #dev-relatorio)
Bugs Identificados
Bug 1: Newlines e pipes em nomes (CRÍTICO)
Causa: psql -At retorna uma linha por registro, mas nomes contendo \n ou | fazem o split quebrar.
Exemplo real:
`
Row 111 (chatwoot_id=115): nome = "~Leonardo Froese \n A Forja"
psql -At output (2 linhas em vez de 1):
"115|1|2|0|~Leonardo Froese "
" A Forja|+556**8205|..."
→ Python split("|") gera 14 colunas em vez de 13
→ Dados desalinhados → SQL语法错误
`
Dados afetados: Qualquer contato com nome/email contendo |, \n, ou caracteres especiais.
Bug 2: INSERT batch é UMA transação — rollback em cascata
Causa: INSERT INTO ... VALUES (...), (...), ...; é uma única transação.
Se QUALQUER row tem erro, TODAS as 200 rows fazem rollback.
Exemplo:
`
INSERT 0 100 ← Batch 1 succeeds
ERROR: syntax error at or near "," ← Batch 2 fails on row 111
→ PostgreSQL rolls back ENTIRE transaction
→ Resultado: 0 rows inserted (não 100, não 200)
`
Por que não aparecia erro? O sync_v5.py original verificava apenas if 'ERROR' in result, mas result vem de stdout que era vazio no erro. stderr era ignorado.
Soluções Aplicadas
1. Usar COPY ... TO STDOUT WITH (FORMAT CSV)
`python
Em vez de psql -At (split por |), usar:
cmd = f'''docker exec root-postgres-1 psql -U postgres -d chatwoot_production \\
-c "COPY ({full_query}) TO STDOUT WITH (FORMAT CSV, DELIMITER ',', NULL '\\\\N')"'''
CSV é escapado corretamente — newlines e pipes dentro de campos são citados
`
2. Batch menor (50 rows por INSERT)
`python
BATCH_SIZE = 50 # em vez de 200
Se 1 row falhar, no máximo 50 são perdidas (não 200)
`
3. Cada batch é transação independente
`python
Cada batch executa单独的 INSERT
Sucesso ou erro não afeta outros batches
`
4. Capturar stderr sempre
`python
def psql_insights(sql):
out, err = run_cmd(f'docker exec deploy-vps-db-1 psql -U postgres -d postgres -c "{sql}"')
if 'ERROR' in err:
print(f"SQL ERROR: {err}")
return out
`
Script Corrigido: sync_v6.py
Estrutura
- - Fetch:
COPY ... TO STDOUT WITH (FORMAT CSV)— evita problemas de newline/pipe - - Batch: 50 rows por INSERT (transação independente)
- - Escape: CSV quoting automático — não precisa manual
- - Progresso: offset 0, 50, 100, 150... até fim
- - [x] Bug identificado (newline + pipe em nomes)
- - [x] Bug identificado (rollback em cascata do batch)
- - [x] Solução: stdin pipe + batch menor
- - [x] Script v7 testado em produção ✅
- - [x] Full resync executado: 2042 conversas inseridas, 0 erros
- - [x] Script salvo em
/root/hermes-insights/sync_v7.py - - Causa:
psql -Atusa|como delimiter. Nomes como"~Leonardo Froese \n A Forja"geram 14 colunas em vez de 13. - - Solução:
psql -At -F "\t"usa tab como delimiter — tab não aparece em dados. - - Causa: 1 transação com 200 rows — se 1 falhar, todas são revertidas.
- - Solução: BATCH_SIZE = 50 + cada INSERT é transação independente.
- - Causa: Variável
agent_cw_idnão era passada parainsert_batch, fazendo o fallback INSERT falhar. - - Solução: Adicionado parâmetro
agent_cw_idna função. - - Problema: Não tratava
\N(NULL do CSV), newlines, backslashes. - - Solução: stdin pipe + tab delimiter elimina necessidade de escaping manual.
Mudanças vs v5
| Aspecto | v5 | v6 | |
| --------- | ---- | ---- | |
| Fetch | psql -At + split(\ | ) | COPY TO STDOUT WITH CSV + csv.reader |
| Batch size | 200 | 50 | |
| Transação | 1 por agente (todas ou nenhuma) | 1 por batch (independente) | |
| Escape | manual .replace("'","''") | CSV automático | |
| Erro captura | stdout apenas | stdout + stderr | |
| Agente | Chatwoot | Insights | |
| -------- | ---------- | ---------- | |
| Maria Giulha | 1676 | 2462* | |
| Rayca Soares | 191 | 191 | |
| Vinicius Sales | 106 | 106 | |
| Nayara | 62 | 62 | |
| Victoria | 7 | 7 | |
| Pietra Maniezzo | 1 | 1 | |
| Rafael William | 0 | 0 | |
| Raiany Cristina | 0 | 0 |
*Maria Giulha tem mais no Insights que no Chatwoot — Provavelmente是因为之前sync parcial deixou registros.
Bugsroot e Soluções
Bug 1: | como delimiter quebra em nomes
Bug 2: Batch INSERT faz rollback em cascata
Bug 3: agent_cw_id undefined na função insert_batch
Bug 4: Escape manual com .replace("'","''")
Comando para Rodar
`bash
python3 /root/hermes-insights/sync_v7.py
`
Salvo: 2026-06-26