0.1.13: one rule for taking an event, and no handler left by a refused subscribe (hq issue 276)
A handler takes an event by returning and asks for it again by throwing; any mesh/event answer but an error is taken. Written down in the README where event handling is, with what follows for a handler: throw only when the work was not done, and be safe to run twice. Both SDKs added the handler before asking the runtime and kept it when the runtime refused, so a module that asks again until it is taken (every Go consumer does) ran its handler once per attempt for every event. A refused subscribe now removes its handler; one the Go runtime did not answer in time is kept, since the runtime may have bound it.
This commit is contained in:
@@ -65,6 +65,10 @@ export async function emit<T>(type: string, body: T, opts: EmitOptions = {}): Pr
|
||||
* React to events whose type matches a topic pattern (`*` one segment, `#` any). The audit logger
|
||||
* is just `on("#", …)`. The handler receives the reconstructed event — its metadata read back from
|
||||
* the headers, its body the domain payload.
|
||||
*
|
||||
* **The handler takes the event by returning and asks for it again by throwing** — nothing else
|
||||
* counts (README, "Taking an event"). Throw only when the work was not done; delivery is
|
||||
* at-least-once, so make the work safe to repeat or skip an `id` already done.
|
||||
*/
|
||||
export async function on<T>(pattern: string, handler: (event: Event<T>) => Promise<void>): Promise<() => void> {
|
||||
return broker().subscribe<T>(pattern, async (envelope) => {
|
||||
|
||||
+10
-2
@@ -106,11 +106,19 @@ function startSession(): Session {
|
||||
subscribe: (async <T>(pattern: string, handler: (env: Envelope<T>) => Promise<void>) => {
|
||||
const listener = { pattern, handler: handler as (env: Envelope<unknown>) => Promise<void> };
|
||||
listeners.push(listener);
|
||||
await ask("mesh/subscribe", { pattern });
|
||||
return () => {
|
||||
const remove = (): void => {
|
||||
const at = listeners.indexOf(listener);
|
||||
if (at >= 0) listeners.splice(at, 1);
|
||||
};
|
||||
try {
|
||||
await ask("mesh/subscribe", { pattern });
|
||||
} catch (err) {
|
||||
// Refused: nothing is bound, and a handler left behind would be handed each event twice once
|
||||
// the module asks again (novox/hq issue 276).
|
||||
remove();
|
||||
throw err;
|
||||
}
|
||||
return remove;
|
||||
}) as Broker["subscribe"],
|
||||
close: async () => {},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user