Creado apartir del commit b888de6c92056de294456f581a56e25e734d4ab7 de develop

This commit is contained in:
jrojas
2026-06-26 09:52:35 +02:00
commit 319fd3dfb0
746 changed files with 106610 additions and 0 deletions
@@ -0,0 +1,126 @@
using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Models.AppSettings;
using EasyNetQ;
using EasyNetQ.SystemMessages;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
namespace adas_core.Infrastructure.Services;
public class PublisherService : IPublisherService
{
private readonly ILogger<PublisherService> _logger;
private readonly HashSet<string> _queues = new();
private readonly IBus? _bus;
public PublisherService(
IOptions<RabbitMqSettings> rabbitMqSettings,
ILogger<PublisherService> logger)
{
_logger = logger;
try
{
var connection = rabbitMqSettings.Value.ConnectionString;
if (string.IsNullOrWhiteSpace(connection))
{
_logger.LogError("Missing RabbitMQ connection string");
return;
}
var services = new ServiceCollection();
services.AddEasyNetQ(connection);
var provider = services.BuildServiceProvider();
_bus = provider.GetRequiredService<IBus>();
_logger.LogInformation("PublisherService initialized");
}
catch (Exception ex)
{
_logger.LogError(ex, "Error initializing PublisherService");
}
}
public Task<bool> CreateQueue(string queueName)
{
if (string.IsNullOrWhiteSpace(queueName))
return Task.FromResult(false);
if (_queues.Contains(queueName))
{
_logger.LogDebug("Queue {queueName} already registered", queueName);
return Task.FromResult(true);
}
_queues.Add(queueName);
_logger.LogInformation("Queue registered: {queueName}", queueName);
// EasyNetQ crea colas automáticamente
return Task.FromResult(true);
}
public async Task<bool> SendMessage(string msg, string queueName)
{
try
{
if (_bus == null)
{
_logger.LogError("Bus is null");
return false;
}
await CreateQueue(queueName);
_logger.LogDebug("Sending message to {queueName}", queueName);
await _bus.SendReceive.SendAsync(queueName, msg);
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error sending message to {queueName}", queueName);
return false;
}
}
public async Task<bool> SendMessage(object obj, string queueName)
{
var json = JsonConvert.SerializeObject(obj);
return await SendMessage(json, queueName);
}
public async Task<bool> SendMessageError(object obj, string queueName)
{
try
{
if (_bus == null)
{
_logger.LogError("Bus is null - cannot send error message");
return false;
}
if (obj is not Message<Error> errorMessage)
return false;
await CreateQueue(queueName);
_logger.LogDebug("Sending error message to {queueName}", queueName);
// enviamos solo el Error (no Message<Error>)
await _bus.SendReceive.SendAsync(queueName, errorMessage.Body);
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error sending error message");
return false;
}
}
}
@@ -0,0 +1,239 @@
using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Models;
using adas_core.Domain.Models.AppSettings;
using EasyNetQ;
using EasyNetQ.SystemMessages;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
namespace adas_core.Infrastructure.Services;
public class ReceiverService
{
private readonly ILogger<ReceiverService> _logger;
private readonly RabbitMqSettings _settings;
private readonly IObservationService _observationService;
private readonly ITreatmentService _treatmentService;
private readonly IPatientService _patientsService;
private readonly IPumpService _pumpService;
private readonly IRecordingAlertService _recordingAlertService;
private readonly IRecordingService _recordingService;
private readonly IAppointmentService _appointmentService;
private readonly IAlarmService _alarmService;
private readonly List<string> _queues = [];
private IBus? _bus;
public ReceiverService(
IObservationService observationService,
ITreatmentService treatmentService,
IPatientService patientsService,
IPumpService pumpService,
IRecordingAlertService recordingAlertService,
IRecordingService recordingService,
IAppointmentService appointmentService,
IAlarmService alarmService,
IOptions<RabbitMqSettings> settings,
ILogger<ReceiverService> logger)
{
_logger = logger;
_settings = settings.Value;
_observationService = observationService;
_treatmentService = treatmentService;
_patientsService = patientsService;
_pumpService = pumpService;
_recordingAlertService = recordingAlertService;
_recordingService = recordingService;
_appointmentService = appointmentService;
_alarmService = alarmService;
if (!string.IsNullOrWhiteSpace(_settings.ConnectionString))
{
SetQueues();
TryToConnect();
}
else
{
_logger.LogError("RabbitMQ connection string NOT configured");
}
}
private void SetQueues()
{
AddQueue(_settings.ObservationsQueue);
AddQueue(_settings.TreatmentsQueue);
AddQueue(_settings.PatientsQueue);
AddQueue(_settings.PumpsQueue);
AddQueue(_settings.AppointmentsQueue);
AddQueue(_settings.RecordingQueue);
AddQueue(_settings.RecordingAlertQueue);
AddQueue(_settings.AlarmObservationQueue);
}
private void AddQueue(string? queue)
{
if (!string.IsNullOrWhiteSpace(queue))
_queues.Add(queue!);
}
private void TryToConnect()
{
try
{
DisposeBus();
var services = new ServiceCollection();
services.AddEasyNetQ(_settings.ConnectionString);
var provider = services.BuildServiceProvider();
_bus = provider.GetRequiredService<IBus>();
foreach (var queue in _queues)
{
RegisterConsumer(queue);
}
_logger.LogInformation("RabbitMQ connected. Registered {Count} queues", _queues.Count);
}
catch (Exception ex)
{
_logger.LogError(ex, "RabbitMQ connection failed. Retrying in 5 seconds...");
var timer = new System.Timers.Timer(5000);
timer.Elapsed += (_, _) =>
{
timer.Stop();
TryToConnect();
};
timer.Start();
}
}
private void DisposeBus()
{
if (_bus is IDisposable disposable)
{
disposable.Dispose();
}
}
private void RegisterConsumer(string queue)
{
_bus!.SendReceive.ReceiveAsync<string>(queue, async payload =>
{
try
{
_logger.LogDebug("Message received from {queue}", queue);
var service = ResolveService(queue);
if (service == null)
{
_logger.LogWarning("No service mapped for queue {queue}", queue);
return;
}
var message = new Message<string>(
payload,
new MessageProperties()
);
await Task.Run(() => TryToParseAndSend(message, service));
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing message from {queue}", queue);
throw; // 🔴 importante: activa retry
}
});
}
private IApiRequestService? ResolveService(string queue)
{
return queue switch
{
var q when q == _settings.ObservationsQueue => _observationService,
var q when q == _settings.TreatmentsQueue => _treatmentService,
var q when q == _settings.PatientsQueue => _patientsService,
var q when q == _settings.PumpsQueue => _pumpService,
var q when q == _settings.RecordingQueue => _recordingService,
var q when q == _settings.RecordingAlertQueue => _recordingAlertService,
var q when q == _settings.AlarmObservationQueue => _alarmService,
var q when q == _settings.AppointmentsQueue => _appointmentService,
_ => null
};
}
public async Task ProcessErrorQueue(string errorQueueName)
{
if (_bus == null)
{
_logger.LogError("Cannot process error queue - bus is null");
return;
}
await _bus.SendReceive.ReceiveAsync<Error>(errorQueueName, async err =>
{
try
{
var queue = err.RoutingKey?.Replace("Key", "");
if (string.IsNullOrEmpty(queue))
return;
var service = ResolveService(queue);
if (service == null)
return;
var message = new Message<string>(
err.Message,
new MessageProperties()
);
await Task.Run(() => TryToParseAndSend(message, service));
}
catch (Exception ex)
{
_logger.LogError(ex, "Error reprocessing message from {queue}", errorQueueName);
throw;
}
});
}
/// <summary>
/// Sends EasyNetQ messages to a service implementing IApiRequestService
/// Throws exception to trigger retry on failure
/// </summary>
private void TryToParseAndSend(IMessage<string> msg, IApiRequestService service)
{
try
{
_logger.LogDebug("Processing message: {msg}", msg.Body);
var apiRequest = JsonConvert.DeserializeObject<ApiRequest>(msg.Body);
if (apiRequest == null)
{
_logger.LogError("Invalid ApiRequest JSON: {msg}", msg.Body);
return;
}
if (apiRequest.PatientNumber == "\"\"")
apiRequest.PatientNumber = string.Empty;
service.SaveRequest(apiRequest);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing request");
throw;
}
}
}
@@ -0,0 +1,459 @@
using System.Collections.Concurrent;
using System.Net;
using System.Text;
using System.Web;
using adas_core.Application.Repositories.Interfaces;
using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Enums;
using adas_core.Domain.Exceptions;
using adas_core.Domain.Models.Filter;
using adas_core.Domain.Models.MongoModels;
using adas_core.Domain.Models.Responses;
using adas_core.Infrastructure.Utils;
using adas_core.module.Relays.Devices;
using adas_core.module.Relays.Models;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MongoDB.Bson;
using MongoDB.Driver;
using Quartz.Util;
namespace adas_core.Infrastructure.Services;
public class RelayService : IRelayService
{
private readonly List<RelayDevice> _devices = [];
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILogger<RelayService> _logger;
private readonly IPointOfCareService _pointOfCareService;
private readonly RelaySettings _relaySettings;
private readonly IRelayRepository _relayRepository;
private readonly ConcurrentDictionary<Tuple<string, int, int>, RelayEnum.Status> _relayWithStatus = new();
private readonly string _url;
private UriBuilder? _builder;
public RelayService(
ILogger<RelayService> logger,
IHttpClientFactory httpClientFactory,
IOptions<RelaySettings> relaySettings,
IPointOfCareService pointOfCareService,
IRelayRepository relayRepository)
{
_httpClientFactory = httpClientFactory;
_pointOfCareService = pointOfCareService;
_relayRepository = relayRepository;
_logger = logger;
_relaySettings = relaySettings.Value;
_url = _relaySettings.RecordingOrApiUrl ?? string.Empty;
Task.Run(async () => await InitRelayWithStatus());
}
public async Task<RelayEnum.Status> CheckRelayStatus(Relay relay)
{
var cacheKey = Tuple.Create(relay.Ip, relay.Port, relay.RelayNumber);
try
{
if (_relaySettings.Cache && relay.Cache)
lock (_relayWithStatus)
{
if (_relayWithStatus.TryGetValue(cacheKey, out var status) &&
status != RelayEnum.Status.NotInitialized)
return status;
_logger.LogDebug("Relay status not found in cache: {Dct}",
DictionaryToString(_relayWithStatus));
}
RelayDevice? relayDevice = null;
try
{
relayDevice = GetRelayDevice(relay);
}
catch (Exception e)
{
_logger.LogWarning("Error getting relay device: {EMessage} {EStackTrace}", e.Message, e.StackTrace);
}
if (relayDevice == null && !string.IsNullOrEmpty(_url)) return await GetRelayStatusByOr(relay);
if (relayDevice != null) return relayDevice.GetStatusRelay(relay.RelayNumber);
}
catch (Exception e)
{
_logger.LogError("Error CheckRelayStatus relay {Relay}: {EMessage} {EStackTrace}", relay, e.Message,
e.StackTrace);
lock (_relayWithStatus)
{
_relayWithStatus[cacheKey] = RelayEnum.Status.Unknown;
}
}
return RelayEnum.Status.Unknown;
}
public async Task<RelayEnum.Status> CheckRelayStatus(ObjectId relayId)
{
var relay = await _relayRepository.GetById(relayId);
if(relay == null) return RelayEnum.Status.Unknown;
return await CheckRelayStatus(relay);
}
public async Task PowerOff(Relay relay)
{
var cacheKey = Tuple.Create(relay.Ip, relay.Port, relay.RelayNumber);
if (_relaySettings.Cache && relay.Cache)
lock (_relayWithStatus)
{
if (_relayWithStatus.Any() &&
_relayWithStatus[cacheKey] == RelayEnum.Status.Off)
return;
}
RelayDevice? relayDevice = null;
try
{
relayDevice = GetRelayDevice(relay);
}
catch (Exception e)
{
_logger.LogWarning("Error getting relay device: {EMessage} {EStackTrace}", e.Message, e.StackTrace);
}
if (relayDevice == null && !string.IsNullOrEmpty(_url))
{
_builder = new UriBuilder(_url)
{
Path = $"Relay/{relay.RelayNumber}/powerOff"
};
_logger.LogDebug("Send PowerOff relay {Relay}", relay);
await PowerRelay(relay, _builder);
}
relayDevice?.PowerOffRelay(relay.RelayNumber);
if (_relaySettings.Cache && relay.Cache)
lock (_relayWithStatus)
{
_relayWithStatus[cacheKey] = RelayEnum.Status.Off;
_logger.LogDebug("Relay status cached: {Dct}", DictionaryToString(_relayWithStatus));
}
}
public async Task PowerOn(Relay relay)
{
if (string.IsNullOrEmpty(relay.Driver) || string.IsNullOrEmpty(relay.Ip)) return;
var cacheKey = Tuple.Create(relay.Ip, relay.Port, relay.RelayNumber);
if (_relaySettings.Cache && relay.Cache)
if (_relaySettings.Cache && relay.Cache)
lock (_relayWithStatus)
{
if (_relayWithStatus.Any() &&
_relayWithStatus[cacheKey] == RelayEnum.Status.On)
return;
}
RelayDevice? relayDevice = null;
try
{
relayDevice = GetRelayDevice(relay);
}
catch (Exception e)
{
_logger.LogWarning("Error getting relay device: {EMessage} {EStackTrace}", e.Message, e.StackTrace);
}
if (relayDevice == null && !string.IsNullOrEmpty(_url))
{
_builder = new UriBuilder(_url)
{
Path = $"Relay/{relay.RelayNumber}/powerOn"
};
_logger.LogDebug("Send PowerOn relay {Relay}", relay);
await PowerRelay(relay, _builder);
}
relayDevice?.PowerOnRelay(relay.RelayNumber);
if (_relaySettings.Cache && relay.Cache)
lock (_relayWithStatus)
{
_relayWithStatus[cacheKey] = RelayEnum.Status.On;
_logger.LogDebug("Relay status cached: {Dct}", DictionaryToString(_relayWithStatus));
}
}
public async Task SetManualRelay(RelayEnum.Status status, ObjectId pocId, RelayEnum.Type type)
{
try
{
var poc = await _pointOfCareService.FindById(pocId);
if (poc is { Configuration.RelayIdList: not null })
{
var relay = _relayRepository.GetRelayByTypeInList(poc.Configuration.RelayIdList, type).FirstOrDefault();
if (relay != null) relay.ManualRelayStatus = status;
await _pointOfCareService.UpdateRelayConfig(poc);
_logger.LogDebug("SetManualRelay: {Status}, pocId: {Location}, bed: {Bed}", status, poc.Id, poc.Bed);
}
}
catch (Exception ex)
{
_logger.LogError("Error settings manual relay. Exception: {ex}", ex);
throw;
}
}
public Task<Relay?> GetById(ObjectId relay)
{
return _relayRepository.GetById(relay);
}
public List<Relay> GetRelayInList(List<ObjectId>? relayList)
{
if(relayList == null) return new List<Relay>();
return _relayRepository.GetRelayInList(relayList);
}
public List<Relay> GetRelayByTypeInList(List<ObjectId>? configurationRelayList, RelayEnum.Type type)
{
if(configurationRelayList == null) return new List<Relay>();
return _relayRepository.GetRelayByTypeInList(configurationRelayList, type);
}
public async Task<PaginationResponse<Relay>> GetPaginatedRelays(PaginationFilter filter)
{
var usedRelayIds = await _pointOfCareService.FindAllIdRelaysInUse();
var fluentQuery = _relayRepository.GetPaginatedRelays(filter);
if (filter.FilteredRequest?.InUse != null)
{
bool filterInUse = filter.FilteredRequest.InUse.Value;
var filterBuilder = Builders<Relay>.Filter;
var idFilter = filterInUse
? filterBuilder.In(c => c.Id, usedRelayIds)
: filterBuilder.Not(filterBuilder.In(c => c.Id, usedRelayIds));
fluentQuery.Filter = filterBuilder.And(fluentQuery.Filter, idFilter);
}
var count = await fluentQuery.CountDocumentsAsync();
var data = await fluentQuery
.Skip((filter.PageNumber - 1) * filter.PageSize)
.Limit(filter.PageSize)
.ToListAsync();
if (data == null) return new PaginationResponse<Relay>([], filter.PageNumber, filter.PageSize, count);
foreach (var camera in data)
{
if (camera == null) continue;
bool isInUse = usedRelayIds.Contains(camera.Id);
// Asignación mediante reflexión para el private set
camera.GetType().GetProperty(nameof(Relay.InUse))
?.SetValue(camera, isInUse);
}
return new PaginationResponse<Relay>(data, filter.PageNumber, filter.PageSize, count);
}
public async Task<Relay?> InsertRelay(Relay request)
{
var relayExist = await _relayRepository.GetByName(request.RelayName);
if(relayExist != null) throw new Exception($"Relay with name {request.RelayName} already exists");
return await _relayRepository.InsertOneRelayAsync(request);
}
public Task<Relay?> UpdateRelayById(ObjectId objectId, Relay relay)
{
return _relayRepository.UpdateRelayAsync(objectId, relay);
}
public event EventHandler<Tuple<RelayDevice, int>>? RelayStatusChanged;
private async Task InitRelayWithStatus()
{
try
{
var pocConfigList = await _pointOfCareService.GetAllConfigs();
var relayTasks = new List<Task>();
pocConfigList.ForEach(poc =>
{
if (poc.Configuration?.RelayList == null) return;
relayTasks.AddRange(from relayConf in poc.Configuration.RelayList
let statusTask = CheckRelayStatus(relayConf)
select statusTask.ContinueWith(task =>
{
if (task.IsCompletedSuccessfully)
{
var cackeKey = Tuple.Create(relayConf.Ip, relayConf.Port, relayConf.RelayNumber);
if (!relayConf.Cache || !relayConf.Cache) return;
lock (_relayWithStatus)
{
_relayWithStatus[cackeKey] = task.Result;
}
}
else if (task.IsFaulted)
{
// Manejar la excepción si la llamada asincrónica falla
_logger.LogError("Error al obtener el estado del relé {RelayParsedIp}: {TaskException}",
relayConf.Ip, task.Exception.Message);
}
}));
});
await Task.WhenAll(relayTasks);
lock (_relayWithStatus)
{
_logger.LogDebug("Relay status cached: {Dct}", DictionaryToString(_relayWithStatus));
}
}
catch (Exception ex)
{
Console.WriteLine("Exception setting relay with status: " + ex.Message);
}
}
private RelayDevice? GetRelayDevice(Relay relay)
{
if(relay.Ip.IsNullOrWhiteSpace() || relay.Port == 0) return null;
var device = _devices.FirstOrDefault(d => d.Relay.Ip == relay.Ip && d.Relay.Port == relay.Port);
if (device != null) return device;
var type = TypesUtils.GetDriver("Relay", relay.Driver ?? string.Empty);
var constructor = type.GetConstructor([typeof(Relay), typeof(RelaySettings)]);
if (constructor == null) throw new AdasException("Constructor not found for relay device");
var relayDevice = (RelayDevice)constructor.Invoke([relay, _relaySettings]);
if (relayDevice == null) throw new AdasException("Relay device not found");
relayDevice.RelayStatusChanged += (_, outletId) =>
{
var cacheKey = Tuple.Create(relay.Ip, relay.Port, outletId);
var value = relayDevice.GetStatusRelay(outletId);
lock (_relayWithStatus)
{
_relayWithStatus[cacheKey] = value;
}
_logger.LogDebug("Relay status changed for {Key} with value {Value}", cacheKey, value);
RelayStatusChanged?.Invoke(this, Tuple.Create(relayDevice, outletId));
};
_devices.Add(relayDevice);
return relayDevice;
}
private async Task PowerRelay(Relay relay, UriBuilder builder)
{
var query = HttpUtility.ParseQueryString(builder.Query);
query["driver"] = relay.Driver;
query["host"] = relay.Ip;
query["port"] = relay.Port.ToString();
query["relayName"] = relay.RelayName;
query["relays"] = relay.Total.ToString();
query["username"] = relay.Username;
query["password"] = relay.Password;
builder.Query = query.ToString();
HttpRequestMessage request = new()
{
RequestUri = builder.Uri,
Method = HttpMethod.Post
};
try
{
using var client = _httpClientFactory.CreateClient();
var httpResponse = await client.SendAsync(request);
if (!httpResponse.StatusCode.Equals(HttpStatusCode.OK))
_logger.LogDebug("Send PowerRelay relay {Relay}", relay);
}
catch (Exception e)
{
_logger.LogError("Error PowerRelay relay {Relay}: {EMessage} {EStackTrace}", relay, e.Message,
e.StackTrace);
}
}
private static string DictionaryToString(ConcurrentDictionary<Tuple<string, int, int>, RelayEnum.Status> dictionary)
{
var builder = new StringBuilder();
foreach (var pair in dictionary)
builder.AppendLine($"Device ID: {pair.Key.Item1}, Port: {pair.Key.Item2}, Status: {pair.Value}");
return builder.ToString();
}
private async Task<RelayEnum.Status> GetRelayStatusByOr(Relay relay)
{
var cacheKey = Tuple.Create(relay.Ip, relay.Port, relay.RelayNumber);
_builder = new UriBuilder(_url)
{
Path = $"Relay/{relay.RelayNumber}/status"
};
var query = HttpUtility.ParseQueryString(_builder.Query);
query["driver"] = relay.Driver;
query["host"] = relay.Ip;
query["port"] = relay.Port.ToString();
query["relayName"] = relay.RelayName;
query["relays"] = relay.Total.ToString();
query["username"] = relay.Username;
query["password"] = relay.Password;
query["mode"] = relay.Mode.ToString();
query["refreshTime"] = "0";
_builder.Query = query.ToString();
HttpRequestMessage request = new()
{
RequestUri = _builder.Uri,
Method = HttpMethod.Get
};
using var client = _httpClientFactory.CreateClient();
client.Timeout = new TimeSpan(0, 0, 3);
var httpResponse = await client.SendAsync(request);
if (httpResponse.StatusCode.Equals(HttpStatusCode.OK))
{
var responseContent = httpResponse.Content;
var response = await responseContent.ReadAsStringAsync();
response = response.Replace("\"", "");
var relayStatusParsed = (RelayEnum.Status)Enum.Parse(typeof(RelayEnum.Status), response);
if (_relaySettings.Cache && relay.Cache)
lock (_relayWithStatus)
{
_relayWithStatus[cacheKey] = relayStatusParsed;
_logger.LogDebug("Relay status cached: {Dct}", DictionaryToString(_relayWithStatus));
}
return relayStatusParsed;
}
if (_relaySettings.Cache && relay.Cache)
lock (_relayWithStatus)
{
_relayWithStatus[cacheKey] = RelayEnum.Status.Unknown;
_logger.LogDebug("Relay status cached: {Dct}", DictionaryToString(_relayWithStatus));
}
return RelayEnum.Status.Unknown;
}
}
@@ -0,0 +1,282 @@
using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Models.AppSettings;
using adas_core.Domain.Models.SystemAlerts;
using EasyNetQ;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Diagnostics;
namespace adas_core.Infrastructure.Services;
public class SendAlertService(
IOptions<RabbitMqSettings> rabbitMqSettings,
ILogger<SendAlertService> logger)
: ISendAlertService
{
private readonly string _errorObservationsQueue = $"Error{rabbitMqSettings.Value.ObservationsQueue}";
private readonly string _errorPatientsQueue = $"Error{rabbitMqSettings.Value.PatientsQueue}";
private readonly string _errorPumpsQueue = $"Error{rabbitMqSettings.Value.PumpsQueue}";
private readonly string _errorRecordingQueue = $"Error{rabbitMqSettings.Value.RecordingQueue}";
private readonly string _errorTreatmetsQueue = $"Error{rabbitMqSettings.Value.TreatmentsQueue}";
private readonly string? _rabbitConnectionString = rabbitMqSettings.Value.ConnectionString;
//readonly PlatformID[] _windowsPlatforms;
////TODO new ws private static DefaultWebSocketHandler defaultWebSocketHandler = new ();
//_windowsPlatforms = new[]
//{
// PlatformID.Win32NT,
// PlatformID.Win32S,
// PlatformID.Win32Windows,
// PlatformID.WinCE
//};
public async Task<List<Queue>> GetQueues()
{
if (_rabbitConnectionString != null) return await GetQueuesAsync();
logger.LogError("Rabbit connection string not defined in web config");
return [];
}
public List<Performance> GetPerformance()
{
logger.LogDebug("Starting check performance data from hospitals");
var list = new List<Performance>();
try
{
list.Add(GetConsumedCpu());
list.Add(GetConsumedRam());
list.AddRange(GetConsumedStorages());
}
catch (Exception e)
{
logger.LogError("Error check error performance data from hospitals: {eMessage} {eStackTrace}",
e.Message, e.StackTrace);
}
return list;
}
public async Task<List<ApiClients>> GetApiClients()
{
return await GetApiClientsAsync();
}
private async Task<List<Queue>> GetQueuesAsync()
{
logger.LogDebug("Starting check rabbitMQ data from hospitals");
var errorQueues = new List<Queue>();
var errorQueuesNames = new List<string>();
try
{
var services = new ServiceCollection();
services.AddEasyNetQ(_rabbitConnectionString);
var provider = services.BuildServiceProvider();
var bus = provider.GetRequiredService<IBus>();
var advanced = bus.Advanced;
if (!string.IsNullOrEmpty(_errorRecordingQueue))
errorQueuesNames.Add(_errorRecordingQueue);
if (!string.IsNullOrEmpty(_errorPatientsQueue))
errorQueuesNames.Add(_errorPatientsQueue);
if (!string.IsNullOrEmpty(_errorTreatmetsQueue))
errorQueuesNames.Add(_errorTreatmetsQueue);
if (!string.IsNullOrEmpty(_errorObservationsQueue))
errorQueuesNames.Add(_errorObservationsQueue);
if (!string.IsNullOrEmpty(_errorPumpsQueue))
errorQueuesNames.Add(_errorPumpsQueue);
foreach (var errorQueueName in errorQueuesNames.Distinct())
{
var stats = await advanced.GetQueueStatsAsync(errorQueueName);
errorQueues.Add(new Queue
{
Name = errorQueueName,
Messages = stats.MessagesCount,
Consumers = stats.ConsumersCount
});
}
}
catch (Exception e)
{
logger.LogError("Error checking RabbitMQ queues: {msg} {stack}",
e.Message, e.StackTrace);
}
return errorQueues;
}
public Performance GetConsumedCpu()
{
Performance performance = new();
try
{
var currentProcess = Process.GetCurrentProcess();
var percentage = currentProcess.TotalProcessorTime.TotalMilliseconds / Environment.ProcessorCount / 10;
performance = new Performance
{
Name = "CPU",
PercentageConsumed = percentage,
ValueTotal = 100,
Unit = "%"
};
}
catch (Exception e)
{
logger.LogError("Error check CPU performance: {eMessage} {eStackTrace}", e.Message, e.StackTrace);
}
return performance;
}
public Performance GetConsumedRam()
{
Performance performance = new();
try
{
var totalMemoryBytes = GC.GetTotalMemory(false);
var totalMemoryGb = Math.Round((double)totalMemoryBytes / 1024 / 1024 / 1024, 2);
performance = new Performance
{
Name = "RAM",
ValueTotal = totalMemoryGb,
ValueConsumed = totalMemoryGb,
PercentageConsumed = 100,
Unit = "GB"
};
}
catch (Exception e)
{
logger.LogError("Error check RAM performance: {eMessage} {eStackTrace}", e.Message, e.StackTrace);
}
return performance;
}
public Performance GetConsumedStorage(DriveInfo drive)
{
Performance performance = new();
try
{
double percentage = 0;
//Total storage
double valueTotal = drive.TotalSize;
//Consumed storage
var value = valueTotal - drive.AvailableFreeSpace;
if (valueTotal != 0)
{
percentage = Math.Round(value * 100 / valueTotal, 2); //%
valueTotal = Math.Round(valueTotal / 1024 / 1024 / 1024, 2); //Bytes -> GB
}
value = Math.Round(value / 1024 / 1024 / 1024, 2); //Bytes -> GB
performance = new Performance
{
Name = "STORAGE " + drive.Name,
ValueConsumed = value,
ValueTotal = valueTotal,
PercentageConsumed = percentage,
Unit = "GB"
};
}
catch (Exception e)
{
logger.LogError("Error check Storage performance: {eMessage} {eStackTrace}", e.Message, e.StackTrace);
}
return performance;
}
private List<Performance> GetConsumedStorages()
{
var list = new List<Performance>();
try
{
foreach (var drive in DriveInfo.GetDrives())
{
if (!drive.IsReady) continue;
try
{
var performance = GetConsumedStorage(drive);
list.Add(performance);
}
catch (Exception e)
{
logger.LogError("Error check Storage drive {drive} in performance: {eMessage}", drive.Name,
e.Message);
}
}
}
catch (Exception e)
{
logger.LogError("Error check Storages performance: {eMessage}", e.Message);
}
return list;
}
private async Task<List<ApiClients>> GetApiClientsAsync()
{
logger.LogDebug("Starting check conected clients from hospitals");
var clientsList = new List<ApiClients>();
try
{
var clients = await GetWebSocketClients();
if (clients != null)
clientsList.Add(clients);
}
catch (Exception e)
{
logger.LogError("Error check error conected clients from hospitals: {eMessage} {eStackTrace}",
e.Message, e.StackTrace);
}
return clientsList;
}
private Task<ApiClients?> GetWebSocketClients()
{
ApiClients apiClients = new();
try
{
//TODO new ws apiClients = defaultWebSocketHandler.GetSubscribersConected();
//apiClients = webSocketHandler.GetSubscribersConected();
}
catch (Exception e)
{
logger.LogError("Error check WebSocket Clients: {eMessage} {eStackTrace}", e.Message, e.StackTrace);
}
return Task.FromResult<ApiClients?>(apiClients);
}
}