Skip to content

fix(br_anatel_banda_larga_fixa): destrava atualização com poll deferido#1632

Open
DaviMacielCavalcante wants to merge 9 commits into
mainfrom
fix/br_anatel_banda_larga_fixa
Open

fix(br_anatel_banda_larga_fixa): destrava atualização com poll deferido#1632
DaviMacielCavalcante wants to merge 9 commits into
mainfrom
fix/br_anatel_banda_larga_fixa

Conversation

@DaviMacielCavalcante

@DaviMacielCavalcante DaviMacielCavalcante commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Contexto

A base parou de atualizar. O flow desistia antes de materializar por causa do poll eager (register_source_poll_task), que comparava a cobertura do dado (último ano-mês, dia 01) com a data de publicação do arquivo gravada na fonte (2026-06-04). Como a cobertura sempre atrasa a publicação, o poll nunca detectava novidade.

Verificação (2026-07-06): a Anatel já publicou maio/2026 enquanto o prod estava preso em abril — o congelamento passou a causar perda de dado real.

Mudanças

  • Poll eager → deferido (crawler/anatel/banda_larga_fixa/flows.py): poll_source_for_update_task (detecta antes) + commit_source_update_task (grava o Update só após materializar), no padrão do ibge_inflacao. O commit reescreve a data de fonte envenenada por uma data de cobertura, destravando o poll dali em diante.
  • Range de partição do microdados (end 2023 → 2031): os anos 2024–2026 caíam em __UNPARTITIONED__ e perdiam partition pruning.
  • README com contexto e decisões da base.

Validação

  • force_run em dev (deploy basedosdados-dev): microdados alcança 2026-05 e as contagens jan–abr batem com a fonte
  • force_run por tabela em prod: recupera o backlog e o commit reescreve o 2026-06-04

Notas

  • telefonia_movel tem o mesmo poll eager — fix à parte.

@DaviMacielCavalcante DaviMacielCavalcante added the deploy-flow [PR] Dispara deploy dos flows alterados no work pool basedosdados-dev (Prefect 3 staging) label Jul 6, 2026
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR updates the Anatel banda_larga_fixa crawler flow, density parsing, and microdados partitioning, and adds dataset documentation plus a flow docstring reference.

Changes

Deferred Poll/Commit and Dataset Updates

Layer / File(s) Summary
Poll then commit task wiring in crawler flow
pipelines/crawler/anatel/banda_larga_fixa/flows.py
Imports poll and commit source update tasks, replaces the outdated-source check with a has_new_data poll, and commits the source update after metadata changes using source_max_date, env, and date_format parameters.
Density parsing and partition range
pipelines/crawler/anatel/banda_larga_fixa/utils.py, models/br_anatel_banda_larga_fixa/br_anatel_banda_larga_fixa__microdados.sql
Adds a shared density parser that preserves non-string values and applies it in the three treatment functions, while extending the microdados ano partition range end to 2031.
Dataset README and flow docstring
pipelines/datasets/br_anatel_banda_larga_fixa/README.md, pipelines/datasets/br_anatel_banda_larga_fixa/flows.py
Adds the dataset README with source context, freeze root cause, deferred poll/commit fix, verification notes, table semantics, execution parameters, and correction history, and updates the flow module docstring to point to that README.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested labels: bug, check-metadata

