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();
}
}