< 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{
 218    private static readonly MethodConfig DefaultGrpcMethodConfig = new()
 219    {
 220        Names = { MethodName.Default },
 221        RetryPolicy = new RetryPolicy
 222        {
 223            MaxAttempts = 5,
 224            InitialBackoff = TimeSpan.FromSeconds(1),
 225            MaxBackoff = TimeSpan.FromSeconds(5),
 226            BackoffMultiplier = 1.5,
 227            RetryableStatusCodes = { StatusCode.Unavailable }
 228        }
 229    };
 30
 231    private static readonly RetryThrottlingPolicy DefaultRetryThrottlingPolicy = new()
 232    {
 233        MaxTokens = 10,
 234        TokenRatio = 0.1
 235    };
 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)
 10956    {
 10957        var parser = new ConnectionStringParser();
 10958        var (uris, isDnsConnection) = parser.ParseConnectionString(connectionString, port, credentials);
 59
 10960        var httpHandler = new SocketsHttpHandler
 10961        {
 10962            KeepAlivePingDelay = TimeSpan.FromSeconds(30),
 10963            KeepAlivePingTimeout = TimeSpan.FromSeconds(30),
 10964            KeepAlivePingPolicy = HttpKeepAlivePingPolicy.Always
 10965        };
 66
 67        // Configure SSL options if provided - this is the correct way for gRPC .NET
 10968        if (configureSslOptions != null)
 369        {
 370            var sslOptions = new SslClientAuthenticationOptions();
 371            configureSslOptions(sslOptions);
 372            httpHandler.SslOptions = sslOptions;
 373        }
 74
 10975        var options = new GrpcChannelOptions
 10976        {
 10977            ServiceConfig = new ServiceConfig
 10978            {
 10979                MethodConfigs = { DefaultGrpcMethodConfig },
 10980                RetryThrottling = DefaultRetryThrottlingPolicy,
 10981                LoadBalancingConfigs = { new RoundRobinConfig() }
 10982            },
 10983            HttpHandler = httpHandler,
 10984            DisposeHttpClient = true,
 10985            ThrowOperationCanceledOnCancellation = true,
 10986            Credentials = credentials
 10987        };
 88
 10989        configureChannelOptions?.Invoke(options);
 90
 10991        if (isDnsConnection)
 192        {
 193            return GrpcChannel.ForAddress(uris[0].ToString(), options);
 94        }
 95
 32796        var factory = new StaticResolverFactory(addr => uris.Select(i => new BalancerAddress(i.Host, i.Port)).ToArray())
 10897        var services = new ServiceCollection();
 10898        services.AddSingleton<ResolverFactory>(factory);
 10899        options.ServiceProvider = services.BuildServiceProvider();
 100
 108101        return GrpcChannel.ForAddress($"{StaticHostsPrefix}{serverName}", options);
 109102    }
 103}