Suggested reviewers: folhesgabriel

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning O título é relacionado, mas não segue o padrão exigido do repositório com a keyword entre colchetes. Troque para algo como "[Bugfix] br_anatel_banda_larga_fixa: destrava atualização com poll deferido".
Description check ⚠️ Warning A descrição cobre contexto, mudanças e validação, mas está incompleta frente ao template obrigatório e omite várias seções pedidas. Adicione as seções do template: descrição do PR, detalhes técnicos, riscos/rollback, dependências, revisadores e testes/validações completos.
✅ Passed checks (3 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/br_anatel_banda_larga_fixa

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pipelines/datasets/br_anatel_banda_larga_fixa/README.md`:
- Line 142: The correction history entry in the README still contains an
unfilled PR number placeholder. Update the “Destravamento da atualização” note
to replace PR `#____` with the actual pull request number, keeping the existing
entry text and formatting intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 711d1e7e-4020-4d18-86c3-0118add52103

📥 Commits

Reviewing files that changed from the base of the PR and between 351f232 and 710c906.

📒 Files selected for processing (4)
  • models/br_anatel_banda_larga_fixa/br_anatel_banda_larga_fixa__microdados.sql
  • pipelines/crawler/anatel/banda_larga_fixa/flows.py
  • pipelines/datasets/br_anatel_banda_larga_fixa/README.md
  • pipelines/datasets/br_anatel_banda_larga_fixa/flows.py


## Histórico de Correções

- **Destravamento da atualização (PR #____):** substituição do poll eager

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fill in the PR number placeholder.

PR #____`` is an unfilled placeholder in the correction history entry.

✏️ Suggested fix
-- **Destravamento da atualização (PR `#____`):** substituição do poll eager
+- **Destravamento da atualização (PR `#123`):** substituição do poll eager
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pipelines/datasets/br_anatel_banda_larga_fixa/README.md` at line 142, The
correction history entry in the README still contains an unfilled PR number
placeholder. Update the “Destravamento da atualização” note to replace PR `#____`
with the actual pull request number, keeping the existing entry text and
formatting intact.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pipelines/crawler/anatel/banda_larga_fixa/utils.py`:
- Around line 115-138: The docstring in _parse_densidade is using NumPy-style
sections instead of the project-required Google Style, and several lines exceed
the 79-character Ruff limit. Update the _parse_densidade docstring to use
Google-style Args and Returns headers, keep the same meaning for x and the
return value, and rewrap any long prose so every line stays within the
line-length limit. Ensure the function’s behavior and signature remain
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6f6a9e33-cce6-4ba8-b4b7-268ad468ea86

📥 Commits

Reviewing files that changed from the base of the PR and between 710c906 and a6a6bad.

📒 Files selected for processing (2)
  • pipelines/crawler/anatel/banda_larga_fixa/utils.py
  • pipelines/datasets/br_anatel_banda_larga_fixa/README.md
✅ Files skipped from review due to trivial changes (1)
  • pipelines/datasets/br_anatel_banda_larga_fixa/README.md

Comment on lines +115 to +138
def _parse_densidade(x: object) -> float | None:
"""Converte a Densidade da fonte (string BR, ex. '12,34') para float.

A fonte traz Densidade vazia (NaN) em ~45% das linhas — ver
``task_davi/diagnostico_densidade_blf.py``. Esses casos devem virar NULL no
``safe_cast(densidade as float64)`` do dbt.

Parameters
----------
x : object
Valor bruto da célula: string com vírgula decimal, ou NaN (float) quando
a densidade não está preenchida.

Returns
-------
float | None
A densidade como float; ou o próprio NaN/None quando a célula está vazia.
"""
if isinstance(x, str):
return float(x.replace(",", "."))

return x


Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Docstring uses NumPy style, not Google Style; also exceeds the 79-char line limit.

The docstring here uses Parameters/Returns headers with ---- underlines (NumPy style) rather than Google Style's Args:/Returns: headers. Additionally, the parameter/return description lines (e.g., lines 126, 131) run past the project's configured 79-character Ruff limit.

♻️ Proposed Google-style rewrite
 def _parse_densidade(x: object) -> float | None:
     """Converte a Densidade da fonte (string BR, ex. '12,34') para float.
 
     A fonte traz Densidade vazia (NaN) em ~45% das linhas — ver
-    ``task_davi/diagnostico_densidade_blf.py``. Esses casos devem virar NULL no
-    ``safe_cast(densidade as float64)`` do dbt.
-
-    Parameters
-    ----------
-    x : object
-        Valor bruto da célula: string com vírgula decimal, ou NaN (float) quando
-        a densidade não está preenchida.
-
-    Returns
-    -------
-    float | None
-        A densidade como float; ou o próprio NaN/None quando a célula está vazia.
+    ``task_davi/diagnostico_densidade_blf.py``. Esses casos devem virar
+    NULL no ``safe_cast(densidade as float64)`` do dbt.
+
+    Args:
+        x: Valor bruto da célula: string com vírgula decimal, ou NaN
+            (float) quando a densidade não está preenchida.
+
+    Returns:
+        A densidade como float; ou o próprio NaN/None quando a célula
+        está vazia.
     """
     if isinstance(x, str):
         return float(x.replace(",", "."))
 
     return x

As per coding guidelines, **/*.py: "Add type hints and docstrings for Python functions following Google Style" and "Use Ruff linter with line length 79 and Python 3.10 target".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def _parse_densidade(x: object) -> float | None:
"""Converte a Densidade da fonte (string BR, ex. '12,34') para float.
A fonte traz Densidade vazia (NaN) em ~45% das linhasver
``task_davi/diagnostico_densidade_blf.py``. Esses casos devem virar NULL no
``safe_cast(densidade as float64)`` do dbt.
Parameters
----------
x : object
Valor bruto da célula: string com vírgula decimal, ou NaN (float) quando
a densidade não está preenchida.
Returns
-------
float | None
A densidade como float; ou o próprio NaN/None quando a célula está vazia.
"""
if isinstance(x, str):
return float(x.replace(",", "."))
return x
def _parse_densidade(x: object) -> float | None:
"""Converte a Densidade da fonte (string BR, ex. '12,34') para float.
A fonte traz Densidade vazia (NaN) em ~45% das linhasver
``task_davi/diagnostico_densidade_blf.py``. Esses casos devem virar
NULL no ``safe_cast(densidade as float64)`` do dbt.
Args:
x: Valor bruto da célula: string com vírgula decimal, ou NaN
(float) quando a densidade não está preenchida.
Returns:
A densidade como float; ou o próprio NaN/None quando a célula
está vazia.
"""
if isinstance(x, str):
return float(x.replace(",", "."))
return x
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pipelines/crawler/anatel/banda_larga_fixa/utils.py` around lines 115 - 138,
The docstring in _parse_densidade is using NumPy-style sections instead of the
project-required Google Style, and several lines exceed the 79-character Ruff
limit. Update the _parse_densidade docstring to use Google-style Args and
Returns headers, keep the same meaning for x and the return value, and rewrap
any long prose so every line stays within the line-length limit. Ensure the
function’s behavior and signature remain unchanged.

Source: Coding guidelines

@DaviMacielCavalcante

Copy link
Copy Markdown
Collaborator Author

Escopo ampliado — tratamento das densidades

O fix do poll destravou as densidades e expôs bugs pré-existentes de tratamento (crawler/anatel/banda_larga_fixa/utils.py) que o congelamento mascarava. Corrigidos neste PR:

  1. Densidade vazia quebrava o parse. float(x.replace(",", ".")) assumia string em toda célula, mas a fonte traz Densidade NaN em ~45% das linhas de município → AttributeError. Extraí _parse_densidade: converte a string BR ("12,34") para float e devolve o NaN intacto (→ NULL no safe_cast). Usado por treatment_br/uf/municipio — elimina a lambda duplicada nos três.

  2. id_municipio com .0 reprovava o teste de relationships. O Código IBGE era lido sem dtype=str; como a coluna tem NaN, o pandas inferia float e o id virava "3552502.0", sem match no diretório. Fix: dtype=str nos 3 reads de densidade (o microdados passa porque a coluna dele não tem NaN → fica int).

  3. Linhas de município sem código reprovavam o unique_combination. A fonte traz ~752k linhas de município sem Código IBGE (id e densidade vazios) que colapsavam em [ano, mes, NULL] duplicado. Fix: dropna(subset=["Código IBGE"]) no treatment_municipio.

Decisão de modelagem: em Brasil/UF a densidade vazia é mantida como NULL (geografia válida, valor faltando). Em município, as linhas sem código são dropadas — não são "município sem densidade", são linhas sem município. Isso não afeta o invariante 1/27/5570, pois count(distinct id_municipio) ignora NULL.

Validação: microdados validado em dev (cobertura chega a 2026-05, contagens batem com a fonte). Tratamento das densidades validado localmente sobre o arquivo atual da fonte (904.700 linhas de município, 0 código nulo). Validação end-to-end de densidade_municipio em dev em andamento.

@mergify

mergify Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

@DaviMacielCavalcante esse pull request tem conflitos 😩

@mergify mergify Bot added the conflict [PR] Conflito de merge a resolver label Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

conflict [PR] Conflito de merge a resolver deploy-flow [PR] Dispara deploy dos flows alterados no work pool basedosdados-dev (Prefect 3 staging)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant