< Summary - Kestrun — Combined Coverage

Information
Class: Kestrun.Hosting.KestrunHostSignalRExtensions
Assembly: Kestrun
File(s): /home/runner/work/Kestrun/Kestrun/src/CSharp/Kestrun/Hosting/KestrunHostSignalRExtensions.cs
Tag: Kestrun/Kestrun@0d738bf294e6281b936d031e1979d928007495ff
Line coverage
82%
Covered lines: 55
Uncovered lines: 12
Coverable lines: 67
Total lines: 176
Line coverage: 82%
Branch coverage
63%
Covered branches: 19
Total branches: 30
Branch coverage: 63.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 10/15/2025 - 21:27:26 Line coverage: 0% (0/55) Branch coverage: 0% (0/30) Total lines: 141 Tag: Kestrun/Kestrun@c33ec02a85e4f8d6061aeaab5a5e8c3a8b66559412/15/2025 - 04:25:23 Line coverage: 82% (55/67) Branch coverage: 63.3% (19/30) Total lines: 176 Tag: Kestrun/Kestrun@e333660af9731cab5ae4c14a12f3bb84a8fabc7d 10/15/2025 - 21:27:26 Line coverage: 0% (0/55) Branch coverage: 0% (0/30) Total lines: 141 Tag: Kestrun/Kestrun@c33ec02a85e4f8d6061aeaab5a5e8c3a8b66559412/15/2025 - 04:25:23 Line coverage: 82% (55/67) Branch coverage: 63.3% (19/30) Total lines: 176 Tag: Kestrun/Kestrun@e333660af9731cab5ae4c14a12f3bb84a8fabc7d

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
GetConnectedClientCount(...)66.66%66100%
BroadcastLogAsync()62.5%9880%
BroadcastEventAsync()62.5%9880%
BroadcastToGroupAsync()62.5%9880%

File(s)

/home/runner/work/Kestrun/Kestrun/src/CSharp/Kestrun/Hosting/KestrunHostSignalRExtensions.cs

