UNPKG

graphql-amqp-subscriptions

Version:
119 lines 4.73 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AMQPPubSub = void 0; const debug_1 = __importDefault(require("debug")); const pubsub_async_iterable_iterator_1 = require("graphql-subscriptions/dist/pubsub-async-iterable-iterator"); const uuid_1 = require("uuid"); const publisher_1 = require("./amqp/publisher"); const subscriber_1 = require("./amqp/subscriber"); const logger = (0, debug_1.default)('AMQPPubSub'); class AMQPPubSub { publisher; subscriber; exchange; subscriptionMap; subsRefsMap; unsubscribeMap; currentSubscriptionId; constructor(config) { this.subscriptionMap = {}; this.subsRefsMap = {}; this.unsubscribeMap = {}; this.currentSubscriptionId = 0; // Initialize AMQP Helper this.publisher = new publisher_1.AMQPPublisher(config, logger); this.subscriber = new subscriber_1.AMQPSubscriber(config, logger); this.exchange = { name: 'graphql_subscriptions', type: 'topic', options: { durable: false, autoDelete: false }, ...config.exchange }; logger('Finished initializing'); } async publish(routingKey, payload, options) { logger('Publishing message to exchange "%s" for key "%s" (%j)', this.exchange.name, routingKey, payload); return this.publisher.publish(routingKey, payload, options); } async subscribe(routingKey, onMessage, arguments_, options) { const id = this.currentSubscriptionId++; if (routingKey === 'fanout') { routingKey = (0, uuid_1.v4)(); } logger('Subscribing to "%s" with id: "%s"', routingKey, id); this.subscriptionMap[id] = { routingKey, listener: onMessage }; const references = this.subsRefsMap[routingKey]; if (references && references.length > 0) { const newReferences = [...references, id]; this.subsRefsMap[routingKey] = newReferences; return id; } this.subsRefsMap[routingKey] = [ ...(this.subsRefsMap[routingKey] || []), id ]; const existingDispose = this.unsubscribeMap[routingKey]; // Get rid of exisiting subscription while we get a new one. const [newDispose] = await Promise.all([ this.subscriber.subscribe(routingKey, this.onMessage, arguments_, options), existingDispose ? existingDispose() : Promise.resolve() ]); this.unsubscribeMap[routingKey] = newDispose; return id; } async unsubscribe(subId) { const sub = this.subscriptionMap[subId]; if (!sub) { throw new Error(`There is no subscription for id "${subId}"`); } const { routingKey } = sub; const references = this.subsRefsMap[routingKey]; if (!references) { throw new Error(`There is no subscription ref for routing key "${routingKey}", id "${subId}"`); } logger('Unsubscribing from "%s" with id: "%s"', routingKey, subId); if (references.length === 1) { delete this.subscriptionMap[subId]; return this.unsubscribeForKey(routingKey); } const index = references.indexOf(subId); const newReferences = index === -1 ? references : [...references.slice(0, index), ...references.slice(index + 1)]; this.subsRefsMap[routingKey] = newReferences; delete this.subscriptionMap[subId]; } asyncIterableIterator(triggers) { return new pubsub_async_iterable_iterator_1.PubSubAsyncIterableIterator(this, triggers); } onMessage = (routingKey, content, message) => { const subscribers = this.subsRefsMap[routingKey]; // Don't work for nothing... if (!subscribers || subscribers.length === 0) { this.unsubscribeForKey(routingKey).catch((error) => { logger('onMessage unsubscribeForKey error "%j", Routing Key "%s"', error, routingKey); }); return; } for (const subId of subscribers) { this.subscriptionMap[subId].listener(content, message); } }; async unsubscribeForKey(routingKey) { const dispose = this.unsubscribeMap[routingKey]; delete this.unsubscribeMap[routingKey]; delete this.subsRefsMap[routingKey]; await dispose(); } } exports.AMQPPubSub = AMQPPubSub; //# sourceMappingURL=pubsub.js.map