Pular para o conteúdo

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()                                        // desinscreve

O 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}