Signals do repositório¶
Reagir a persistência — invalidar cache, enfileirar evento, sincronizar índice de busca, escrever auditoria — sem envolver todo call site à mão. O call site que alguém esquecer é o bug.
import { onSignal } from "tempest-db-js";
onSignal(User, "postSave", async ({ row, session }) => {
await cache.del(`user:${row.id}`);
});
Os quatro pontos¶
| Signal | Quando | O que row traz |
|---|---|---|
preSave |
antes do INSERT/UPDATE | o que você passou (insert) ou a linha já com o patch (update) |
postSave |
depois | a linha armazenada — id gerado incluído |
preDelete |
antes do DELETE | a linha como estava; é a última chance de vê-la |
postDelete |
depois | a mesma imagem de antes |
Disparam em create, createMany, update e delete do BaseRepository — por
linha, mesmo num lote.
Vetar uma escrita¶
onSignal(Order, "preSave", ({ row }) => {
if (row.total < 0) throw new ValidationError("total negativo");
});
Handler que lança em preSave/preDelete impede a escrita: o erro sobe para quem
chamou. Não é sugestão — um veto que pudesse ser engolido não seria veto.
O handler roda dentro da sua transação¶
O payload traz a mesma session da escrita. Handler que escreve comita junto:
onSignal(Order, "postSave", async ({ row, session }) => {
await new BaseRepository(OutboxEvent, session).create({ topic: "order.created", ... });
});
await session.transaction(async () => {
await orders.create(order); // linha + evento, ou nenhum dos dois
});
Sem handler, sem custo
update/delete recebem filtro, não linha — para entregar a linha ao handler é
preciso lê-la antes. Esse SELECT extra só acontece quando há handler registrado
(hasHandlers), então quem não usa signals não paga nada.
activeRecord não dispara
Os signals estão no caminho do BaseRepository. O activeRecord escreve pelos
builders direto e não dispara — se você mistura os dois, faça a escrita
observável passar pelo repository.
Limpe entre testes
Handler registrado é global e vive até o processo morrer. clearSignals() (ou
clearSignals(Model)) num afterEach evita um teste enxergar o handler do outro.
Recapitulando¶
onSignal(Model, signal, handler)devolve a função que desregistra.preSave/preDeleteque lançam vetam a escrita.- O handler recebe a session da escrita, então participa da transação.
hasHandlersé o que mantém o custo em zero para quem não usa. 🚀