Mapa da aula
Aula 09 publicada. Mapa, exemplo, EX025.
flowchart TD
N0["9.1 Pipelines"]
N1["9.3 JSON seguro"]
N2["9.4 Propriedades"]
N3["9.5 Versionamento de parsers"]
N4["Nota de prática — Contrapressão"]
N5["Síntese"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5
N5 --> EX["Exemplo resolvido"]
EX --> Q["Exercício EX025"]
Desenho lógico
flowchart LR
N0["9.1 Pipelines"]
N1["9.3 JSON seguro"]
N2["9.4 Propriedades"]
N3["9.5 Versionamento de parsers"]
N4["Nota de prática — Contrapressão"]
N5["Síntese"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> Q["EX025"]
[9.1 Pipelines]
|
v
[9.3 JSON seguro]
|
v
[9.4 Propriedades]
|
v
[9.5 Versionamento de parsers]
|
v
[Nota de prática — Contrapressão]
|
v
[Síntese]
|
v
[Exemplo resolvido] --> [Exercício EX025]
Objetivos de aprendizagem
Você vai (1) estruturar um parser como um pipeline de etapas; (2) tratar erros sem perder registros em silêncio; (3) interpretar JSON com segurança usando a biblioteca padrão; (4) escrever testes de propriedades para a normalização.
9.1 Pipelines
A ingestão do Lantern é uma cadeia: obter → decodificar → validar → normalizar → deduplicar → armazenar. Cada etapa recebe registros e produz registros mais rejeições. Os geradores do Python permitem que feeds grandes fluam sem carregar tudo na memória. Cada etapa pode ser testada isoladamente com uma lista curta de registros, e uma falha em uma etapa não esconde o que as outras fizeram. Os logs de Kofi mostram quantos registros entraram e saíram de cada etapa, então uma queda repentina aponta a etapa que a causou. Quando um parceiro envia um arquivo muito grande, o fluxo contínuo faz o uso de memória ficar estável, em vez de crescer com o arquivo.
9.2 Erros como dados
Um objeto malformado não é uma exceção a engolir; é um registro de rejeição com um motivo, a fonte e o hash dos bytes originais. As contagens de rejeições por fonte viram uma métrica de qualidade de dados sobre a qual os parceiros podem agir. Os registros de rejeição de Kofi guardam o hash, e não o conteúdo, para que dados restritos de um parceiro não sejam copiados para logs que uma equipe mais ampla pode ler. Se o mesmo motivo aparece em muitos registros de uma fonte, o parceiro provavelmente mudou algo do lado dele. O relatório enviado a ele traz contagens e exemplos, o que geralmente basta para que encontre e corrija o problema.
9.3 JSON seguro
json.loads interpreta dados sem executar código, ao contrário de avaliar texto. Limite o tamanho das entradas para evitar o esgotamento da memória e valide os tipos depois do parsing; números, strings e nulos JSON chegam em lugares inesperados. Kofi define um tamanho máximo para cada objeto antes do parsing, para que uma entrada enorme seja rejeitada em vez de encher a memória. Depois do parsing, ele verifica se cada campo tem o tipo esperado: um campo de carimbo de tempo contendo um número, ou uma lista onde se esperava uma string, é uma rejeição com motivo claro. Um código antigo que avaliava texto como programa para poupar esforço foi removido em seu primeiro mês.
9.4 Propriedades
Em vez de apenas testes de exemplo, declare propriedades: normalizar duas vezes é igual a normalizar uma vez (idempotência); a saída está sempre em minúsculas; nenhuma saída tem espaço em branco em nenhuma das pontas. Gere muitas entradas aleatórias e verifique se as propriedades se mantêm. As entradas aleatórias de Kofi incluem maiúsculas e minúsculas misturadas, espaços no início e no fim, strings vazias e caracteres de outros alfabetos. Um teste de propriedade descobriu que seu normalizador de domínios mantinha um ponto final, o que fazia duas formas do mesmo nome contarem como indicadores diferentes. A correção removeu algumas centenas de duplicatas do repositório.
9.5 Versionamento de parsers
Quando um parceiro muda seu formato de exportação, uma nova versão do parser é implantada ao lado da antiga até que a troca seja verificada. Cada objeto armazenado registra a versão do parser que o produziu. Rodar as duas versões sobre a mesma entrada por alguns dias mostra se a nova produz os mesmos registros, mais rejeições ou valores diferentes. Só quando as diferenças são compreendidas o parser antigo é desligado. Registrar a versão em cada objeto significa que, se um bug for encontrado depois, os registros afetados podem ser identificados e reprocessados, em vez de adivinhados.
Nota de prática — Contrapressão
Quando uma etapa a jusante fica lenta, as etapas a montante não podem continuar empurrando até a memória acabar. Filas limitadas entre as etapas dão contrapressão (backpressure): os produtores esperam quando uma fila está cheia. O coletor do Lantern pausa as consultas quando a fila de validação está na capacidade máxima e registra a pausa, para que os operadores a vejam, em vez de descobrirem dados ausentes depois.
Exemplo resolvido
Um parceiro envia 5.000 objetos com 37 carimbos de tempo malformados. O pipeline de Kofi armazena 4.963, grava 37 rejeições com o motivo "created not RFC 3339" e envia ao contato de qualidade de dados do parceiro um e-mail com a contagem e dois hashes de exemplo — não os objetos brutos, que são TLP:AMBER.
Caso sintético. As contagens e o parceiro são inventados.
Erros e limites
Descartar registros ruins em silêncio esconde problemas dos parceiros; corrigi-los em silêncio inventa dados. Não avalie texto não confiável como código.
Exercícios
- EX025 — Registro de rejeição. Liste quatro campos que um registro de rejeição deve trazer.
Mostrar critérios de avaliação
Rubrica: 3 = quatro entre motivo, fonte, hash, carimbo de tempo, versão do parser; 2 = dois; 1 = um; 0 = nenhuma. - EX026 — Idempotência. Enuncie a propriedade de idempotência de um normalizador e por que ela importa.
Mostrar critérios de avaliação
Rubrica: 3 = norm(norm(x)) == norm(x); reprocessar é estável; 2 = só o enunciado; 1 = errado; 0 = nenhuma. - EX027 — Relatório ao parceiro. Por que enviar hashes e contagens, e não os próprios objetos malformados?
Mostrar critérios de avaliação
Rubrica: 3 = TLP/minimização; o parceiro localiza pelo hash; 2 = parcial; 1 = enviar tudo; 0 = nenhuma.
Síntese
Faça os dados fluírem por etapas, trate erros como dados, interprete com segurança, teste propriedades e registre as versões dos parsers.
Continue estudando — capítulo 09 de 50
← Capítulo 08 (rascunho) · Índice de capítulos do curso · Capítulo 10 (rascunho) →