Typescript 中使用(mq连接管理) amqp-connection-manager


import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import amqp from 'amqplib';
import * as acm from 'amqp-connection-manager';

const logger = new Logger('RabbitMQ');

/**MQ交换器-事件 */
export const MQ_EVENT_EXCHANGE_EVENT_CONSUME: string = "exchange_event_consume";

type OnEventHandler = (data: any) => Promise<boolean>;
/**备注:这里是Nestjs框架*/
@Injectable()
export class RabbitMQUtils implements OnModuleInit {
  private connection: acm.AmqpConnectionManager | undefined;
  private channelWrapper: acm.ChannelWrapper | undefined;
  constructor(
  ) { }
  private async connectMq() {
    return new Promise<void>((resolve, reject) => {
      this.connection = acm.connect(['host' as string], {
        heartbeatIntervalInSeconds: 3,
        reconnectTimeInSeconds: 3,
        connectionOptions: {
          rejectUnauthorized: false
        }
      });

      this.connection.on('connect', function () {
        console.log("[AmqpConnectionManager]连接成功");
        return resolve();
      });
      this.connection.on('disconnect', function (err) {
        console.log("[AmqpConnectionManager]断开连接%O");
        return reject();
      });
    });
  }


  /**mq事件消费 */
  async consume(queueName: string, onEventHandler: OnEventHandler): Promise<void> {
    if (this.connection === undefined || this.connection === null) {
      return Promise.reject("请初始化客户端");
    }

    this.channelWrapper = this.connection.createChannel({
      json: false,
      setup: async function (channel: amqp.Channel): Promise<any> {
        // 初始化事件Exchange
        await channel.assertExchange(MQ_EVENT_EXCHANGE_EVENT_CONSUME, "direct", { durable: true });
        // 初始化事件队列
        channel.assertQueue(queueName, {
          durable: false,
          autoDelete: true
        });
        // 绑定事件队列
        channel.bindQueue(queueName, MQ_EVENT_EXCHANGE_EVENT_CONSUME, '');
        // 设置预消费
        channel.prefetch(1);
        // 消费事件
        channel.consume(queueName, async function (msg: amqp.ConsumeMessage | null): Promise<void> {
          let data: any;
          try {
            if (msg !== undefined && msg !== null && msg.content !== undefined && msg.content !== null) {
              data = msg.content.toString("utf8") as any;
              data = JSON.parse(data);
              await onEventHandler(data);
              channel.ack(msg);//应答
            }
            else {
              console.log("事件数据异常 %O", data);
              return Promise.reject(`事件数据异常`);
            }
          }
          catch (error) {
            console.log("[consume]%O", error);
            channel.ack(msg);
          }


        }, { noAck: false });//需要应答
      }
    });

    this.channelWrapper.on('connect', function () {
      console.log("[ChannelWrapper]连接成功");
    });
    this.channelWrapper.on('close', function () {
      console.log("[ChannelWrapper]连接关闭");
    });
    this.channelWrapper.on('error', function (err) {
      console.log("[ChannelWrapper]%O", err);
    });
  }

  /**mq事件推送 */
  async publish(queue: string, data: any): Promise<boolean> {
    return this.channelWrapper
      .sendToQueue(queue, Buffer.from(JSON.stringify(data)))
      .then(function () {
        logger.debug('publish Message was sent!')
        return true;
      })
      .catch(function (err) {
        logger.log('publish Message was rejected...  Boo!')
        return false;
      });
  }




  async onModuleInit() {
    await this.connectMq();
  }
}


posted @ 2022-03-30 14:24  吃西瓜不吐西瓜籽  阅读(492)  评论(0)    收藏  举报
Live2D