UNPKG

nestjs-google-pubsub-microservice

Version:
213 lines 8.32 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.GCPubSubClient = void 0; const pubsub_1 = require("@google-cloud/pubsub"); const common_1 = require("@nestjs/common"); const microservices_1 = require("@nestjs/microservices"); const gc_pubsub_constants_1 = require("./gc-pubsub.constants"); const gc_pubsub_utils_1 = require("./gc-pubsub.utils"); class GCPubSubClient extends microservices_1.ClientProxy { constructor(options) { super(); this.options = options; this.logger = new common_1.Logger(GCPubSubClient.name); this.client = null; this.replySubscription = null; this.topic = null; this.clientConfig = this.options.client || gc_pubsub_constants_1.GC_PUBSUB_DEFAULT_CLIENT_CONFIG; this.scopedEnvKey = this.options.scopedEnvKey ?? ''; this.topicName = this.options.topic || gc_pubsub_constants_1.GC_PUBSUB_DEFAULT_TOPIC; this.topicName = `${this.scopedEnvKey}${this.topicName}`; this.subscriberConfig = this.options.subscriber || gc_pubsub_constants_1.GC_PUBSUB_DEFAULT_SUBSCRIBER_CONFIG; this.publisherConfig = this.options.publisher || gc_pubsub_constants_1.GC_PUBSUB_DEFAULT_PUBLISHER_CONFIG; this.replyTopicName = this.options.replyTopic ? `${this.scopedEnvKey}${this.options.replyTopic}` : undefined; this.replySubscriptionName = this.options.replySubscription ? `${this.scopedEnvKey}${this.options.replySubscription}` : undefined; this.noAck = this.options.noAck ?? gc_pubsub_constants_1.GC_PUBSUB_DEFAULT_NO_ACK; this.init = this.options.init ?? gc_pubsub_constants_1.GC_PUBSUB_DEFAULT_INIT; this.useAttributes = this.options.useAttributes ?? gc_pubsub_constants_1.GC_PUBSUB_DEFAULT_USE_ATTRIBUTES; this.checkExistence = this.options.checkExistence ?? gc_pubsub_constants_1.GC_PUBSUB_DEFAULT_CHECK_EXISTENCE; this.initializeSerializer(options); this.initializeDeserializer(options); } async close() { await (0, gc_pubsub_utils_1.flushTopic)(this.topic); await (0, gc_pubsub_utils_1.closeSubscription)(this.replySubscription); await (0, gc_pubsub_utils_1.closePubSub)(this.client); this.client = null; this.topic = null; this.replySubscription = null; } async connect() { if (this.client) { return this.client; } this.client = this.createClient(); this.topic = this.client.topic(this.topicName, this.publisherConfig); if (this.init) { await this.createIfNotExists(this.topic.create.bind(this.topic)); } else if (this.checkExistence) { const [topicExists] = await this.topic.exists(); if (!topicExists) { const message = `PubSub client is not connected: topic ${this.topicName} does not exist`; this.logger.error(message); throw new Error(message); } } if (this.replyTopicName && this.replySubscriptionName) { const replyTopic = this.client.topic(this.replyTopicName); if (this.init) { await this.createIfNotExists(replyTopic.create.bind(replyTopic)); } else if (this.checkExistence) { const [exists] = await replyTopic.exists(); if (!exists) { const message = `PubSub client is not connected: topic ${this.replyTopicName} does not exist`; this.logger.error(message); throw new Error(message); } } this.replySubscription = replyTopic.subscription(this.replySubscriptionName, this.subscriberConfig); if (this.init) { await this.createIfNotExists(this.replySubscription.create.bind(this.replySubscription)); } else if (this.checkExistence) { const [exists] = await this.replySubscription.exists(); if (!exists) { const message = `PubSub client is not connected: subscription ${this.replySubscription} does not exist`; this.logger.error(message); throw new Error(message); } } this.replySubscription .on('message', async (message) => { try { const isHandled = await this.handleResponse(message); if (!isHandled) { message.nack(); } else if (this.noAck) { message.ack(); } } catch (error) { this.logger.error(error); if (this.noAck) { message.nack(); } } }) .on('error', (err) => this.logger.error(err)); } return this.client; } createClient() { return new pubsub_1.PubSub(this.clientConfig); } async dispatchEvent(packet) { const pattern = this.normalizePattern(packet.pattern); if (!this.topic) { return; } const serializedPacket = this.serializer.serialize({ ...packet, pattern, }); if (this.useAttributes) { await this.topic.publishMessage({ json: serializedPacket.data, attributes: { pattern: serializedPacket.pattern, }, }); } else { await this.topic.publishMessage({ json: serializedPacket }); } } publish(partialPacket, callback) { try { const packet = this.assignPacketId(partialPacket); const serializedPacket = this.serializer.serialize(packet); this.routingMap.set(packet.id, callback); if (this.topic) { if (this.useAttributes) { this.topic .publishMessage({ json: serializedPacket.data, attributes: { replyTo: this.replyTopicName, pattern: serializedPacket.pattern, id: serializedPacket.id, }, }) .catch((err) => callback({ err })); } else { this.topic .publishMessage({ json: serializedPacket, attributes: { replyTo: this.replyTopicName }, }) .catch((err) => callback({ err })); } } else { callback({ err: new Error('Topic is not created') }); } return () => this.routingMap.delete(packet.id); } catch (err) { callback({ err }); } } async handleResponse(message) { const rawMessage = JSON.parse(message.data.toString()); const { err, response, isDisposed, id } = this.deserializer.deserialize(rawMessage); const correlationId = message.attributes.id || id; const callback = this.routingMap.get(correlationId); if (!callback) { return false; } if (err || isDisposed) { callback({ err, response, isDisposed, }); } else { callback({ err, response, }); } return true; } async createIfNotExists(create) { try { await create(); } catch (error) { if (error.code !== gc_pubsub_constants_1.ALREADY_EXISTS) { throw error; } } } unwrap() { if (!this.client) { throw new Error('Client is not initialized.'); } return this.client; } } exports.GCPubSubClient = GCPubSubClient; //# sourceMappingURL=gc-pubsub.client.js.map