Refator scripts/normalize.py::load_all_contracts para streaming #2

Open
opened 2026-04-30 04:04:16 -03:00 by navigator · 0 comments
Owner

Contexto

A função carrega 4,77M rows de contratos num único cursor.execute() + fetchall(). RSS Python explode no LXC de 8 GiB — em 2026-04-28 causou OOM-thrash com sshd/nginx/postgres ficando mudos por horas.

Reproduce

ssh root@soberaniadigital.org.br
sudo -u autonomia bash -c "cd /home/autonomia/soberaniadigital && .venv/bin/python scripts/normalize.py"
# observe RSS crescer e MemAvailable cair → kill antes de 1GB livre

Solução

  • Trocar fetchall() por server-side cursor: conn.cursor("named", withhold=False) + cur.itersize = 10000
  • Ou: converter generate_uniao_jsons, generate_estados_json, generate_municipios_json para SQL agregado (o que generate_dashboard_json já faz)
  • generate_municipios_json faz UPPER(unaccent(TRIM(municipio))) por município (não-sargável, lentíssimo) — substituir por chave normalizada na ingestão
  • Limite RSS no systemd unit (MemoryMax=2G) como guarda-chuva

Critério de aceite

  • python scripts/normalize.py em produção sem ultrapassar 500 MB RSS e MemAvailable nunca abaixo de 1 GB

Workaround atual

/tmp/fast_regen_dashboard.py (criado em 2026-04-29) regera só headline + séries do dashboard.json em 5s, RSS < 100 MB. Mas pula estados/municípios/uniao.

## Contexto A função carrega 4,77M rows de `contratos` num único `cursor.execute() + fetchall()`. RSS Python explode no LXC de 8 GiB — em 2026-04-28 causou OOM-thrash com sshd/nginx/postgres ficando mudos por horas. ## Reproduce ``` ssh root@soberaniadigital.org.br sudo -u autonomia bash -c "cd /home/autonomia/soberaniadigital && .venv/bin/python scripts/normalize.py" # observe RSS crescer e MemAvailable cair → kill antes de 1GB livre ``` ## Solução - [ ] Trocar `fetchall()` por server-side cursor: `conn.cursor("named", withhold=False)` + `cur.itersize = 10000` - [ ] Ou: converter `generate_uniao_jsons`, `generate_estados_json`, `generate_municipios_json` para SQL agregado (o que `generate_dashboard_json` já faz) - [ ] `generate_municipios_json` faz `UPPER(unaccent(TRIM(municipio)))` por município (não-sargável, lentíssimo) — substituir por chave normalizada na ingestão - [ ] Limite RSS no systemd unit (`MemoryMax=2G`) como guarda-chuva ## Critério de aceite - `python scripts/normalize.py` em produção sem ultrapassar 500 MB RSS e MemAvailable nunca abaixo de 1 GB ## Workaround atual `/tmp/fast_regen_dashboard.py` (criado em 2026-04-29) regera só headline + séries do `dashboard.json` em 5s, RSS < 100 MB. Mas pula estados/municípios/uniao.
Sign in to join this conversation.
No description provided.