@graphql-yoga/redis-event-target
Version:
Do distributed GraphQL subscriptions over Redis.
59 lines (58 loc) • 2.15 kB
JavaScript
import { CustomEvent } from '@whatwg-node/events';
export function createRedisEventTarget(args) {
const { publishClient, subscribeClient } = args;
const serializer = args.serializer ?? JSON;
const callbacksForTopic = new Map();
function onMessage(channel, message) {
const callbacks = callbacksForTopic.get(channel);
if (callbacks === undefined) {
return;
}
const event = new CustomEvent(channel, {
detail: message === '' ? null : serializer.parse(message),
});
for (const callback of callbacks) {
callback(event);
}
}
subscribeClient.on('message', onMessage);
function addCallback(topic, callback) {
let callbacks = callbacksForTopic.get(topic);
if (callbacks === undefined) {
callbacks = new Set();
callbacksForTopic.set(topic, callbacks);
subscribeClient.subscribe(topic);
}
callbacks.add(callback);
}
function removeCallback(topic, callback) {
const callbacks = callbacksForTopic.get(topic);
if (callbacks === undefined) {
return;
}
callbacks.delete(callback);
if (callbacks.size > 0) {
return;
}
callbacksForTopic.delete(topic);
subscribeClient.unsubscribe(topic);
}
return {
addEventListener(topic, callbackOrOptions) {
if (callbackOrOptions != null) {
const callback = 'handleEvent' in callbackOrOptions ? callbackOrOptions.handleEvent : callbackOrOptions;
addCallback(topic, callback);
}
},
dispatchEvent(event) {
publishClient.publish(event.type, event.detail === undefined ? '' : serializer.stringify(event.detail));
return true;
},
removeEventListener(topic, callbackOrOptions) {
if (callbackOrOptions != null) {
const callback = 'handleEvent' in callbackOrOptions ? callbackOrOptions.handleEvent : callbackOrOptions;
removeCallback(topic, callback);
}
},
};
}