UNPKG

@eventstore.net/event.store

Version:

A simple and fast EventStore that support multiple persistence and notification providers

57 lines (48 loc) 1.96 kB
import * as amqp from 'amqplib'; import { Message } from '../model/message'; import { HasSubscribers, Publisher, Subscriber, Subscription } from './publisher'; /** * A Publisher that use RabbitMQ to message communications. */ export class RabbitMQPublisher implements Publisher, HasSubscribers { private channel: amqp.Channel; private url: string; private exchanges: Set<string> = new Set(); constructor(url: string) { this.url = url; } public async publish(message: Message) { const channel = await this.getChannel(); await this.ensureExchange(message.stream.aggregation, channel); return await channel.publish(message.stream.aggregation, '', Buffer.from(JSON.stringify(message))); } public async subscribe(aggregation: string, subscriber: Subscriber): Promise<Subscription> { const channel = await this.getChannel(); await this.ensureExchange(aggregation, channel); const q = await channel.assertQueue('', { exclusive: true }); channel.bindQueue(q.queue, aggregation, ''); const response = await channel.consume(q.queue, (msg) => { subscriber(JSON.parse(msg.content.toString())); }, { noAck: true }); const consumerTag = response.consumerTag; return { remove: async () => { await channel.cancel(consumerTag); await channel.deleteQueue(q.queue); } }; } private async ensureExchange(aggregation: string, channel: amqp.Channel) { if (!this.exchanges.has(aggregation)) { await channel.assertExchange(aggregation, 'fanout', { durable: false }); this.exchanges.add(aggregation); } } private async getChannel() { if (!this.channel) { const conn = await amqp.connect(this.url); this.channel = await conn.createChannel(); } return this.channel; } }