1
0
tinklu-paslaugos/Lab4/ChatRoom/ChatRoomRabbitMQService.cs
2024-12-07 17:21:09 +02:00

160 lines
5.8 KiB
C#

using RabbitMQ.Client;
using Newtonsoft.Json;
using RabbitMQ.Client.Events;
using ChatRoomContract;
using System.Text;
using MessagePack;
using System.Diagnostics;
using NLog.LayoutRenderers.Wrappers;
using NLog;
namespace ChatRoom;
internal class ChatRoomRabbitMQService
{
/// <summary>
/// Logger for this class.
/// </summary>
private Logger log = LogManager.GetCurrentClassLogger();
/// <summary>
/// Communications channel to RabbitMQ message broker.
/// </summary>
private IModel rmqChannel;
/// <summary>
/// Service logic.
/// </summary>
private ChatRoomLogic logic;
public ChatRoomRabbitMQService(ChatRoomLogic logic, IConnection connection, string exchangeName, string serverQueueName)
{
this.logic = logic;
//get channel, configure exchanges and request queue
rmqChannel = connection.CreateModel();
rmqChannel.ExchangeDeclare(exchange: exchangeName, type: ExchangeType.Direct);
rmqChannel.QueueDeclare(queue: serverQueueName, durable: true, exclusive: false, autoDelete: false, arguments: null);
rmqChannel.QueueBind(queue: serverQueueName, exchange: exchangeName, routingKey: serverQueueName, arguments: null);
//connect to the queue as consumer
//XXX: see https://www.rabbitmq.com/dotnet-api-guide.html#concurrency for threading issues
var rmqConsumer = new EventingBasicConsumer(rmqChannel);
rmqConsumer.Received += (consumer, delivery) => OnMessageReceived(((EventingBasicConsumer)consumer).Model, delivery);
rmqChannel.BasicConsume(queue: serverQueueName, autoAck: true, consumer: rmqConsumer);
}
/// <summary>
/// Is invoked to process messages received.
/// </summary>
/// <param name="channel">Related communications channel.</param>
/// <param name="msgIn">Message deliver data.</param>
private void OnMessageReceived(IModel channel, BasicDeliverEventArgs msgIn)
{
try
{
var msg = MessagePackSerializer.Deserialize<RPCMessage>(msgIn.Body);
Debug.Assert(msg != null);
if (msg.isResponse == true)
{
return;
}
bool hasResponse = false;
byte[]? response = null;
switch (msg.method)
{
case nameof(IChatRoomService.RegisterClient):
{
var name = MessagePackSerializer.Deserialize<string>(msg.args);
var clientId = logic.RegisterClient(name);
response = MessagePackSerializer.Serialize(clientId);
hasResponse = true;
break;
}
case nameof(IChatRoomService.GetStrikes):
{
var clientId = MessagePackSerializer.Deserialize<int>(msg.args);
var strikes = logic.GetStrikes(clientId);
response = MessagePackSerializer.Serialize(strikes);
hasResponse = true;
break;
}
case nameof(IChatRoomService.GetBlockedUntil):
{
var clientId = MessagePackSerializer.Deserialize<int>(msg.args);
var blockedUntil = logic.GetBlockedUntil(clientId);
response = MessagePackSerializer.Serialize(blockedUntil);
hasResponse = true;
break;
}
case nameof(IChatRoomService.SendMessage):
{
var args = MessagePackSerializer.Deserialize<SendMessageArgs>(msg.args);
var success = logic.SendMessage(args.clientId, args.contents, args.needsToBeCensored);
response = MessagePackSerializer.Serialize(success);
hasResponse = true;
break;
}
case nameof(IChatRoomService.GetNewMessage):
{
var newMessage = logic.GetNewMessage();
response = MessagePackSerializer.Serialize(newMessage);
hasResponse = true;
break;
}
case nameof(IChatRoomService.RejectMessage):
{
var messageId = MessagePackSerializer.Deserialize<int>(msg.args);
logic.ApproveMessage(messageId);
break;
}
case nameof(IChatRoomService.ApproveMessage):
{
var messageId = MessagePackSerializer.Deserialize<int>(msg.args);
logic.ApproveMessage(messageId);
break;
}
default:
{
throw new Exception("Unknown RPC method");
}
}
if (hasResponse)
{
var responseMsg = new RPCMessage
{
isResponse = true,
method = msg.method,
args = response
};
var properties = channel.CreateBasicProperties();
properties.CorrelationId = msgIn.BasicProperties.CorrelationId;
channel.BasicPublish(
exchange: msgIn.Exchange,
routingKey: msgIn.BasicProperties.ReplyTo,
basicProperties: properties,
body: MessagePackSerializer.Serialize(responseMsg)
);
}
}
catch (Exception e)
{
log.Error(e, "Unhandled exception caught when processing a message. The message is now lost.");
}
}
}