Fix Backend service crash when RabbitMQ queues are predeclared

Signed-off-by: Fred Heinecke <fred.heinecke@yahoo.com>
This commit is contained in:
Fred Heinecke 2025-04-27 09:52:43 +00:00 committed by Zoe Roux
parent 0fe423869a
commit 1a61b18b2d
2 changed files with 56 additions and 4 deletions

View File

@ -30,7 +30,8 @@ public class RabbitProducer
{ {
_channel = rabbitConnection.CreateModel(); _channel = rabbitConnection.CreateModel();
_channel.ExchangeDeclare("events.resource", ExchangeType.Topic); if (!doesExchangeExist(rabbitConnection, "events.resource"))
_channel.ExchangeDeclare("events.resource", ExchangeType.Topic);
_ListenResourceEvents<Collection>("events.resource"); _ListenResourceEvents<Collection>("events.resource");
_ListenResourceEvents<Movie>("events.resource"); _ListenResourceEvents<Movie>("events.resource");
_ListenResourceEvents<Show>("events.resource"); _ListenResourceEvents<Show>("events.resource");
@ -39,7 +40,8 @@ public class RabbitProducer
_ListenResourceEvents<Studio>("events.resource"); _ListenResourceEvents<Studio>("events.resource");
_ListenResourceEvents<User>("events.resource"); _ListenResourceEvents<User>("events.resource");
_channel.ExchangeDeclare("events.watched", ExchangeType.Topic); if (!doesExchangeExist(rabbitConnection, "events.watched"))
_channel.ExchangeDeclare("events.watched", ExchangeType.Topic);
IWatchStatusRepository.OnMovieStatusChangedHandler += _PublishWatchStatus<Movie>("movie"); IWatchStatusRepository.OnMovieStatusChangedHandler += _PublishWatchStatus<Movie>("movie");
IWatchStatusRepository.OnShowStatusChangedHandler += _PublishWatchStatus<Show>("show"); IWatchStatusRepository.OnShowStatusChangedHandler += _PublishWatchStatus<Show>("show");
IWatchStatusRepository.OnEpisodeStatusChangedHandler += _PublishWatchStatus<Episode>( IWatchStatusRepository.OnEpisodeStatusChangedHandler += _PublishWatchStatus<Episode>(
@ -47,6 +49,30 @@ public class RabbitProducer
); );
} }
/// <summary>
/// Checks if the exchange exists. Needed to avoid crashing when re-declaring an existing
/// queue with different parameters.
/// </summary>
/// <param name="rabbitConnection">The RabbitMQ connection.</param>
/// <param name="exchangeName">The name of the channel.</param>
/// <returns>True if the queue exists, false otherwise.</returns>
private bool doesExchangeExist(IConnection rabbitConnection, string exchangeName)
{
// If the queue does not exist when QueueDeclarePassive is called,
// an exception will be thrown. According to the docs, when this
// happens, the entire channel should be thrown away.
using var channel = rabbitConnection.CreateModel();
try
{
channel.ExchangeDeclarePassive(exchangeName);
return true;
}
catch (Exception)
{
return false;
}
}
private void _ListenResourceEvents<T>(string exchange) private void _ListenResourceEvents<T>(string exchange)
where T : IResource, IQuery where T : IResource, IQuery
{ {

View File

@ -31,8 +31,34 @@ public class ScannerProducer : IScanner
public ScannerProducer(IConnection rabbitConnection) public ScannerProducer(IConnection rabbitConnection)
{ {
_channel = rabbitConnection.CreateModel(); _channel = rabbitConnection.CreateModel();
_channel.QueueDeclare("scanner", exclusive: false, autoDelete: false); if (!doesQueueExist(rabbitConnection, "scanner"))
_channel.QueueDeclare("scanner.rescan", exclusive: false, autoDelete: false); _channel.QueueDeclare("scanner", exclusive: false, autoDelete: false);
if (!doesQueueExist(rabbitConnection, "scanner.rescan"))
_channel.QueueDeclare("scanner.rescan", exclusive: false, autoDelete: false);
}
/// <summary>
/// Checks if the queue exists. Needed to avoid crashing when re-declaring an existing
/// queue with different parameters.
/// </summary>
/// <param name="rabbitConnection">The RabbitMQ connection.</param>
/// <param name="queueName">The name of the channel.</param>
/// <returns>True if the queue exists, false otherwise.</returns>
private bool doesQueueExist(IConnection rabbitConnection, string queueName)
{
// If the queue does not exist when QueueDeclarePassive is called,
// an exception will be thrown. According to the docs, when this
// happens, the entire channel should be thrown away.
using var channel = rabbitConnection.CreateModel();
try
{
channel.QueueDeclarePassive(queueName);
return true;
}
catch (Exception)
{
return false;
}
} }
private Task _Publish<T>(T message, string queue = "scanner") private Task _Publish<T>(T message, string queue = "scanner")