basedosdados / basedosdados/pipelines

[bug] quebra nos flows do CNO e do CNPJ (ambos RF)

Open
#2,036 0 comments 0 reactions 2 assignees Claimed by @luizavboas View on GitHub
bug
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.