UNPKG

@niur/nestjs-service-bus

Version:

NestJS Azure Service Bus Microservice Transport

130 lines (110 loc) 3.57 kB
import { Server, WritePacket, CustomTransportStrategy, } from "@nestjs/microservices"; import { MessageHandlers, ProcessErrorArgs, ServiceBusClient, ServiceBusMessage, ServiceBusReceivedMessage, } from "@azure/service-bus"; import { AzureServiceBusContext } from "../azure-service-bus.context"; import { AzureServiceBusOptions } from "../interfaces"; import { SbSubscriberMetadata } from "../metadata"; export class AzureServiceBusServer extends Server implements CustomTransportStrategy { private sbClient: ServiceBusClient; constructor(protected readonly options: AzureServiceBusOptions) { super(); this.initializeSerializer(options); this.initializeDeserializer(options); } async listen(callback: (...optionalParams: unknown[]) => any) { try { this.sbClient = this.createServiceBusClient(); await this.start(callback); } catch (err) { callback(err); } } async start( callback: (err?: unknown, ...optionalParams: unknown[]) => void ): Promise<void> { await this.bindEvents(); callback(); } async bindEvents(): Promise<void> { const subscribe = async (pattern: string) => { const { metaOptions: { topic, subscription: name, subQueueType, skipParsingBodyAsJson, receiveMode, options, }, }: SbSubscriberMetadata = JSON.parse(pattern); const receiver = this.sbClient.createReceiver(topic, name, { receiveMode, subQueueType, skipParsingBodyAsJson, }); receiver.subscribe(this.createMessageHandlers(pattern), options); await receiver.close(); }; const registeredPatterns = [...this.messageHandlers.keys()]; await Promise.all(registeredPatterns.map(subscribe)); } public createMessageHandlers = (pattern: string): MessageHandlers => ({ processMessage: async (receivedMessage: ServiceBusReceivedMessage) => await this.handleMessage(receivedMessage, pattern), processError: async (args: ProcessErrorArgs): Promise<void> => { return new Promise<void>(() => { console.error(`Error processing message: ${args.error}`); }); }, }); public async handleMessage( receivedMessage: ServiceBusReceivedMessage, pattern: string ): Promise<void> { const partialPacket = { data: receivedMessage, pattern }; const packet = await this.deserializer.deserialize(partialPacket); if (!receivedMessage.replyTo) { const sbContext = new AzureServiceBusContext([]); return this.handleEvent(packet.pattern, packet, sbContext); } const publish = this.getPublisher( receivedMessage.replyTo, receivedMessage.messageId as string ); const handler = this.getHandlerByPattern(pattern); const response$ = this.transformToObservable( await handler(receivedMessage) ); response$ && this.send(response$, publish); } public getPublisher(replyTo: string, correlationId: string) { return async (data: WritePacket) => { const sender = this.sbClient.createSender(replyTo); const responseMessage = { correlationId, body: data.response, } as ServiceBusMessage; await sender.sendMessages([responseMessage]); await sender.close(); }; } createServiceBusClient(): ServiceBusClient { const { connectionString, options } = this.options; return new ServiceBusClient(connectionString, options); } async close(): Promise<void> { await this.sbClient?.close(); } }