Pular para o conteúdo
SparquetSparquet

Conceitos centrais

Tudo no Sparquet decorre de uma única ordem de execução. Aprenda-a uma vez e o resto da referência se lê sozinho.

Um pipeline tem cinco partes. Apenas três são obrigatórias.

{
"name": "orders_curated", // required
"description": "", // optional
"spark": { "configs": {} }, // optional
"input": { }, // required
"transformations": [ ], // optional, ordered
"validations": { }, // optional
"output": { } // required — or "outputs": [ … ]
}

Esta sequência é o modelo mental de todo o framework:

  1. Substituição de {param} — os placeholders são substituídos no texto bruto, antes de o JSON ser parseado.
  2. Expansão de $include — os fragmentos referenciados são inlinados em transformations.
  3. Parse — o documento vira configuração tipada; chaves desconhecidas são carregadas adiante, não rejeitadas.
  4. Leitura do input — uma fonte, através do registry de readers. Uma coluna ingestion_ts é adicionada automaticamente.
  5. Transformações — aplicadas na ordem do array, com as variáveis {{runtime}} resolvidas conforme cada uma roda.
  6. Validações — medidas sobre o DataFrame transformado; o relatório opcional é gravado aqui.
  7. Para cada destino — suas próprias transformations, depois sua projeção de colunas, depois a escrita.

Duas consequências em que as pessoas tropeçam:

  • Transformações rodam antes das validações. Uma regra sempre vê os dados limpos, nunca a fonte bruta.
  • As transformações por destino rodam depois das validações. Reformatar para uma saída nunca afeta o que as regras mediram, nem o que outra saída recebe.

Transformações mudam os dados. Validações reportam sobre eles.

Seção intitulada “Transformações mudam os dados. Validações reportam sobre eles.”
Você quer… Use
Remover linhas com id nulo filter em transformations
Saber quantos ids nulos chegaram not_null em validations
Descartar duplicatas drop_duplicates
Falhar a execução quando existirem duplicatas unique com on_failure: "fail"

Uma validação nunca modifica o DataFrame. Essa separação é o que torna um relatório de qualidade confiável: ele descreve os dados que você realmente gravou.

O Sparquet tem dois mecanismos de substituição, e eles são resolvidos em momentos diferentes.

{param} {{variable}}
Resolvido antes do parse durante a execução
Vem de o argumento params da execução uma transformação collect
Uso típico ambiente, data, feature flags uma lista de chaves empurrada para uma leitura posterior
Se não resolvido fica literal, sem erro fica literal, resolvido depois se aparecer
// {param}: known when you launch the run
{ "type": "filter", "condition": "region = '{region}'" }
// {{variable}}: computed by the pipeline itself
{ "type": "collect", "column": "customer_id", "as": "active" },
{ "type": "join",
"with": { "format": "delta", "path": "sales.events" },
"with_transformations": [
{ "type": "filter", "condition": "customer_id IN ({{active}})" }
],
"on": "customer_id" }

Veja Parâmetros e variáveis para as regras de formatação de cada tipo.

O Studio não armazena um formato proprietário — ele compila o grafo. Duas regras definem o mapeamento:

1. A cadeia compartilhada é o pipeline principal. As transformações que todo destino tem em comum viram as transformations de topo. Assim que o grafo se ramifica, cada branch vira as transformations próprias daquele destino.

source → filter → cast ─┬─→ [group_by] → delta ← group_by belongs to this output
└─→ parquet ← filter and cast are shared

2. Um join ou union pega sua segunda fonte do seu segundo input. A cadeia que alimenta aquele handle vira with_transformations.

┌── delta(events) → filter → select ──┐ ← with + with_transformations
source → filter ─┴────────────────────────────────────→ join → sink

Todo o resto é um campo de um node. Notas nunca compilam; nodes desabilitados são pulados.

O framework detecta seu ambiente e adapta a sessão:

Ambiente Comportamento
Databricks Reusa a sessão ativa; o bloco spark é ignorado
EMR / Dataproc / Synapse Constrói uma sessão com seus configs
Local Aplica master também (local[*] por padrão)

A sessão é um singleton de todo o processo: a primeira instância de Sparquet vence, e os pipelines posteriores a compartilham. É isso que torna barato rodar vários pipelines num único job.

PipelineResult nunca lança exceção. Uma execução que falhou volta como dado:

result = fw.run("pipeline.json")
result.success # False when something went wrong
result.error # the message, when it did
result.skipped # True when stop_if_empty ended the run early
result.rows_read # rows read from the input
result.rows_written # rows in the main DataFrame at write time
result.validation_results # one entry per rule

Esse formato é o que permite a um orquestrador ramificar pelo resultado sem envolver tudo num try.