< Summary - Combined Code Coverage

Information
Class: NLightning.Infrastructure.Protocol.Services.MessageService
Assembly: NLightning.Infrastructure
File(s): /home/runner/work/nlightning/nlightning/src/NLightning.Infrastructure/Protocol/Services/MessageService.cs
Tag: 36_15743069263
Line coverage
54%
Covered lines: 27
Uncovered lines: 23
Coverable lines: 50
Total lines: 140
Line coverage: 54%
Branch coverage
41%
Covered branches: 10
Total branches: 24
Branch coverage: 41.6%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_IsConnected()50%22100%
.ctor(...)100%11100%
SendMessageAsync()50%4.37471.43%
ReceiveMessage(...)30%54.231023.81%
RaiseException(...)0%620%
Dispose()100%11100%
Dispose(...)66.67%6.17683.33%
Finalize()100%210%

File(s)

/home/runner/work/nlightning/nlightning/src/NLightning.Infrastructure/Protocol/Services/MessageService.cs

#LineLine coverage
 1using Microsoft.Extensions.Logging;
 2
 3namespace NLightning.Infrastructure.Protocol.Services;
 4
 5using Domain.Protocol.Interfaces;
 6using Domain.Protocol.Messages;
 7using Domain.Protocol.Payloads;
 8using Domain.Serialization.Interfaces;
 9using Domain.Transport;
 10using Domain.Utils;
 11using Exceptions;
 12
 13/// <summary>
 14/// Service for sending and receiving messages.
 15/// </summary>
 16/// <remarks>
 17/// This class is used to send and receive messages over a transport service.
 18/// </remarks>
 19/// <seealso cref="IMessageService" />
 20internal sealed class MessageService : IMessageService
 21{
 22    private readonly ILogger<IMessageService> _logger;
 23    private readonly IMessageSerializer _messageSerializer;
 24    private readonly ITransportService? _transportService;
 25
 26    private bool _disposed;
 27
 28    /// <inheritdoc />
 29    public event EventHandler<IMessage?>? OnMessageReceived;
 30
 31    public event EventHandler<Exception>? OnExceptionRaised;
 32
 33    /// <inheritdoc />
 434    public bool IsConnected => _transportService?.IsConnected ?? false;
 35
 36    /// <summary>
 37    /// Initializes a new <see cref="MessageService"/> class.
 38    /// </summary>
 39    /// <param name="logger">The logger.</param>
 40    /// <param name="messageSerializer">The message serializer.</param>
 41    /// <param name="transportService">The transport service.</param>
 2042    public MessageService(ILogger<IMessageService> logger, IMessageSerializer messageSerializer,
 2043                          ITransportService transportService)
 44    {
 2045        _logger = logger;
 2046        _messageSerializer = messageSerializer;
 2047        _transportService = transportService;
 48
 2049        _transportService.MessageReceived += ReceiveMessage;
 2050        _transportService.ExceptionRaised += RaiseException;
 2051    }
 52
 53    /// <inheritdoc />
 54    /// <exception cref="ObjectDisposedException">Thrown when the object is disposed.</exception>
 55    public async Task SendMessageAsync(IMessage message, CancellationToken cancellationToken = default)
 56    {
 857        ExceptionUtils.ThrowIfDisposed(_disposed, nameof(MessageService));
 58
 459        if (cancellationToken.IsCancellationRequested)
 060            return;
 61
 462        if (_transportService == null)
 063            throw new InvalidOperationException($"{nameof(MessageService)} is not initialized");
 64
 465        await _transportService.WriteMessageAsync(message, cancellationToken);
 466    }
 67
 68    private void ReceiveMessage(object? _, MemoryStream stream)
 69    {
 70        try
 71        {
 472            var message = _messageSerializer.DeserializeMessageAsync(stream).GetAwaiter().GetResult();
 473            if (message is not null)
 74            {
 475                OnMessageReceived?.Invoke(this, message);
 76            }
 477        }
 078        catch (MessageSerializationException mse)
 79        {
 080            var message = mse.Message;
 081            if (mse.InnerException is PayloadSerializationException pse)
 82            {
 083                if (pse.InnerException is not null)
 084                    message = pse.InnerException.Message;
 85                else
 086                    message = pse.Message;
 87            }
 088            else if (mse.InnerException is not null)
 89            {
 090                message = mse.InnerException.Message;
 91            }
 92
 093            _logger.LogError(mse, "Failed to deserialize message: {Message}", message);
 094            SendMessageAsync(new ErrorMessage(new ErrorPayload(message))).GetAwaiter().GetResult();
 095            RaiseException(this, mse);
 096        }
 097        catch (Exception e)
 98        {
 099            _logger.LogError(e, "Failed to receive message");
 0100            RaiseException(this, e);
 0101        }
 4102    }
 103
 104    private void RaiseException(object? sender, Exception e)
 105    {
 0106        OnExceptionRaised?.Invoke(sender, e);
 0107    }
 108
 109    #region Dispose Pattern
 110
 111    /// <inheritdoc />
 112    /// <remarks>
 113    /// Disposes the TransportService.
 114    /// </remarks>
 115    public void Dispose()
 116    {
 8117        Dispose(true);
 8118        GC.SuppressFinalize(this);
 8119    }
 120
 121    private void Dispose(bool disposing)
 122    {
 8123        if (_disposed)
 0124            return;
 125
 8126        if (disposing)
 127        {
 8128            _transportService?.Dispose();
 129        }
 130
 8131        _disposed = true;
 8132    }
 133
 134    ~MessageService()
 135    {
 0136        Dispose(false);
 0137    }
 138
 139    #endregion
 140}