Skip to main content
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. O hub assina apenas os tópicos de fatos por aplicação do v3:
ce-source é um único segmento em minúsculas, sem pontos, que usa letras, dígitos, sublinhados ou hífens. O tópico não carrega recurso, evento nem sufixo do major do schema; o hub faz o dispatch pelos cabeçalhos CloudEvents. Tópicos de comandos (.commands) e de dead letters (.dlq) ficam fora do conjunto. Os tópicos de fatos por aplicação do Midaz, Tracer, Matcher, Lender e Consignado agora atendem a esse contrato do conjunto acompanhado. Um segundo consumidor lê os tópicos .dlq que os produtores escrevem. Esse consumidor serve apenas para observabilidade. A gramática do conjunto exclui uma cauda .dlq, então um registro de dead-letter nunca se torna uma entrega para uma das suas assinaturas. Os operadores leem esses registros com GET /admin/dlq — veja Análise forense de DLQ. 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. Não há gate de roster na ingestão. Eventos armazenados só dão match com assinaturas do mesmo tenant.
Três strings relacionadas se parecem, mas são distintas — nunca as confunda:
  • ce-type — o tipo CloudEvents qualificado pela fonte: studio.lerian.<source>.<resource>.<event> (por exemplo, studio.lerian.lender.loan_application.approved).
  • Tópico Kafka — um tópico de fatos v3 por aplicação: lerian.streaming.<source> (por exemplo, lerian.streaming.lender). O recurso, o evento e o major do schema não aparecem no tópico.
  • X-Lerian-Event-Type — a chave simples <resource>.<event> estampada em um webhook entregue (loan_application.approved). Ela omite deliberadamente o produtor. Use o pin origin da assinatura quando a mesma chave puder vir de mais de uma aplicação.
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


Depois que um evento é armazenado, o hub resolve quais assinaturas devem recebê-lo. O match é interno e catalog-free: ele avalia cada evento diretamente por (tenant, origem, tipo de evento, major do schema). A dimensão origin é opcional na assinatura; quando ausente, a mesma chave de evento de qualquer aplicação produtora pode dar match. Um 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.