UNPKG

@shirayukikitsune/graphql-kafkajs-subscriptions

Version:

An implementation for the Apollo PubSubEngine using the KafkaJS as backend.

102 lines 3.85 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PubSubAsyncIterator = void 0; const iterall_1 = require("iterall"); /** * A class for digesting PubSubEngine events via the new AsyncIterator interface. * This implementation is a generic version of the one located at * https://github.com/apollographql/graphql-subscriptions/blob/master/src/event-emitter-to-async-iterator.ts * @class * * @constructor * * @property pullQueue @type {Function[]} * A queue of resolve functions waiting for an incoming event which has not yet arrived. * This queue expands as next() calls are made without PubSubEngine events occurring in between. * * @property pushQueue @type {any[]} * A queue of PubSubEngine events waiting for next() calls to be made. * This queue expands as PubSubEngine events arrice without next() calls occurring in between. * * @property eventsArray @type {string[]} * An array of PubSubEngine event names which this PubSubAsyncIterator should watch. * * @property allSubscribed @type {Promise<number[]>} * A promise of a list of all subscription ids to the passed PubSubEngine. * * @property listening @type {boolean} * Whether or not the PubSubAsynIterator is in listening mode (responding to incoming PubSubEngine events and next() calls). * Listening begins as true and turns to false once the return method is called. * * @property pubsub @type {PubSubEngine} * The PubSubEngine whose events will be observed. */ class PubSubAsyncIterator { constructor(pubsub, eventNames, options) { this.pubsub = pubsub; this.options = options; this.pullQueue = []; this.pushQueue = []; this.listening = true; this.eventsArray = typeof eventNames === 'string' ? [eventNames] : eventNames; } async next() { await this.subscribeAll(); return this.listening ? this.pullValue() : this.return(); } async return() { await this.emptyQueue(); return { value: undefined, done: true }; } async throw(error) { await this.emptyQueue(); return Promise.reject(error); } [iterall_1.$$asyncIterator]() { return this; } async pushValue(event) { await this.subscribeAll(); const fn = this.pullQueue.shift(); if (fn) { fn({ value: event, done: false }); } else { this.pushQueue.push(event); } } pullValue() { return new Promise(resolve => { if (this.pushQueue.length !== 0) { // @ts-ignore: TS fails to identify the right choice for this union type resolve({ done: false, value: this.pushQueue.shift() }); } else { this.pullQueue.push(resolve); } }); } async emptyQueue() { if (this.listening) { this.listening = false; if (this.subscriptionIds) this.unsubscribeAll(await this.subscriptionIds); this.pullQueue.forEach(resolve => resolve({ value: undefined, done: true })); this.pullQueue.length = 0; this.pushQueue.length = 0; } } subscribeAll() { if (!this.subscriptionIds) { this.subscriptionIds = Promise.all(this.eventsArray.map(eventName => this.pubsub.subscribe(eventName, this.pushValue.bind(this), this.options))); } return this.subscriptionIds; } unsubscribeAll(subscriptionIds) { for (const subscriptionId of subscriptionIds) { this.pubsub.unsubscribe(subscriptionId); } } } exports.PubSubAsyncIterator = PubSubAsyncIterator; //# sourceMappingURL=pubsub-async-iterator.js.map