Buscar K
Aparência
Aparência
Um flow é um Dataflow: extrai de uma origem, transforma e grava numa tabela do HorusDW. O arquivo fica em flows/<slug>--<id>.yaml. Os dois eixos da carga, Extração e Gravação, estão explicados em tipos de carga.
Crie com lumo new flow --name "Fato Vendas", edite o arquivo que o comando escreveu e mande com lumo push flow:<id>. O push grava o rascunho; para publicar numa Mesa de Dados, lumo flow publish flow:<id> --desk <id>.
fileName^[a-z0-9-]+--\d+\.yaml$headerheader.idheader.kindflow (fixo)header.lumov2 (fixo)header.tenantIdheader.appIdheader.dashboardIdbodybody.criado_em^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$body.criado_porbody.publicado_em^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$body.publicado_porbody.nomebody._statedraft, published, inconsistentbody.load_typeTotal, Incremental, Temporalbody.load_type_columnbody.write_modereplace_all, replace_window, upsert_by_key, insert_onlylumo lint refuses the ones that would corrupt data, and names which of the two fields to change.body.key_sweeplumo lint checks the shape, the server owns the SQL safety check.body.key_sweep.sqlbody.key_sweep.credentialIdbody.deskIdbody.cloned_frombody.originalTableIdbody.versionbody.tokenIdbody.development_variablesbody.nodesbody.nodes.Connectionsbody.nodes.Connections[].frombody.nodes.Connections[].tobody.nodes.Processorsbody.nodes.Processors[].complete_idbody.nodes.Processors[].internalIdbody.nodes.Processors[].kindbody.nodes.Processors[].descriptionbody.nodes.Processors[].inputsbody.nodes.Processors[].metadatabody.nodes.Processors[].optionsbody.nodes.Processors[].xbody.nodes.Processors[].ybody.tablebody.table.idbody.table.nomebody.tagsbody.ownersbody.owners[].userIdUm fato de vendas que recarrega uma janela de datas a cada execução.
# flows/fato-vendas--5101.yaml
# yaml-language-server: $schema=https://docs.horusbi.com.br/schemas/v2/flow.schema.json
id: 5101
kind: flow
lumo: v2
tenantId: 1200
---
nome: Fato Vendas
# Extração: uma janela de datas. A coluna precisa ser imutável na origem.
load_type: Temporal
load_type_column: DATA_EMISSAO
# Gravação: apaga a janela no destino e insere de novo.
write_mode: replace_window
tokenId: 41 # Agente ETL que roda o Dataflow (lumo list agent)
nodes:
Processors:
- internalId: ext_pedidos
kind: ExtractPostgreSQL
inputs: []
options:
Credential: erp-producao # chave da credencial, não o id (lumo list credential)
SQL: |
SELECT p.id AS PEDIDO_ID,
p.cliente_id AS CLIENTE_ID,
p.data_emissao AS DATA_EMISSAO,
p.valor_total AS VALOR_TOTAL
FROM public.pedidos p
WHERE p.data_emissao >= '{StartDate}'
AND p.data_emissao < '{EndDate}'
- internalId: load_dw
kind: InsertDatawarehouse
inputs: [ext_pedidos]
options:
TableID: 6230 # preenchido por lumo new table --from-flow
Mode: Datawarehouse
Connections:
- from: ext_pedidos
to: load_dwlumo scaffold flow lista os modelos prontos (PostgreSQL, CSV, HTTP, Python, Join, Union e outros), e lumo scaffold node <kind> mostra as options de cada tipo de nó, comentadas.
Das 12 combinações de load_type com write_mode, 5 são aceitas. O lumo lint recusa as outras e diz qual dos dois campos trocar.
load_type | write_mode aceitos |
|---|---|
Total | replace_all |
Temporal | replace_window, upsert_by_key |
Incremental | upsert_by_key, insert_only |
write_mode ausente faz o servidor deduzir a Gravação de load_type e do key_type da tabela de destino, como rodavam os Dataflows anteriores ao campo. upsert_by_key exige destino table_type: table com key_type: unique e key_columns, e insert_only é recusado num destino que já tira duplicata. Só replace_all e replace_window percebem um registro apagado na origem; para os outros, veja exclusões na origem e o campo key_sweep.
inputs do nó de destino e em Connections. Os dois precisam concordar, e o lint recusa um inputs que aponta para nó inexistente.Join, a ordem de inputs importa: o primeiro é o principal, e todas as colunas dele ficam. O Union casa as colunas pelo nome.Credential leva a chave da credencial (o campo key do arquivo dela), não o id nem o nome.TableID à mão. O lumo new table --from-flow e o lumo flow sync-table o preenchem; um valor escrito à mão gera drift.Mode do InsertDatawarehouse precisa combinar com o table_type da tabela (Datawarehouse para table, Datalake para cloud). Discordando, a carga grava no lugar certo, mas a carga Incremental procura a marca da última execução no lugar errado, sem erro.table_type: table), a opção PrimaryKeys do InsertDatawarehouse é ignorada: quem tira duplicata é o key_type: unique da tabela.key_sweep só vale com load_type: Incremental e destino com key_type: unique. A consulta precisa devolver todas as chaves vivas na origem, sem filtro de período: o que não voltar é marcado como apagado.tokenId e dar push muda o Agente ETL do Dataflow e leva os agendamentos dele junto. Se a credencial do Dataflow não está no agente destino, o push é recusado e nada é gravado: rode lumo credential transfer antes.push: lumo flow clone, edite o clone e publique.lumo flow run roda só Dataflow publicado. Num rascunho, teste nó a nó com lumo flow run-node.