< Summary

Information
Class: dotnet_etcd.GrpcChannelFactory
Assembly: dotnet-etcd
File(s): /home/runner/work/dotnet-etcd/dotnet-etcd/dotnet-etcd/GrpcChannelFactory.cs
Line coverage
100%
Covered lines: 55
Uncovered lines: 0
Coverable lines: 55
Total lines: 103
Line coverage: 100%
Branch coverage
100%
Covered branches: 6
Total branches: 6
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
CreateChannel(...)100%66100%

File(s)

/home/runner/work/dotnet-etcd/dotnet-etcd/dotnet-etcd/GrpcChannelFactory.cs

#LineLine coverage
 1using System;
 2using System.Linq;
 3using System.Net.Http;
 4using System.Net.Security;
 5using Grpc.Core;
 6using Grpc.Net.Client;
 7using Grpc.Net.Client.Balancer;
 8using Grpc.Net.Client.Configuration;
 9using Microsoft.Extensions.DependencyInjection;
 10
 11namespace dotnet_etcd;
 12
 13/// <summary>
 14///     Factory for creating gRPC channels
 15/// </summary>
 16public class GrpcChannelFactory
 17{
 118    private static readonly MethodConfig DefaultGrpcMethodConfig = new()
 119    {
 120        Names = { MethodName.Default },
 121        RetryPolicy = new RetryPolicy
 122        {
 123            MaxAttempts = 5,
 124            InitialBackoff = TimeSpan.FromSeconds(1),
 125            MaxBackoff = TimeSpan.FromSeconds(5),
 126            BackoffMultiplier = 1.5,
 127            RetryableStatusCodes = { StatusCode.Unavailable }
 128        }
 129    };
 30
 131    private static readonly RetryThrottlingPolicy DefaultRetryThrottlingPolicy = new()
 132    {
 133        MaxTokens = 10,
 134        TokenRatio = 0.1
 135    };
 36
 37    private const string StaticHostsPrefix = "static://";
 38
 39    /// <summary>
 40    ///     Creates a gRPC channel with the specified configuration
 41    /// </summary>
 42    /// <param name="connectionString">The connection string</param>
 43    /// <param name="port">The port to use</param>
 44    /// <param name="serverName">The server name</param>
 45    /// <param name="credentials">The credentials to use</param>
 46    /// <param name="configureChannelOptions">Optional configuration for channel options</param>
 47    /// <param name="configureSslOptions">Optional configuration for SSL options (for custom SSL certificates)</param>
 48    /// <returns>A gRPC channel</returns>
 49    public GrpcChannel CreateChannel(
 50        string connectionString,
 51        int port,
 52        string serverName,
 53        ChannelCredentials credentials,
 54        Action<GrpcChannelOptions> configureChannelOptions = null,
 55        Action<SslClientAuthenticationOptions> configureSslOptions = null)
 1456    {
 1457        var parser = new ConnectionStringParser();
 1458        var (uris, isDnsConnection) = parser.ParseConnectionString(connectionString, port, credentials);
 59
 1460        var httpHandler = new SocketsHttpHandler
 1461        {
 1462            KeepAlivePingDelay = TimeSpan.FromSeconds(30),
 1463            KeepAlivePingTimeout = TimeSpan.FromSeconds(30),
 1464            KeepAlivePingPolicy = HttpKeepAlivePingPolicy.Always
 1465        };
 66
 67        // Configure SSL options if provided - this is the correct way for gRPC .NET
 1468        if (configureSslOptions != null)
 169        {
 170            var sslOptions = new SslClientAuthenticationOptions();
 171            configureSslOptions(sslOptions);
 172            httpHandler.SslOptions = sslOptions;
 173        }
 74
 1475        var options = new GrpcChannelOptions
 1476        {
 1477            ServiceConfig = new ServiceConfig
 1478            {
 1479                MethodConfigs = { DefaultGrpcMethodConfig },
 1480                RetryThrottling = DefaultRetryThrottlingPolicy,
 1481                LoadBalancingConfigs = { new RoundRobinConfig() }
 1482            },
 1483            HttpHandler = httpHandler,
 1484            DisposeHttpClient = true,
 1485            ThrowOperationCanceledOnCancellation = true,
 1486            Credentials = credentials
 1487        };
 88
 1489        configureChannelOptions?.Invoke(options);
 90
 1491        if (isDnsConnection)
 192        {
 193            return GrpcChannel.ForAddress(uris[0].ToString(), options);
 94        }
 95
 4196        var factory = new StaticResolverFactory(addr => uris.Select(i => new BalancerAddress(i.Host, i.Port)).ToArray())
 1397        var services = new ServiceCollection();
 1398        services.AddSingleton<ResolverFactory>(factory);
 1399        options.ServiceProvider = services.BuildServiceProvider();
 100
 13101        return GrpcChannel.ForAddress($"{StaticHostsPrefix}{serverName}", options);
 14102    }
 103}