feat(redis): add channel prefix and error handling

This commit is contained in:
2026-05-08 06:33:15 +00:00
parent 7c12b40ed2
commit 392682c7be
6 changed files with 258 additions and 28 deletions

View File

@@ -41,6 +41,7 @@ export type CreateRedisEventTargetArgs = {
stringify: (message: unknown) => string;
parse: (message: string) => unknown;
};
prefix?: string;
};
export function createRedisEventTarget<TEvent extends TypedEvent>(
@@ -49,6 +50,7 @@ export function createRedisEventTarget<TEvent extends TypedEvent>(
const { publishClient, subscribeClient } = args;
const serializer = args.serializer ?? JSON;
const prefix = args.prefix ?? "";
const callbacksForTopic = new Map<string, Set<EventListener>>();
@@ -58,7 +60,15 @@ export function createRedisEventTarget<TEvent extends TypedEvent>(
return;
}
const envelope = serializer.parse(message) as EventEnvelope;
let envelope: EventEnvelope;
try {
envelope = serializer.parse(message) as EventEnvelope;
} catch {
console.warn(
`Failed to parse message on channel "${channel}": ${message}`,
);
return;
}
const event = new CustomEvent(channel, {
detail: envelope,
}) as TEvent;
@@ -70,18 +80,20 @@ export function createRedisEventTarget<TEvent extends TypedEvent>(
(subscribeClient as Redis).on("message", onMessage);
function addCallback(topic: string, callback: EventListener) {
let callbacks = callbacksForTopic.get(topic);
const prefixedTopic = prefix + topic;
let callbacks = callbacksForTopic.get(prefixedTopic);
if (callbacks === undefined) {
callbacks = new Set();
callbacksForTopic.set(topic, callbacks);
callbacksForTopic.set(prefixedTopic, callbacks);
subscribeClient.subscribe(topic);
subscribeClient.subscribe(prefixedTopic);
}
callbacks.add(callback);
}
function removeCallback(topic: string, callback: EventListener) {
const callbacks = callbacksForTopic.get(topic);
const prefixedTopic = prefix + topic;
const callbacks = callbacksForTopic.get(prefixedTopic);
if (callbacks === undefined) {
return;
}
@@ -89,8 +101,8 @@ export function createRedisEventTarget<TEvent extends TypedEvent>(
if (callbacks.size > 0) {
return;
}
callbacksForTopic.delete(topic);
subscribeClient.unsubscribe(topic);
callbacksForTopic.delete(prefixedTopic);
subscribeClient.unsubscribe(prefixedTopic);
}
return {
@@ -103,7 +115,7 @@ export function createRedisEventTarget<TEvent extends TypedEvent>(
},
dispatchEvent(event: TEvent) {
publishClient.publish(
event.type,
prefix + event.type,
serializer.stringify(event.detail),
);
return true;