Pular para conteúdo

Arquitetura

flowchart TD
    API[OpenSky API] --> Collector[Coletor Python finito]
    Collector --> Bronze[Bronze: JSONL]
    Bronze --> Beam1[Beam: validação e normalização]
    Beam1 --> Silver[Silver: Parquet]
    Beam1 --> Rejected[Rejeitados: JSONL]
    Silver --> Beam2[Beam: agregações]
    Beam2 --> Gold[Gold: JSONL]
    Gold --> Streamlit[Streamlit]
    Silver -. Sem Gold: consulta com DuckDB .-> Streamlit
    Collector --> Obs[Relatórios JSON]
    Beam1 --> Obs
    Beam2 --> Obs
    Obs --> Streamlit

Responsabilidades

Componente Responsabilidade
collectors/opensky_client.py Consultar a API, validar respostas e repetir falhas transitórias
collectors/aircraft_states.py Acumular respostas de uma execução e gravar um microbatch Bronze atomicamente
pipelines/bronze_to_silver.py Executar parsing, normalização e separação de rejeitados com Beam
pipelines/silver_to_gold.py Produzir a última observação por aeronave e o resumo das observações de entrada
run_all.py Encadear as etapas usando os arquivos produzidos na execução atual
dashboard/app.py Ler Gold e relatórios; consultar Silver com DuckDB quando Gold não existe

Os módulos acima ficam em src/air_traffic_beam/. O coletor é Python comum; os dois pipelines de transformação usam Apache Beam com DirectRunner nos comandos documentados.

Persistência e escopo

A Bronze acumula as respostas em memória e grava um arquivo ao terminar a coleta. Se uma requisição falhar depois de respostas válidas, grava o lote parcial com sufixo _partial.jsonl antes de propagar o erro.

Silver e Gold recebem UUIDs nos prefixos de saída. Isso preserva os arquivos anteriores, mas não torna reprocessamentos idempotentes: ler novamente a mesma Bronze gera novas observações Silver. Consulte Execução local para escolher entre a carga atual e o histórico.

O resumo Gold usa ToList e mantém as observações de entrada em memória. A implementação atende a lotes locais pequenos; o loop make stream repete execuções finitas, sem janelas ou estado persistente de streaming.