basedosdados / basedosdados/pipelines
[bug] quebra nos flows do CNO e do CNPJ (ambos RF)
- Dominant language
- Python
- Stars
- 49
- Forks
- 22
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 167
Description
### Descrição do bug
## Sintoma
Desde 11/09/2026, os nove flows que acessam `arquivos.receitafederal.gov.br` falham
na primeira task, antes de qualquer download. São dois conjuntos, que compartilham o
mesmo host e o mesmo token de compartilhamento (`gn672Ad4CF8N6TK`), em pastas
diferentes.
**`br_rf_cno`** (`microdados`, `vinculos`, `areas`, `cnaes`) — falha em
`check_need_for_update` (`pipelines/crawler/rf/tasks.py:61`), no `HEAD` via `httpx`:
```
---- Checking most recent update date for br_rf_cno
Request attempt 1..5/5 failed: Server disconnected without sending a response.
httpx.RemoteProtocolError: Server disconnected without sending a response.
```
**`br_rf_cnpj`** (`dicionario`, `empresas`, `socios`, `simples`, `estabelecimentos`) —
falha em `data_url` (`pipelines/datasets/br_rf_cnpj/utils.py:41`), chamada por
`get_data_source_max_date` (`tasks.py:43`), no `PROPFIND` via `requests`:
```
requests.exceptions.ConnectionError:
('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
```
Os dois erros descrevem o mesmo evento em bibliotecas diferentes: a conexão é aceita,
a requisição é enviada por completo e o servidor a encerra sem devolver nenhum byte
de resposta — o erro é levantado em `_read_status`, na espera da linha de status.
Horários das falhas em 11/09 (UTC):
```
br_rf_cno microdados 07:05 vinculos 07:15 areas 07:25 cnaes 07:35
br_rf_cnpj dicionario 08:00 empresas 09:08 socios 10:00 simples 11:09
estabelecimentos 12:00
```
Cada execução do `br_rf_cnpj` dura cerca de 95 segundos: quatro tentativas espaçadas
em 30 segundos, todas com o mesmo resultado. As do `br_rf_cno` esgotam cinco
tentativas com backoff em menos de 40 segundos.
## Verificação da fonte
A fonte responde normalmente a requisições feitas fora do cluster. Em 11/09/2026
14:23 UTC, com os mesmos headers usados por `check_need_for_update`:
```
HEAD .../Dados/Cadastros/CNO/cno.zip → 200
Last-Modified: Thu, 10 Sep 2026 05:00:03 GMT
Content-Length: 330189729
GET (Range: bytes=0-1023) → 206, assinatura PK
PROPFIND .../Dados/Cadastros/CNO/ → 207
```
Em 14:38 UTC, replicando o `PROPFIND` do `br_rf_cnpj` — mesmo método, mesmos quatro
headers, mesmo corpo XML:
```
PROPFIND .../Dados/Cadastros/CNPJ/ → 207, 19.677 bytes
última pasta listada: 2026-08/
```
O `HEAD` do `br_rf_cno` retornou 200 tanto com `br_rf_constants.HEADERS` quanto com
`_BROWSER_HEADERS`, em três repetições de cada.
## Comparação direta
Execução manual do `br_rf_cnpj__dicionario` em 11/09, com `materialize_after_dump` e
`update_metadata` desligados, seguida da mesma requisição feita de fora do cluster:
```
14:55:54 UTC cluster conexão encerrada sem resposta
14:56:25 UTC cluster idem (retry 1/3)
14:56:56 UTC cluster idem (retry 2/3)
14:57:26 UTC cluster idem (retry 3/3)
14:58:53 UTC fora 207, 19.677 bytes, 1,87s
```
A requisição é idêntica nos dois casos. A execução manual terminou na primeira task,
sem baixar dados nem alterar metadados.
## Histórico de execuções
```
09/09 br_rf_cno as quatro concluíram em ~3s (sem novidade na fonte)
10/09 br_rf_cno microdados 07:05 → 07:18 vinculos 07:15 → 07:25
areas 07:25 → 07:36 cnaes 07:37 → 07:47 (ingestão completa)
10/09 br_rf_cnpj as cinco concluíram em ~3s (sem novidade na fonte)
11/09 ambos as nove falham antes de acessar a fonte
```
## Comportamento atual do download (br_rf_cno)
Cada um dos quatro flows do `br_rf_cno` baixa o ZIP completo (~315 MB) de forma
independente, em partes de 16 MB com `Semaphore(5)` (`download_file_async`,
`pipelines/crawler/rf/utils.py`). Os horários agendados se sobrepõem, conforme os
tempos de 10/09 acima: cerca de 1,26 GB transferidos do mesmo arquivo em 40 minutos,
com até 10 conexões simultâneas nos intervalos de coincidência.
O README do conjunto (`pipelines/datasets/br_rf_cno/README.md`) registra que a fonte
está atrás de um WAF (F5 BIG-IP) que bloqueia `PROPFIND` e User-Agents crus, e que
aplica limites por IP.
### Como reproduzir
Não reproduza, pode ocorrer de bloquearam o IP novamente
Contributor guide
Assessment
This issue has not been assessed yet.