Buscar K
Aparência
Aparência
Um agendamento executa flows de forma recorrente. Ele vive em schedules/<slug>--<id>.yaml.
lumo new schedule --name "Carga Diária"Ligue o autocomplete no editor colando esta linha no topo do arquivo:
# yaml-language-server: $schema=https://docs.horusbi.com.br/schemas/v2/schedule.schema.jsonAntes de agendar: todos os flows precisam estar publicados num dw-desk, e todos precisam estar no mesmo agente. O agendamento herda o agente dos flows e não tem campo de agente próprio.
# ── header ────────────────────────────────────────────────
id: integer # obrigatório, >= 1
kind: schedule # obrigatório, literal "schedule"
lumo: v2 # obrigatório, literal "v2"
tenantId: integer # obrigatório, >= 1
---
# ── body ──────────────────────────────────────────────────
nome: string # obrigatório, mínimo 1 caractere
ativo: boolean # obrigatório
timezone: string # obrigatório, nome IANA (ex: America/Sao_Paulo)
tags: [string]
flows: # obrigatório. executados em sequência
- flow_etl_id: integer # obrigatório
context: string # obrigatório: Total | Incremental | Temporal | Temporal:Days:<n>
triggers: # obrigatório. quando o agendamento dispara
# Hour / Minute: a cada N unidades, dentro de uma janela diária
- type: Hour # Hour | Minute. Minute exige schedulingGranularity=minutes no tenant
period: integer # obrigatório, >= 1
start_when: string # obrigatório, ISO 8601 UTC (ex: 2026-01-01T07:00:00.000Z)
start_time: "HH:MM" # obrigatório, início da janela
end_time: "HH:MM" # obrigatório, fim da janela
# Day: uma vez por dia
- type: Day
start_when: "HH:MM" # obrigatório, hora do dia
# Week: num dia da semana
- type: Week
period: integer # obrigatório, 0=domingo até 6=sábado
start_when: "HH:MM" # obrigatório
# Month: num dia do mês
- type: Month
period: integer # obrigatório, 1 a 31 (dia do mês, não intervalo)
start_when: "HH:MM" # obrigatório
# Mudança de dados (CDC): sonda a origem em vez de esperar um horário
- type: CDC
period: integer # obrigatório, EM SEGUNDOS para este tipo, 5 a 3600
# (nos outros tipos acima, period é hora/minuto/dia; aqui não)
start_when: string # obrigatório, ISO 8601 completo (não aceita "HH:MM" aqui)
start_time: "HH:MM" # opcional, início da janela em que a sondagem roda
end_time: "HH:MM" # opcional, fim da janela
config: # obrigatório
kind: query-scalar # único valor aceito hoje
credential: string # chave da credencial da sonda; pode ser outra além das dos flows
sql: string # SELECT ou WITH, instrução única, até 8 KB, 1 linha x 1 coluna
timeout_seconds: integer # opcional, default 5, precisa ser menor que period
parallel_lane: boolean # opcional, default false. Roda fora do limite de execuções
# simultâneas do agente. Vale para qualquer tipo de gatilho acima.start_when muda de formato conforme o type. Em Hour e Minute, é um timestamp ISO completo em UTC. Em Day, Week e Month, é apenas a hora do dia, no formato HH:MM. Em CDC, volta a ser um timestamp ISO completo, mas por um motivo diferente (o agente não usa este campo para decidir quando sondar); veja a especificação de start_when mais abaixo.
Em Month, period é o dia do mês, e não um intervalo de meses. O dia 31 é ajustado para o último dia válido nos meses mais curtos.
Em CDC, period está em segundos, não em horas, minutos ou dias. É o único tipo em que a unidade muda para uma escala menor; confira sempre o type antes de reaproveitar um valor de period de outro gatilho.
# schedules/carga-diaria--2478.yaml
# yaml-language-server: $schema=https://docs.horusbi.com.br/schemas/v2/schedule.schema.json
id: 2478
kind: schedule
lumo: v2
tenantId: 853
---
nome: Carga Diária
ativo: true
# Nome IANA, obrigatório. Sem ele, o horário do gatilho fica ambíguo entre
# UTC e local.
timezone: America/Sao_Paulo
# Executados em sequência: o segundo começa quando o primeiro termina.
# Carregue as dimensões antes dos fatos.
flows:
- flow_etl_id: 44547
context: Total # dimensão pequena: apaga tudo e recarrega
- flow_etl_id: 44531
# Recarrega os últimos 31 dias. A tabela precisa ser key_type: unique,
# senão a janela recarregada duplica as linhas a cada execução.
context: Temporal:Days:31
triggers:
# A cada 2 horas, entre 07:00 e 19:00, no fuso acima.
- type: Hour
period: 2
start_when: "2026-01-01T07:00:00.000Z"
start_time: "07:00"
end_time: "19:00"
tags: [producao]id Tipo: integer (>= 1) · Obrigatório: sim
kind Tipo: string · Obrigatório: sim · Valor: schedule
lumo Tipo: string · Obrigatório: sim · Valor: v2
tenantId Tipo: integer (>= 1) · Obrigatório: sim
nome Tipo: string (mínimo 1 caractere) · Obrigatório: sim
Nome do agendamento. Descreva o que ele faz e como carrega, por exemplo Vendas Diário Temporal 7d.
ativo Tipo: boolean · Obrigatório: sim
false desliga o agendamento sem apagá-lo. Equivale a lumo schedule pause.
timezone Tipo: string (mínimo 1 caractere) · Obrigatório: sim
Nome de fuso IANA, como America/Sao_Paulo. Define quando os gatilhos disparam. É obrigatório para não deixar o horário ambíguo entre UTC e local.
flows Tipo: array de objetos · Obrigatório: sim
Flows executados, em sequência. Cada item exige flow_etl_id e context. Veja Especificação: flow do agendamento.
triggers Tipo: array de objetos · Obrigatório: sim
Quando o agendamento dispara. Veja Especificação: trigger.
parallel_lane Tipo: boolean · Obrigatório: não · Default: false
Roda este agendamento fora do limite de execuções simultâneas do agente, numa pista própria. Vale para o agendamento inteiro, qualquer que seja o tipo de gatilho (inclusive CDC), não só as sondagens. Use só em agendamentos leves, para que uma carga pesada de outro agendamento não segure este atrás dela na fila.
O teto da pista paralela (parallel_lane_slots) é configurado por agente, não neste arquivo. Um teto igual a 0 desliga a pista, não significa "sem limite".
tags Tipo: array de string · Obrigatório: não · Default: []
Cada item de flows.
flow_etl_id Tipo: integer (>= 1) · Obrigatório: sim
Id do flow. O flow precisa estar publicado num dw-desk.
context Tipo: string · Obrigatório: sim
Como o flow carrega nesta execução.
| Valor | Comportamento |
|---|---|
Total | Apaga tudo e recarrega tudo. |
Incremental | Acrescenta ou atualiza, sem apagar. |
Temporal | Recarrega a janela padrão, expandida pelo servidor com o temporal_value do flow. |
TemporalFuture | Igual ao Temporal, mas para a frente. Também expandida pelo servidor. |
Temporal:Days:<n> | Recarrega os últimos <n> dias. |
Temporal:Future:<n> | Recarrega os próximos <n> dias. |
Temporal:Month:<M>-<AAAA> | Recarrega um mês do calendário, por exemplo Temporal:Month:3-2026. |
Temporal:Year:<AAAA> | Recarrega um ano do calendário. Temporal:Year:Current resolve para o ano corrente. |
KeySweep | Não é uma carga. Roda a consulta de chaves do flow e marca como excluído, na tabela de destino, tudo que a origem não devolveu. |
context: Temporal:Days:31Temporal e TemporalFuture são as únicas formas curtas. Month e Year não têm forma curta e precisam ser escritas expandidas.
O context escolhe a janela de extração; o load_type do flow decide o predicado de exclusão. Os dois precisam concordar, e o lumo lint cobra isso.
context: KeySweep KeySweep é o contexto da sincronização de exclusões. Ele não carrega dado: o agente roda apenas a consulta de key_sweep do flow, lê da origem só as chaves ainda existentes e marca como excluído, no destino, tudo que não veio.
Exige que o flow tenha load_type: Incremental e key_sweep configurado. Sem os dois, o servidor recusa no push.
flows:
# A carga do dado, de hora em hora.
- flow_etl_id: 44531
context: Incremental
# Num agendamento SEPARADO, uma vez por noite: só a varredura.
- flow_etl_id: 44531
context: KeySweepWARNING
A consulta de chaves precisa devolver todas as chaves vivas na origem, sem filtro de período. Tudo que não vier é marcado como excluído, sem erro nenhum. Uma consulta janelada apaga o histórico anterior à janela, e isso não se recupera sozinho. Veja Sincronização de Exclusões.
Exige agente 1.27.0 ou mais novo.
Uma janela Temporal recarregada sobre uma tabela key_type: duplicate duplica as linhas a cada execução. Use unique.
Cada item de triggers. As chaves exigidas mudam conforme type.
type Tipo: string · Obrigatório: sim · Valores: Hour, Minute, Day, Week, Month, CDC
| Valor | Dispara | Exige |
|---|---|---|
Hour | A cada period horas, dentro da janela. | period, start_when, start_time, end_time |
Minute | A cada period minutos, dentro da janela. | period, start_when, start_time, end_time |
Day | Uma vez por dia. | start_when |
Week | Num dia da semana. | period, start_when |
Month | Num dia do mês. | period, start_when |
CDC | A cada period segundos, roda a consulta de config.sql e dispara quando o valor devolvido é diferente do anterior (não é "maior que": um valor que diminui também dispara). Rótulo na tela: Mudança de dados (CDC). | period, start_when, config |
Minute só funciona em tenant com schedulingGranularity igual a minutes.
CDC é para origem sem CDC nativo acessível (Oracle, ODBC genérico, Firebird, Informix, IRIS): em vez de rodar o flow por horário e descobrir se algo mudou pela extração completa, uma sonda leve responde essa pergunta antes. É o mesmo mecanismo do sql_trigger_value do Looker. Ele não detecta linha excluída (ela permanece no data warehouse até uma carga Total) e não informa ao flow quais registros mudaram: ele só dispara, e o flow carrega do jeito que já carrega hoje.
period Tipo: integer · Obrigatório: em Hour, Minute, Week, Month e CDC
O significado muda conforme o type. Confira sempre o type antes de copiar um valor de period de um gatilho para outro, porque a unidade não é a mesma.
type | Significado de period | Faixa |
|---|---|---|
Hour | Intervalo em horas. | >= 1 |
Minute | Intervalo em minutos. | >= 1 |
Week | Dia da semana, com 0 igual a domingo. | 0 a 6 |
Month | Dia do mês. | 1 a 31 |
CDC | Intervalo em segundos entre uma sondagem e outra. Único tipo em que period não é hora, minuto nem dia. | 5 a 3600 |
Em CDC, period: 5 (o mínimo da faixa) só passa no lumo lint; o servidor recusa no push. timeout_seconds precisa ser menor que period, e o default de timeout_seconds é 5. Com o default, o menor period que funciona é 6. Para usar period: 5, baixe timeout_seconds para menos de 5.
start_when Tipo: string · Obrigatório: sim
Em Hour e Minute, é um timestamp ISO 8601 em UTC, como 2026-01-01T07:00:00.000Z, que marca quando o agendamento passa a valer.
Em Day, Week e Month, é apenas a hora do dia, no formato HH:MM.
Em CDC, é de novo um timestamp ISO 8601 completo (não aceita HH:MM aqui). Detalhe que vale saber: o agente não usa este campo para decidir quando sondar, apenas quem limita isso é start_time/end_time. start_when é exigido em CDC só por consistência com os demais tipos de gatilho.
start_time Tipo: string HH:MM · Obrigatório: em Hour e Minute · Opcional: em CDC
Início da janela diária em que o gatilho pode disparar. Em CDC, restringe quando a sondagem roda; fora da janela, o detector fica parado. Sem start_time/end_time, a sondagem roda o dia inteiro.
end_time Tipo: string HH:MM · Obrigatório: em Hour e Minute · Opcional: em CDC
Fim da janela diária.
config Tipo: object · Obrigatório: em CDC
Configuração da sonda. Só existe no tipo CDC; os demais tipos de gatilho não têm este campo. Veja Especificação: config da sonda CDC.
Campos de config, exigido pelo trigger type: CDC.
kind Tipo: string · Obrigatório: sim · Valores: query-scalar
Modo de detecção. Hoje só existe query-scalar: compara o valor devolvido pela consulta de sql com o da sondagem anterior. O campo existe para modos futuros (por chave, por log lógico do banco) entrarem sem precisar de um type de gatilho novo.
O gatilho decide quando rodar e não passa ao flow a lista de registros alterados; o que trazer continua sendo do flow, pelo tipo de carga. É decisão de desenho, não pendência: veja por que o gatilho não passa a lista de registros alterados.
credential Tipo: string (mínimo 1 caractere) · Obrigatório: sim
Chave da credencial que a sonda usa para conectar (mesmo picker do editor de flow; descubra com lumo list credential). Pode ser diferente das credenciais usadas pelos flows do agendamento, o que é útil para dar à sonda um usuário próprio.
Use uma credencial somente leitura para a sonda. A checagem de "só SELECT/WITH" descrita em sql é textual, feita sobre o texto da consulta; ela não é uma garantia de segurança. Existem formas de escrever que não usam nenhuma palavra reconhecível como escrita (nextval, setval, lo_import e funções do usuário com efeito colateral são exemplos que passam pela checagem). A defesa real contra isso é a credencial somente leitura, não a validação textual.
sql Tipo: string (máximo 8192 bytes) · Obrigatório: sim
Consulta de sondagem. Precisa ser:
; fora de um literal de texto);SELECT ou WITH (comentários antes não atrapalham);As duas primeiras regras são validadas ao salvar. A terceira só é possível checar em tempo de execução: se a sondagem devolver mais de uma linha, nenhuma coluna ou mais de oito, ela não dispara, não avança e é reportada como erro de configuração, com mensagem distinta de erro de conexão.
O sistema recusa, pelo texto, palavras de escrita óbvias (INSERT, UPDATE, DELETE, DROP e afins). Essa recusa é textual, não é fronteira de segurança; veja a recomendação de credencial somente leitura em credential acima.
sql: SELECT MAX(UPDATED_AT) FROM PEDIDOSCom duas ou mais colunas, a sonda dispara quando qualquer uma delas muda. Isso existe para uma consulta em particular:
sql: SELECT COUNT(*), MAX(UPDATED_AT) FROM PEDIDOSÉ a única forma de ver os três casos na mesma sonda. A contagem muda quando uma linha entra ou sai, e o maior valor da coluna muda quando uma linha é alterada; cada uma sozinha é cega para o que a outra vê.
São duas colunas em vez de um valor concatenado porque concatenar amarra a consulta a um dialeto: || no Oracle e no PostgreSQL, + no SQL Server, CONCAT no MySQL. Numa conexão ODBC o banco de destino sequer é conhecido pelo Lumo, então não haveria dialeto a escolher.
O valor guardado passa a ser a combinação das colunas. Na tela ele aparece com os valores separados por vírgula; internamente é uma string só, e a comparação continua sendo por diferença.
Versão do agente
Sonda de mais de uma coluna exige o agente 1.26.0 ou mais novo. Contra um agente anterior a sondagem falha como erro de configuração, e o agendamento não dispara.
timeout_seconds Tipo: integer · Obrigatório: não · Default: 5
Precisa ser menor que period, para uma sondagem não encavalar na seguinte. Uma sondagem que estoura o timeout não dispara e não avança; conta como erro e tenta de novo no próximo ciclo.
# schedules/cdc-pedidos--2481.yaml
# yaml-language-server: $schema=https://docs.horusbi.com.br/schemas/v2/schedule.schema.json
id: 2481
kind: schedule
lumo: v2
tenantId: 853
---
nome: Pedidos CDC
ativo: true
timezone: America/Sao_Paulo
flows:
- flow_etl_id: 44560
context: Incremental
triggers:
# Sonda a cada 10 segundos, só entre 07:00 e 22:00. Dispara quando o
# valor devolvido pela consulta mudar.
- type: CDC
period: 10
start_when: "2026-01-01T00:00:00.000Z"
start_time: "07:00"
end_time: "22:00"
config:
kind: query-scalar
credential: oracle-hosp # pode ser diferente da credencial usada pelos flows
sql: SELECT MAX(UPDATED_AT) FROM PEDIDOS
timeout_seconds: 5
# Fora do limite de execuções simultâneas do agente: útil porque a sonda
# em si é barata, mesmo que o dataflow disparado não seja.
parallel_lane: true
tags: [producao]| Campo | O que é |
|---|---|
version | Versão do recurso. |
criado_em, criado_por, publicado_em, publicado_por | Auditoria. |