Arcane.Eventos
Publicar e assinar sem as duas partes se conhecerem, contexto por thread e fila de trabalho.
Duas partes de um programa que precisam conversar sem se conhecer. O Kiln tem Sala para WebSocket e o Lavra tem Fonte para assinatura — os dois resolvem o mesmo problema para um transporte específico, e faltava a peça geral.
Emissor#
dataforge
adopt Arcane.Eventos as Eventos
loja := Eventos.emissor("loja")
loja.ao("venda", lambda pedido: gravar_nota(pedido))
loja.ao("venda", lambda pedido: avisar_estoque(pedido))
quantos := loja.emitir("venda", pedido)O ouvinte que quebra sai#
Um ouvinte quebrado que continua inscrito quebra a cada evento, para sempre, e some no meio do log. Ele é removido, e o erro vai para a lista:
dataforge
out loja.erros // [{evento: venda, erro: …, quando: …}]
out loja.resumo() // {emitidos: 12, entregues: 20, ouvintes: {…}, erros: 1}Curinga e uma vez#
dataforge
loja.ao("*", lambda nome: registrar(nome)) // ouve tudo
loja.uma_vez("pronto", lambda: comecar()) // ouve o próximo, e sai
cancelar := loja.ao("venda", tratar)
cancelar() // desinscreveO contexto atravessa as camadas#
O id do pedido, quem pediu, o rastro — sem passar por parâmetro em cada camada:
dataforge
action atender(req):
yield Eventos.com_contexto({"pedido": req["id"], "quem": req["usuario"]},
lambda => processar())
// dez camadas abaixo, sem ter recebido nada
action gravar_log(texto):
Log.info(texto, {"pedido": Eventos.por("pedido")})Fila de trabalho#
A diferença para o emissor: o emissor entrega agora, na thread de quem emitiu. A fila aceita e devolve o controle — quem publicou não espera o trabalho terminar.
dataforge
envios := Eventos.fila(lambda mensagem: Email.enviar(mensagem, servidor),
operarios := 4)
route POST "/cadastro":
criar(body)
envios.publicar(boas_vindas(body["email"])) // não espera
respond 201 json {"ok": yes}dataforge
envios.esperar(prazo := 5.0) // num teste: espera esvaziar
out envios.resumo() // {feitos: 40, falhos: 0, pendentes: 0, operarios: 4}