UNPKG

@tawk.to/nestjs-google-pubsub-microservice

Version:
250 lines 11.4 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"); const gc_message_serializer_1 = require("./gc-message.serializer"); const gc_pubsub_parser_1 = require("./gc-pubsub.parser"); const uuid_1 = require("uuid"); class GCPubSubClient extends microservices_1.ClientProxy { constructor(options) { var _a, _b, _c, _d, _e, _f, _g, _h, _j; super(); this.options = options; this.logger = new common_1.Logger(GCPubSubClient.name); this.client = null; this.replySubscription = null; this.topic = null; this.clientId = (0, uuid_1.v4)(); this.clientConfig = this.options.client || gc_pubsub_constants_1.GC_PUBSUB_DEFAULT_CLIENT_CONFIG; this.topicName = this.options.topic || gc_pubsub_constants_1.GC_PUBSUB_DEFAULT_TOPIC; 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.replySubscriptionName = this.options.replySubscription; if (this.options.appendClientIdToSubscription) this.replySubscriptionName += '-' + this.clientId; if (this.options.appendClientIdToReplyTopic) this.replyTopicName += '-' + this.clientId; this.noAck = (_a = this.options.noAck) !== null && _a !== void 0 ? _a : gc_pubsub_constants_1.GC_PUBSUB_DEFAULT_NO_ACK; this.init = (_b = this.options.init) !== null && _b !== void 0 ? _b : gc_pubsub_constants_1.GC_PUBSUB_DEFAULT_INIT; this.checkExistence = (_c = this.options.checkExistence) !== null && _c !== void 0 ? _c : gc_pubsub_constants_1.GC_PUBSUB_DEFAULT_CHECK_EXISTENCE; this.autoResume = (_d = this.options.autoResume) !== null && _d !== void 0 ? _d : gc_pubsub_constants_1.GC_PUBSUB_DEFAULT_AUTO_RESUME; this.createSubscriptionOptions = (_e = this.options.createSubscriptionOptions) !== null && _e !== void 0 ? _e : gc_pubsub_constants_1.GC_PUBSUB_DEFAULT_CREATE_SUBSCRIPTION_OPTIONS; this.autoDeleteSubscriptionOnShutdown = (_f = this.options.autoDeleteSubscriptionOnShutdown) !== null && _f !== void 0 ? _f : gc_pubsub_constants_1.GC_AUTO_DELETE_SUBSCRIPTION_ON_SHUTDOWN; this.autoDeleteReplyTopicOnShutdown = (_g = this.options.autoDeleteReplyTopicOnShutdown) !== null && _g !== void 0 ? _g : gc_pubsub_constants_1.GC_AUTO_DELETE_REPLY_TOPIC_ON_SHUTDOWN; this.clientIdFilter = (_h = this.options.clientIdFilter) !== null && _h !== void 0 ? _h : gc_pubsub_constants_1.GC_PUBSUB_DEFAULT_CLIENT_ID_FILTER; this.initializeSerializer(options); this.initializeDeserializer(options); this.parser = (_j = options.parser) !== null && _j !== void 0 ? _j : new gc_pubsub_parser_1.GCPubSubParser(); } getRequestPattern(pattern) { return pattern; } async close() { await (0, gc_pubsub_utils_1.flushTopic)(this.topic); if (this.autoDeleteSubscriptionOnShutdown) { try { await this.replySubscription.delete(); } catch (_a) { await (0, gc_pubsub_utils_1.closeSubscription)(this.replySubscription); } } else { await (0, gc_pubsub_utils_1.closeSubscription)(this.replySubscription); } if (this.autoDeleteReplyTopicOnShutdown && this.client) { const replyTopic = this.client.topic(this.replyTopicName); if (replyTopic) { await replyTopic.delete(); } } await (0, gc_pubsub_utils_1.closePubSub)(this.client); this.client = null; this.topic = null; this.replySubscription = null; } async connect() { var _a, _b; if (this.client) { return this.client; } this.client = this.createClient(); this.topic = this.client.topic(this.topicName, this.publisherConfig); 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) { let filterString = (_b = (_a = this.createSubscriptionOptions) === null || _a === void 0 ? void 0 : _a.filter) !== null && _b !== void 0 ? _b : ''; if (this.clientIdFilter) { const temp = filterString; filterString = `attributes._clientId = "${this.clientId}"`; if (temp !== '') filterString += ` AND (${temp})`; } await this.createIfNotExists(this.replySubscription.create.bind(this.replySubscription, Object.assign(Object.assign({}, this.createSubscriptionOptions), (this.clientIdFilter && { filter: filterString, })))); } 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 { await this.handleResponse(message); message.ack(); } catch (error) { this.logger.error(error); } }) .on('error', (err) => this.logger.error(err)); } return this.client; } createClient() { return new pubsub_1.PubSub(this.clientConfig); } async dispatchEvent(packet) { var _a, _b; const pattern = this.normalizePattern(packet.pattern); if (!this.topic) { return; } const serializedPacket = (await this.serializer.serialize(Object.assign(Object.assign({}, packet), { pattern }), { message: Object.assign({}, packet.data), })); const attributes = Object.assign({ _replyTo: this.replyTopicName, _pattern: this.getRequestPattern(packet.pattern) }, (((_a = serializedPacket.data) === null || _a === void 0 ? void 0 : _a.attributes) && ((_b = serializedPacket.data) === null || _b === void 0 ? void 0 : _b.attributes))); await this.topic.publishMessage({ data: serializedPacket.data, orderingKey: serializedPacket.orderingKey, attributes: attributes, }); } publish(partialPacket, callback) { try { const packet = this.assignPacketId(partialPacket); this.routingMap.set(packet.id, callback); const cleanup = () => this.routingMap.delete(packet.id); const errorCallback = (err) => { cleanup(); callback({ err }); }; Promise.resolve(this.serializer.serialize(packet, { message: Object.assign({}, packet.data), })).then((serializedPacket) => { const attributes = Object.assign({ _replyTo: this.replyTopicName, _pattern: JSON.stringify(this.getRequestPattern(packet.pattern)), _id: packet.id, _clientId: this.clientId }, (serializedPacket.attributes && serializedPacket.attributes)); if (this.topic) { this.topic .publishMessage({ data: serializedPacket.data, orderingKey: serializedPacket.orderingKey, attributes: attributes, }) .catch((err) => { if (this.autoResume && serializedPacket.orderingKey) { this.topic.resumePublishing(serializedPacket.orderingKey); } callback({ err }); }); } else { errorCallback(new Error('Topic is not created')); } if (serializedPacket.attributes._timeout) { setTimeout(() => { errorCallback(new common_1.RequestTimeoutException('Message Timeout')); }, Number(serializedPacket.attributes._timeout)); } }); return cleanup; } catch (err) { callback({ err }); } } initializeSerializer(options) { var _a; this.serializer = (_a = options === null || options === void 0 ? void 0 : options.serializer) !== null && _a !== void 0 ? _a : new gc_message_serializer_1.GCPubSubMessageSerializer(); } async handleResponse(message) { const rawMessage = await this.parser.parse(message); const { err, response, isDisposed, id } = (await this.deserializer.deserialize(rawMessage, { message, })); 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