O vocabulário por trás de um pipeline ContractForge.
O framework usa poucos conceitos centrais. A maior parte do comportamento vem da combinação entre source, transform, qualidade, schema policy, modo de escrita e metadados operacionais.
Plano
O objeto de execução normalizado. YAML, presets e kwargs viram um plano imutável antes da escrita dos dados.
Conector
O leitor de source. Deve recuperar dados e expor metadados de origem, sem esconder transformações de negócio.
Transform
Normalização física antes de qualidade/escrita: mapping, parsing JSON, flattening, arrays, projections, casts, limpeza de strings, derivações e deduplicação.
Modo de gravação
A semântica de escrita Delta: append, overwrite, upsert, hash diff, SCD2 ou snapshot completo com soft delete.
Arquivos de contrato e limites de responsabilidade
ContractForge oferece suporte a contratos divididos porque a lógica de ingestão, metadados de catálogo, propriedade operacional e controle de acesso geralmente têm proprietários e caminhos de aprovação diferentes.
| Arquivo | Proprietário principal | Contém | Aplicado por |
|---|---|---|---|
*.ingestion.yaml | Engenharia de dados | Source, target, modo, schema policy, transformações, qualidade, idempotência e controles de execução. | ingest_bundle() ou contractforge validate-bundle + execução do job. |
*.annotations.yaml | Governança de dados/proprietários de domínio | Descrições de tabelas, descrições de colunas, aliases, classificação de PII, metadados de depreciação e tags. | Workflow de ingestão ou apply_annotations_bundle(). |
*.operations.yaml | SRE/plataforma/proprietário do produto de dados | Business owner, technical owner, criticidade, frequência esperada, freshness SLA, runbook e metadados de alerta. | O workflow de ingestão registra nas control tables. |
*.access.yaml | Segurança/compliance | Grants, row filters, column masks e política de drift. | Workflow de acesso dedicado com um principal privilegiado. |
Guias de decisão
Utilize estes guias quando um contrato puder ser implementado de mais de uma forma válida. O objetivo não é ocultar as opções de design, mas tornar a escolha padrão explícita e revisável.
| Decisão | Escolha padrão | Use outro caminho quando |
|---|---|---|
| YAML, Python ou bundle | Use YAML para pipelines repetíveis e bundles quando ingestão, annotations, operations e access tiverem proprietários diferentes. | Use ingest() diretamente em notebooks para trabalho exploratório, transformações gold complexas ou etapas de migração que ainda precisam de escrita, qualidade e observabilidade do ContractForge. |
| Conector direto ou arquivos landed | Use conectores diretos para leituras bounded com limites explícitos de página, registro, byte e timeout. | Use object storage como landing quando a origem se comportar como feed, produzir grandes exports, precisar de replay ou tiver rate limits rígidos. |
| Serverless ou classic cluster | Use serverless quando a origem puder ser alcançada por recursos governados do workspace, External Locations, Volumes, Lakehouse Federation ou bibliotecas suportadas. | Use classic clusters quando precisar de configuração direta de credenciais Hadoop, roteamento de rede customizado, pacotes de conectores customizados ou controle fino de dependências. |
| Transform no connector ou no contrato | Mantenha connectors focados em leitura e metadados de source. Coloque shaping de negócio em transform. | Faça parsing no connector apenas o suficiente para expor registros com segurança. Nomes de colunas, flattening, casts, explode de arrays e deduplicação pertencem ao contrato. |
| Shaping em bronze ou silver | Mantenha bronze tão raw e auditável quanto possível; aplique estrutura determinística em silver. | Faça shape em bronze somente quando a origem raw for impraticável para armazenamento ou quando a governança downstream exigir um schema bronze estável imediatamente. |
| Write mode | Use o modo mais simples que preserva a semântica da source: append para eventos imutáveis, overwrite para snapshots substituíveis, SCD1 para dimensões de estado atual, SCD2 para histórico. | Use snapshot_reconcile_soft_delete apenas para snapshots completos; não combine com watermarks ou filtros de source porque isso altera o significado de linhas ausentes. |
| Local do schema | Declare source schemas onde o Spark precisa deles para ler bytes corretamente. Declare shape schemas onde strings JSON ou payloads aninhados precisam de parsing determinístico. | Não duplique schemas por conveniência. Se o mesmo schema aparecer em vários lugares, verifique se um é schema de leitura e o outro é schema de transformação. |
Ordem de execução
A ordem de execução faz parte do contrato do produto. Ela permite que usuários raciocinem sobre custo, modos de falha e observabilidade sem ler a implementação.
- A resolução da source acontece antes das transformações do DataFrame.
- Schema policy e quality gates rodam antes das operações de escrita.
- As anotações são aplicadas após a tabela e as colunas finais existirem.
- A governança de acesso é intencionalmente adiada para comandos dedicados.
Camada e esquema físico são separados
layer é uma classificação lógica usada por presets, validações e observabilidade. target.schema é o schema físico no catálogo. Eles podem ser iguais, mas não precisam ser.
target:
catalog: main
schema: crm_curated
table: s_customers
layer: silver
Modelo de falha
ContractForge distingue uma exceção Python lançada do estado operacional persistido de uma execução. Quando uma ingestão falha, o framework grava a run com falha, a mensagem curta e o traceback completo nas control tables e, por padrão, lança ContractForgeExecutionError para o chamador.
Falhe rápido para o chamador
Notebook tasks e jobs param naturalmente quando o contrato retorna FAILED ou ABORTED.
Inspecione payloads explicitamente
Use raise_on_failure=False em testes ou notebooks exploratórios quando o próprio resultado com falha for o alvo da asserção.
Modelo de observabilidade
O result payload e as control tables compartilham o mesmo vocabulário operacional. Um notebook pode inspecionar o resultado imediatamente, enquanto jobs e dashboards consultam evidências persistidas.
| Pergunta | Carga útil do resultado | Evidência da tabela de controle |
|---|---|---|
| A run foi bem-sucedida? | status, error_message | ctrl_ingestion_runs.status, ctrl_ingestion_errors.stack_trace |
| Quantos dados foram movidos? | rows_read, rows_written, rows_inserted, rows_updated, rows_deleted | ctrl_ingestion_runs métricas e operation_metrics_json |
| A qualidade passou? | quality_status, rows_quarantined | ctrl_ingestion_quality, ctrl_ingestion_quarantine |
| O esquema mudou? | schema_changes | ctrl_ingestion_schema_changes |
| Qual runtime foi usado? | runtime_type, spark_version, python_version, framework_version | ctrl_ingestion_runs e ctrl_ingestion_metadata |
| A governança foi aplicada? | governance, annotations_status | ctrl_ingestion_annotations, ctrl_ingestion_operations, ctrl_ingestion_access |
Modelo de runtime
O mesmo contrato deve ser explícito sobre comportamento sensível ao runtime. Algumas capacidades dependem de Databricks serverless, classic clusters, Unity Catalog External Locations ou bibliotecas de conectores Spark instaladas.
| Área | Orientação serverless | Orientação classic cluster |
|---|---|---|
| Object storage | Prefira Volumes ou External Locations. | Pode usar configuração direta Hadoop/S3A/ABFS quando as credenciais forem permitidas. |
| Auto Loader | Use checkpoint/schema locations disponíveis para o workspace. | Use cloudFiles com acesso a storage em nível de cluster. |
| JDBC | Requer disponibilidade de driver e rota de rede. | Instale o driver e configure VPC/firewall/peering conforme necessário. |
| Sistemas externalizados | Prefira federation, Lakeflow/conectores nativos ou tabelas/arquivos landed. | Instale jars/pacotes de conectores próprios apenas quando usar intencionalmente um resolver customizado. |