#LineLine coverage
 1using Kestrun.SignalR;
 2
 3namespace Kestrun.Hosting;
 4
 5/// <summary>
 6/// Extension methods for KestrunHost to support SignalR real-time broadcasting.
 7/// </summary>
 8public static class KestrunHostSignalRExtensions
 9{
 10    /// <summary>
 11    /// Gets the number of currently connected SignalR clients if the Kestrun hub is configured.
 12    /// </summary>
 13    /// <param name="host">The KestrunHost instance.</param>
 14    /// <returns>The count of connected clients, or null if SignalR hub/connection tracking is not configured.</returns>
 15    public static int? GetConnectedClientCount(this KestrunHost host)
 16    {
 17        try
 18        {
 419            var svcProvider = host.App?.Services;
 320            return svcProvider == null
 321                ? null
 322                : svcProvider.GetService(typeof(IConnectionTracker)) is IConnectionTracker tracker ? tracker.ConnectedCo
 23        }
 124        catch (InvalidOperationException)
 25        {
 26            // App not built yet
 127            return null;
 28        }
 429    }
 30
 31    /// <summary>
 32    /// Broadcasts a log message to all connected SignalR clients using the best available service provider.
 33    /// </summary>
 34    /// <param name="host">The KestrunHost instance.</param>
 35    /// <param name="level">The log level (e.g., Information, Warning, Error, Debug, Verbose).</param>
 36    /// <param name="message">The log message to broadcast.</param>
 37    /// <param name="httpContext">Optional: The current HttpContext, if available.</param>
 38    /// <param name="cancellationToken">Optional: Cancellation token.</param>
 39    public static async Task<bool> BroadcastLogAsync(this KestrunHost host, string level, string message, HttpContext? h
 40    {
 841        if (httpContext != null)
 42        {
 043            var ctx = new Models.KestrunContext(host, httpContext);
 044            return await ctx.BroadcastLogAsync(level, message, cancellationToken).ConfigureAwait(false);
 45        }
 46        // Fallback to service resolution when no HttpContext
 47        try
 48        {
 849            var svcProvider = host.App?.Services;
 750            if (svcProvider == null)
 51            {
 052                host.Logger.Warning("No service provider available to resolve IRealtimeBroadcaster.");
 053                return false;
 54            }
 755            if (svcProvider.GetService(typeof(IRealtimeBroadcaster)) is not IRealtimeBroadcaster broadcaster)
 56            {
 157                host.Logger.Warning("IRealtimeBroadcaster service is not registered. Make sure SignalR is configured wit
 158                return false;
 59            }
 60            try
 61            {
 662                await broadcaster.BroadcastLogAsync(level, message, cancellationToken).ConfigureAwait(false);
 563                host.Logger.Debug("Broadcasted log message via SignalR: {Level} - {Message}", level, message);
 564                return true;
 65            }
 166            catch (Exception ex)
 67            {
 168                host.Logger.Error(ex, "Failed to broadcast log message: {Level} - {Message}", level, message);
 169                return false;
 70            }
 71        }
 172        catch (InvalidOperationException)
 73        {
 74            // App not built yet
 175            host.Logger.Warning("WebApplication is not built yet. Call Build() first.");
 176            return false;
 77        }
 878    }
 79
 80    /// <summary>
 81    /// Broadcasts an event to all connected SignalR clients using the best available service provider.
 82    /// </summary>
 83    /// <param name="host">The KestrunHost instance.</param>
 84    /// <param name="eventName">The name of the event to broadcast.</param>
 85    /// <param name="data">Optional data to include with the event.</param>
 86    /// <param name="httpContext">Optional: The current HttpContext, if available.</param>
 87    /// <param name="cancellationToken">Optional: Cancellation token.</param>
 88    public static async Task<bool> BroadcastEventAsync(this KestrunHost host, string eventName, object? data = null, Htt
 89    {
 590        if (httpContext != null)
 91        {
 092            var ctx = new Models.KestrunContext(host, httpContext);
 093            return await ctx.BroadcastEventAsync(eventName, data, cancellationToken).ConfigureAwait(false);
 94        }
 95        try
 96        {
 597            var svcProvider = host.App?.Services;
 498            if (svcProvider == null)
 99            {
 0100                host.Logger.Warning("No service provider available to resolve IRealtimeBroadcaster.");
 0101                return false;
 102            }
 4103            if (svcProvider.GetService(typeof(IRealtimeBroadcaster)) is not IRealtimeBroadcaster broadcaster)
 104            {
 1105                host.Logger.Warning("IRealtimeBroadcaster service is not registered. Make sure SignalR is configured wit
 1106                return false;
 107            }
 108            try
 109            {
 3110                await broadcaster.BroadcastEventAsync(eventName, data, cancellationToken).ConfigureAwait(false);
 2111                host.Logger.Debug("Broadcasted event via SignalR: {EventName}", eventName);
 2112                return true;
 113            }
 1114            catch (Exception ex)
 115            {
 1116                host.Logger.Error(ex, "Failed to broadcast event: {EventName}", eventName);
 1117                return false;
 118            }
 119        }
 1120        catch (InvalidOperationException)
 121        {
 122            // App not built yet
 1123            host.Logger.Warning("WebApplication is not built yet. Call Build() first.");
 1124            return false;
 125        }
 5126    }
 127
 128    /// <summary>
 129    /// Broadcasts a message to a specific SignalR group using the best available service provider.
 130    /// </summary>
 131    /// <param name="host">The KestrunHost instance.</param>
 132    /// <param name="groupName">The name of the group to broadcast to.</param>
 133    /// <param name="method">The hub method name to invoke on clients.</param>
 134    /// <param name="message">The message to broadcast.</param>
 135    /// <param name="httpContext">Optional: The current HttpContext, if available.</param>
 136    /// <param name="cancellationToken">Optional: Cancellation token.</param>
 137    public static async Task<bool> BroadcastToGroupAsync(this KestrunHost host, string groupName, string method, object?
 138    {
 8139        if (httpContext != null)
 140        {
 0141            var ctx = new Models.KestrunContext(host, httpContext);
 0142            return await ctx.BroadcastToGroupAsync(groupName, method, message, cancellationToken).ConfigureAwait(false);
 143        }
 144        try
 145        {
 8146            var svcProvider = host.App?.Services;
 7147            if (svcProvider == null)
 148            {
 0149                host.Logger.Warning("No service provider available to resolve IRealtimeBroadcaster.");
 0150                return false;
 151            }
 7152            if (svcProvider.GetService(typeof(IRealtimeBroadcaster)) is not IRealtimeBroadcaster broadcaster)
 153            {
 1154                host.Logger.Warning("IRealtimeBroadcaster service is not registered. Make sure SignalR is configured wit
 1155                return false;
 156            }
 157            try
 158            {
 6159                await broadcaster.BroadcastToGroupAsync(groupName, method, message, cancellationToken).ConfigureAwait(fa
 5160                host.Logger.Debug("Broadcasted to group {GroupName} via method {Method}", groupName, method);
 5161                return true;
 162            }
 1163            catch (Exception ex)
 164            {
 1165                host.Logger.Error(ex, "Failed to broadcast to group {GroupName}", groupName);
 1166                return false;
 167            }
 168        }
 1169        catch (InvalidOperationException)
 170        {
 171            // App not built yet
 1172            host.Logger.Warning("WebApplication is not built yet. Call Build() first.");
 1173            return false;
 174        }
 8175    }
 176}