UNPKG

nest-nsq-transport

Version:
138 lines 6.09 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NSQStrategy = void 0; const common_1 = require("@nestjs/common"); const microservices_1 = require("@nestjs/microservices"); const nsqjs_1 = require("nsqjs"); const context_1 = require("./context"); const deferred_1 = require("./deferred"); const errors_1 = require("./errors"); const invariant_1 = require("./invariant"); const pattern_1 = require("./pattern"); const serialization_1 = require("./serialization"); const wait_group_1 = require("./wait-group"); class NSQStrategy extends microservices_1.Server { opts; logger = new common_1.Logger(NSQStrategy.name); readers = new Map(); handlingMessagesWG = new wait_group_1.WaitGroup(); readersSetDeferred = new deferred_1.Deferred(); constructor(opts) { super(); this.opts = opts; this.deserializer = opts.deserializer ?? new serialization_1.StringDeserializer(); } async listen(callback) { this.readersSetDeferred.resolve(); await Promise.all([...this.readers.values()].map((reader) => new Promise((res, rej) => { reader.on('ready', res); reader.on('error', rej); reader.connect(); }))); this.logger.log('start listening to messages'); if (callback) callback(); } addHandler(pattern, callback, isEventHandler, extras) { const parsed = pattern_1.NSQPattern.parse(pattern); if (!parsed) return this.logger.debug(`skipping handler with pattern: ${JSON.stringify(pattern)}`); if (!isEventHandler) throw new errors_1.RPCNotSupported(); const reader = this.createOrGetReaderFor(parsed); reader.on(parsed.discard ? 'discard' : 'message', this.handleMessage(parsed)); super.addHandler(pattern, callback, isEventHandler, extras); } async close() { for (const reader of this.readers.values()) { reader.pause(); } await this.handlingMessagesWG.wait(); for (const reader of this.readers.values()) { reader.close(); } } on(event, callback) { void this.readersSetDeferred.promise.then(() => { this.readers.forEach((reader) => { // @ts-expect-error FIXME later reader.on(event, callback); }); }); } // we have multiple underlying readers, so we return all of them unwrap() { return this.readers; } createOrGetReaderFor(pattern) { const existing = this.readers.get(pattern.toString(true)); if (existing) return existing; const reader = this.createReaderFor(pattern); this.readers.set(pattern.toString(true), reader); return reader; } createReaderFor(pattern) { const { topic, channel } = pattern; const { requeueParams: _, ...readerOpts } = this.getOptionsByPattern(pattern); const reader = new nsqjs_1.Reader(topic, channel, readerOpts); const logPrefix = `reader for topic ${topic} and channel ${channel} status:`; reader.on('not_ready', () => this.logger.log(`${logPrefix} not ready`)); reader.on('nsqd_connected', (host, port) => this.logger.log(`${logPrefix} not connected to nsqd ${host}:${port}`)); reader.on('nsqd_closed', (host, port) => this.logger.log(`${logPrefix} nsqd closed ${host}:${port}`)); reader.on('error', (error) => this.logger.error(`${logPrefix} ${error}`)); return reader; } getOptionsByPattern(pattern) { return Object.assign({}, this.opts.defaultChannelOptions, this.opts.channels?.[pattern.topic]?.[pattern.channel]); } handleMessage(pattern) { return async (message) => { this.handlingMessagesWG.add(1); const handler = this.getHandlerByPattern(pattern.toString()); (0, invariant_1.invariant)(handler, `no handler for pattern ${pattern}`); const logAttributes = `message id=${message.id} attempt=${message.attempts} timestamp=${message.timestamp} topic=${pattern.topic} channel=${pattern.channel}${pattern.discard ? ' discarded' : ''}`; this.logger.verbose(`${logAttributes} to be processed`); let success = false; try { const packet = await this.deserializer.deserialize(message, { pattern, }); const ctx = new context_1.NSQContext([message, pattern]); const result = await handler(packet.data, ctx); if (result) await result.toPromise(); this.logger.debug(`${logAttributes} handled successfully`); message.finish(); success = true; } catch (e) { let serializedError = String(e); if (serializedError === objectObject) { try { serializedError = JSON.stringify(e); } catch { } } this.logger.debug(`error thrown while processing ${logAttributes}: ${serializedError}`); const { requeueParams } = this.getOptionsByPattern(pattern); // skipping coverage as it will make test too long with default values /* istanbul ignore next */ if (!requeueParams) message.requeue(); else if (Array.isArray(requeueParams)) message.requeue(...requeueParams); else message.requeue(...requeueParams(message, pattern)); this.logger.debug(`${logAttributes} requeued`); } finally { this.logger.verbose(`${logAttributes} processed ${success ? 'successfully' : 'with error'}`); this.handlingMessagesWG.done(); } }; } } exports.NSQStrategy = NSQStrategy; const objectObject = {}.toString(); //# sourceMappingURL=server.js.map