Eventos do TermoWebhook
Como os apps da Termotubos publicam e recebem eventos pelo hub, com contratos tipados gerados dos esquemas cadastrados.
O TermoWebhook é o hub de eventos da Termotubos. Um app publica (colaborador.criado), o hub guarda e entrega a todos os apps assinantes, assinando cada entrega com Ed25519.
| Recurso | TypeScript | Rust |
|---|---|---|
| Contratos tipados dos eventos | sim (tipos e { aplicativo, tipo, versao }) | sim (structs com o trait Evento) |
| Publicar na hora | não | publicar_evento_no_hub_agora (feature webhook_publicar) |
| Fila de saída no Postgres do app | não | guardar_evento_para_publicar_na_mesma_transacao (feature webhook_postgres) |
| Receber entregas conferidas | não | receber_evento_conferido_do_hub (feature webhook_receber) |
| Rotas da API do hub (painel) | sim | sim. Veja TermoWebhook |
O fluxo
Guardar na mesma transação
No model, dentro da transação que já grava a mudança, o app guarda o evento numa tabela local (termo_eventos_pendente). Se a transação falhar, o evento some junto: nunca existe evento de algo que não aconteceu.
Enviar em background
Uma tarefa iniciada ao subir o app lê a tabela (aviso imediato por LISTEN/NOTIFY, com varredura a cada 5 s) e publica no hub com Authorization: Bearer <token do aplicativo>, com novas tentativas.
Receber conferido
O hub entrega no endereço cadastrado do app assinante. O app confere a assinatura com a chave pública do hub e lê o evento tipado.
Credencial
Para publicar e para receber, basta o segredo do app gerado no TermoAuth (veja Credencial). O hub reconhece quem publica pelo token de aplicativo, e o destino assinado em cada entrega é o id do app no TermoAuth (identificador_do_aplicativo()). Sem segredo, os eventos esperam na fila e as entregas recebidas respondem 503, então o hub reenvia.
Exemplo completo
use termo_core::webhook::eventos::termo_auth::ColaboradorCriadoV2;
// Ao subir, uma vez (feature webhook_postgres):
termo_core::webhook::iniciar_envio_automatico_dos_eventos_guardados(
&pool,
termo_core::webhook::ConfiguracaoDoHub::carregar_do_ambiente_atual(),
)
.await?;
// No model, dentro da transação que já grava a mudança:
termo_core::webhook::guardar_evento_para_publicar_na_mesma_transacao(&mut *transacao, id.to_string(), ColaboradorCriadoV2 { /* ... */ }).await?;
// Na rota que recebe as entregas (feature webhook_receber):
let evento = termo_core::webhook::receber_evento_conferido_do_hub::<ColaboradorCriadoV2>(&cabecalhos, &corpo).await?;