Pular para o conteúdo principal
Um evento se move pelo Streaming Hub em três estágios: o hub ingere o evento a partir do stream interno, faz o match dele contra as suas assinaturas e o despacha para cada destino que deu match. Esta página percorre cada estágio e as garantias de entrega que decorrem dele.

Ingerindo eventos do stream


O Streaming Hub consome o stream da plataforma como mensagens CloudEvents 1.0 em modo de conteúdo binário: os atributos de contexto do CloudEvents trafegam nos cabeçalhos do registro Kafka (cada um com o prefixo ce-) e o corpo do evento é o valor do registro. O hub lê o roteamento e a identidade a partir dos cabeçalhos sem desserializar o payload. Todo registro que o hub aceita precisa carregar este conjunto de contexto: Para cada registro, o hub retorna um de três veredictos: O tenant admitido na ingestão vem apenas do atributo ce-tenantid validado que o parser extraiu. Um tenant desconhecido ou inativo é descartado no gate do roster — o único ponto em que o isolamento por tenant é imposto no caminho de ingestão.
Três strings relacionadas se parecem, mas são distintas — nunca as confunda:
  • ce-type — o tipo CloudEvents: studio.lerian.<resource>.<event> (por exemplo, studio.lerian.transaction.posted).
  • Tópico Kafka — onde o evento trafega no barramento interno. Não há um prefixo único válido para toda a plataforma: cada produtor tem seu próprio namespace de tópico. O Midaz roteia para tópicos explícitos com um segmento de serviço fixo — os eventos do ledger trafegam em lerian.streaming.ledger_<resource>.<event>, com o serviço incorporado ao primeiro segmento (assim transaction.posted trafega em lerian.streaming.ledger_transaction.posted) e qualquer hífen no recurso ou no evento convertido em um sublinhado no tópico (balance.config-changed trafega em lerian.streaming.ledger_balance.config_changed). Outros produtores — o Consignado e os comandos entre produtos — derivam seu namespace de seu ce-source.
  • X-Lerian-Event-Type — o tipo estampado em um webhook entregue: apenas o final <resource>.<event> do ce-type (transaction.posted). Espelha a identidade do ce-type, não o tópico Kafka — não carrega nenhum segmento de serviço do produtor (sem a incorporação ledger_).
Veja a visão geral de event streaming para o contrato completo do wire.

Deduplicação consume-once


O stream interno é at-least-once, então o mesmo registro pode chegar mais de uma vez. No caminho de entrada para o inbox de eventos, o hub deduplica por ce-id: um id duplicado não grava nada e é contabilizado como um descarte por dedup. Os registros são persistidos por partição Kafka em uma única transação, e a posição no stream para uma partição é confirmada apenas depois que a gravação daquela partição é confirmada — de modo que uma falha em uma partição nunca perde nem confirma em duplicidade eventos em outra.

Match de assinaturas


Uma vez que um evento é armazenado, o hub resolve quais das suas assinaturas devem recebê-lo. O match de assinaturas é interno e catalog-free: ele avalia cada evento contra as suas assinaturas por (tenant, tipo de evento, schema major) diretamente, sem consultar o catálogo de eventos. Um tipo de evento que nenhuma assinatura deseja produz zero entregas — um resultado correto, não um erro. Uma assinatura é admitida no match somente quando está enabled e em verification_state = active. Essas são duas condições independentes — veja o modelo de assinatura — e o match exige ambas.

Despachando para os seus destinos


Para cada match, o hub cria um job de entrega e o entrega a um pool de workers (oito workers por padrão). Os workers reivindicam jobs vencidos de forma atômica com um lease curto e se intercalam entre tenants, de modo que o backlog de nenhum tenant faz os outros passarem fome. Cada worker carrega o payload armazenado, decripta em memória o segredo de assinatura ou a credencial do destino, e faz exatamente uma tentativa de entrega ao sink. A entrega é at-least-once: o hub pode entregar o mesmo evento mais de uma vez (através de retentativas ou de re-entregas após o reinício de um worker). Toda entrega carrega um X-Lerian-Event-Id estável (o ce-id) para você deduplicar, e um X-Lerian-Delivery-Id por tentativa que muda a cada retentativa. Trate um X-Lerian-Event-Id repetido como uma duplicata e confirme-o sem reprocessar. Veja Consumindo eventos para o lado do consumidor desse contrato.

Retentativas e back-off


Quando uma tentativa falha, o hub agenda a próxima em uma curva de back-off fixa com full jitter:
A curva abrange cerca de 28 horas ao longo dos seus oito passos. Cada assinatura pode sobrescrevê-la com o seu próprio cronograma (até 12 passos, cada um limitado a 10 horas); uma sobrescrita malformada recai na curva padrão em vez de falhar a entrega.

Dead-lettering


Um evento cujas retentativas se esgotaram é enviado para dead-letter — o hub para de tentá-lo e registra o resultado terminal. Um job que, em vez disso, fica derrubando um worker no meio da tentativa — nunca registrando um resultado — é recuperado um número limitado de vezes (cinco por padrão) e então enviado para dead-letter como poison, de modo que um único job tóxico jamais ocupe um worker para sempre.

Circuit breaker


Cada par (tenant, destino) tem um circuit breaker. Quando um destino falha repetidamente, seu breaker abre e os jobs seguintes para aquele destino são descartados — reagendados sem uma tentativa — para que um único endpoint quebrado não queime a capacidade dos workers nem martele um alvo em dificuldades. O breaker se recupera sozinho assim que o destino volta a ter sucesso.

Desativando automaticamente um destino quebrado


Um destino que permanece quebrado por muito tempo é desativado automaticamente. A desativação automática só dispara quando o span de falha aberto é ao mesmo tempo:
  • sustentado — vem falhando por pelo menos a janela de falha (120 horas por padrão); e
  • espalhado — pelo menos 12 horas separam a primeira e a última falha do span.
Ambos os gates precisam valer, e uma única entrega bem-sucedida limpa o span, de modo que uma pane breve nunca se acumula em direção ao veredicto. Quando a desativação automática dispara, ela vira a flag enabled da assinatura para false — nunca toca em verification_state. A entrega para (o match exige enabled), e o hub registra o motivo. Você recupera uma assinatura desativada automaticamente com POST /v1/subscriptions/:id/verify, que re-sonda o destino e, em caso de sucesso, o reabilita no lugar. A desativação automática é governada por um kill switch (STREAMING_HUB_AUTODISABLE_ENABLED), então um operador pode entregá-la desligada. Veja recuperando uma assinatura desativada automaticamente.

Garantias de ordenação


O stream interno é particionado por tenant, então os eventos de um tenant normalmente trafegam por uma única partição e o hub preserva a ordem first-in, first-out deles de ponta a ponta. O hub atribui e deduplica pelos cabeçalhos CloudEvents, não pela chave do registro Kafka, então um produtor que distribui (aplica salt) um tenant quente entre várias partições muda apenas o posicionamento físico — o hub ainda atribui e deduplica corretamente. O único trade-off é a ordenação: os eventos de um tenant com salt abrangem múltiplas partições sem garantia de ordem entre partições, então esse tenant abre mão do FIFO estrito. A sequência de chegada que o hub atribui reflete a ordem em que os eventos chegaram ao hub, não a ordem em que foram produzidos. Um tenant sem salt mantém o FIFO de partição única por toda a extensão.

Próximos passos


Gerenciando assinaturas

O modelo de assinatura, os fluxos de onboarding e a rotação de segredos.

Consumindo eventos

Verifique assinaturas, deduplique e consuma eventos por pull.