From b5fd3c8a83bd59d8fcc9ee33daadd98d08f8736a Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Tue, 5 Mar 2024 10:41:50 -0800 Subject: [PATCH] docs Signed-off-by: Yury-Fridlyand --- csharp/lib/ConnectionConfiguration.cs | 323 +++++++++++++++++++------- 1 file changed, 239 insertions(+), 84 deletions(-) diff --git a/csharp/lib/ConnectionConfiguration.cs b/csharp/lib/ConnectionConfiguration.cs index f3b1b71e52..b510fcf0be 100644 --- a/csharp/lib/ConnectionConfiguration.cs +++ b/csharp/lib/ConnectionConfiguration.cs @@ -8,6 +8,11 @@ namespace Glide; public abstract class ConnectionConfiguration { + + #region Structs and Enums definitions + /// + /// A mirror of ConnectionRequest from connection_request.proto. + /// [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] internal struct ConnectionRequest { @@ -17,34 +22,57 @@ internal struct ConnectionRequest public bool cluster_mode; public uint request_timeout; public ReadFrom read_from; - public ConnectionRetryStrategy connection_retry_strategy; + public RetryStrategy connection_retry_strategy; public AuthenticationInfo authentication_info; public uint database_id; - public ProtocolVersion protocol; + public Protocol protocol; [MarshalAs(UnmanagedType.LPStr)] public string? client_name; } + /// + /// Represents the address and port of a node in the cluster. + /// [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] internal struct NodeAddress { [MarshalAs(UnmanagedType.LPStr)] - public string host; - public ushort port; + public string Host; + public ushort Port; } + /// + /// Represents the strategy used to determine how and when to reconnect, in case of connection + /// failures. The time between attempts grows exponentially, to the formula rand(0 ... factor * + /// (exponentBase ^ N)), where N is the number of failed attempts. + /// + /// Once the maximum value is reached, that will remain the time between retry attempts until a + /// reconnect attempt is successful. The client will attempt to reconnect indefinitely. + /// + /// [StructLayout(LayoutKind.Sequential)] - public struct ConnectionRetryStrategy + public struct RetryStrategy { - public uint number_of_retries; - public uint factor; - public uint exponent_base; - - public ConnectionRetryStrategy(uint number_of_retries, uint factor, uint exponent_base) - { - this.number_of_retries = number_of_retries; - this.factor = factor; - this.exponent_base = exponent_base; + /// + /// Number of retry attempts that the client should perform when disconnected from the server, + /// where the time between retries increases. Once the retries have reached the maximum value, the + /// time between retries will remain constant until a reconnect attempt is successful. + /// + public uint Number_of_retries; + /// + /// The multiplier that will be applied to the waiting time between each retry. + /// + public uint Factor; + /// + /// The exponent base configured for the strategy. + /// + public uint Exponent_base; + + public RetryStrategy(uint number_of_retries, uint factor, uint exponent_base) + { + Number_of_retries = number_of_retries; + Factor = factor; + Exponent_base = exponent_base; } } @@ -52,17 +80,18 @@ public ConnectionRetryStrategy(uint number_of_retries, uint factor, uint exponen internal struct AuthenticationInfo { [MarshalAs(UnmanagedType.LPStr)] - public string? username; + public string? Username; [MarshalAs(UnmanagedType.LPStr)] - public string? password; + public string? Password; public AuthenticationInfo(string? username, string? password) { - this.username = username; - this.password = password; + Username = username; + Password = password; } } + // TODO doc public enum TlsMode : uint { NoTls = 0, @@ -70,23 +99,46 @@ public enum TlsMode : uint InsecureTls = 2, } + /// + /// Represents the client's read from strategy. + /// public enum ReadFrom : uint { + /// + /// Always get from primary, in order to get the freshest data. + /// Primary = 0, + /// + /// Spread the requests between all replicas in a round-robin manner. If no replica is available, route the requests to the primary. + /// PreferReplica = 1, + // TODO: doc or comment out/remove LowestLatency = 2, AZAffinity = 3, } - public enum ProtocolVersion : uint + /// + /// Represents the communication protocol with the server. + /// + public enum Protocol : uint { + /// + /// Use RESP3 to communicate with the server nodes. + /// RESP3 = 0, + /// + /// Use RESP2 to communicate with the server nodes. + /// RESP2 = 1, } + #endregion private static readonly string DEFAULT_HOST = "localhost"; private static readonly ushort DEFAULT_PORT = 6379; + /// + /// Configuration for a standalone client. Use to create an instance. + /// public sealed class StandaloneClientConfiguration : ConnectionConfiguration { internal ConnectionRequest request; @@ -96,6 +148,9 @@ internal StandaloneClientConfiguration() { } internal ConnectionRequest Request() { return request; } } + /// + /// Configuration for a cluster client. Use to create an instance. + /// public sealed class ClusterClientConfiguration : ConnectionConfiguration { internal ConnectionRequest request; @@ -105,6 +160,10 @@ internal ClusterClientConfiguration() { } internal ConnectionRequest Request() { return request; } } + /// + /// Builder for configuration of common parameters for standalone and cluster client. + /// + /// Derived builder class public abstract class ClientConfigurationBuilder : IDisposable where T : ClientConfigurationBuilder, new() { @@ -120,55 +179,74 @@ protected ClientConfigurationBuilder(bool cluster_mode) #region address private readonly List addresses = new(); - public (string? host, ushort? port) Address + /// + /// Add a new address to the list.
+ /// See also . + // + // + + protected (string? host, ushort? port) Address { set { addresses.Add(new NodeAddress { - host = value.host ?? DEFAULT_HOST, - port = value.port ?? DEFAULT_PORT + Host = value.host ?? DEFAULT_HOST, + Port = value.port ?? DEFAULT_PORT }); } } + /// public T WithAddress((string? host, ushort? port) address) { Address = (address.host, address.port); return (T)this; } + /// public T WithAddress((string host, ushort port) address) { Address = (address.host, address.port); return (T)this; } + /// public T WithAddress(string? host, ushort? port) { Address = (host, port); return (T)this; } + /// public T WithAddress(string host, ushort port) { Address = (host, port); return (T)this; } + /// + /// Add a new address to the list with default port. + /// public T WithAddress(string host) { Address = (host, DEFAULT_PORT); return (T)this; } + /// + /// Add a new address to the list with default host. + /// public T WithAddress(ushort port) { Address = (DEFAULT_HOST, port); return (T)this; } - public class AddressBuilder + /// + /// Syntax sugar helper class for adding addresses. + /// + public sealed class AddressBuilder { private readonly ClientConfigurationBuilder owner; @@ -177,24 +255,28 @@ internal AddressBuilder(ClientConfigurationBuilder owner) this.owner = owner; } + /// public static AddressBuilder operator +(AddressBuilder builder, (string? host, ushort? port) address) { builder.owner.WithAddress(address); return builder; } + /// public static AddressBuilder operator +(AddressBuilder builder, (string host, ushort port) address) { builder.owner.WithAddress(address); return builder; } + /// public static AddressBuilder operator +(AddressBuilder builder, string host) { builder.owner.WithAddress(host); return builder; } + /// public static AddressBuilder operator +(AddressBuilder builder, ushort port) { builder.owner.WithAddress(port); @@ -202,6 +284,19 @@ internal AddressBuilder(ClientConfigurationBuilder owner) } } + /// + /// DNS Addresses and ports of known nodes in the cluster. If the server is in cluster mode the + /// list can be partial, as the client will attempt to map out the cluster and find all nodes. If + /// the server is in standalone mode, only nodes whose addresses were provided will be used by the + /// client. + /// + /// For example: + /// [ + /// ("sample-address-0001.use1.cache.amazonaws.com", 6378), + /// ("sample-address-0002.use2.cache.amazonaws.com"), + /// ("sample-address-0002.use3.cache.amazonaws.com", 6380) + /// ] + /// public AddressBuilder Addresses { get @@ -212,7 +307,11 @@ public AddressBuilder Addresses } // TODO possible options : list and array #endregion - + #region TLS + /// + /// Configure whether communication with the server should use Transport Level Security.
+ /// Should match the TLS configuration of the server/cluster, otherwise the connection attempt will fail. + ///
public TlsMode TlsMode { set @@ -220,19 +319,25 @@ public TlsMode TlsMode config.tls_mode = value; } } - + /// public T WithTlsMode(TlsMode tls_mode) { TlsMode = tls_mode; return (T)this; } - + /// public T With(TlsMode tls_mode) { return WithTlsMode(tls_mode); } - - + #endregion + #region Request Timeout + /// + /// The duration in milliseconds that the client should wait for a request to complete. This + /// duration encompasses sending the request, awaiting for a response from the server, and any + /// required reconnections or retries. If the specified timeout is exceeded for a pending request, + /// it will result in a timeout error. If not set, a default value will be used. + /// public uint RequestTimeout { set @@ -240,14 +345,17 @@ public uint RequestTimeout config.request_timeout = value; } } - + /// public T WithRequestTimeout(uint request_timeout) { RequestTimeout = request_timeout; return (T)this; } - - + #endregion + #region Read From + /// + /// Configure the client's read from strategy. If not set, will be used. + /// public ReadFrom ReadFrom { set @@ -255,44 +363,26 @@ public ReadFrom ReadFrom config.read_from = value; } } - + /// public T WithReadFrom(ReadFrom read_from) { ReadFrom = read_from; return (T)this; } - + /// public T With(ReadFrom read_from) { return WithReadFrom(read_from); } - - - public ConnectionRetryStrategy ConnectionRetryStrategy - { - set - { - config.connection_retry_strategy = value; - } - } - - public T WithConnectionRetryStrategy(ConnectionRetryStrategy connection_retry_strategy) - { - ConnectionRetryStrategy = connection_retry_strategy; - return (T)this; - } - - public T With(ConnectionRetryStrategy connection_retry_strategy) - { - return WithConnectionRetryStrategy(connection_retry_strategy); - } - - public T WithConnectionRetryStrategy(uint number_of_retries, uint factor, uint exponent_base) - { - return WithConnectionRetryStrategy(new ConnectionRetryStrategy(number_of_retries, factor, exponent_base)); - } - - + #endregion + #region Authentication + /// + /// Configure credentials for authentication process. If none are set, the client will not authenticate itself with the server. + /// + /// + /// username The username that will be used for authenticating connections to the Redis servers. If not supplied, "default" will be used.
+ /// password The password that will be used for authenticating connections to the Redis servers. + ///
public (string? username, string? password) Authentication { set @@ -304,35 +394,28 @@ public T WithConnectionRetryStrategy(uint number_of_retries, uint factor, uint e ); } } - + /// + /// Configure credentials for authentication process. If none are set, the client will not authenticate itself with the server. + /// + /// The username that will be used for authenticating connections to the Redis servers. If not supplied, "default" will be used.> + /// The password that will be used for authenticating connections to the Redis servers. public T WithAuthentication(string? username, string? password) { Authentication = (username, password); return (T)this; } - + /// public T WithAuthentication((string? username, string? password) credentials) { return WithAuthentication(credentials.username, credentials.password); } - - - public uint DataBaseId - { - set - { - config.database_id = value; - } - } - - public T WithDataBaseId(uint dataBaseId) - { - DataBaseId = dataBaseId; - return (T)this; - } - - - public ProtocolVersion ProtocolVersion + #endregion + #region Protocol + /// + /// Configure the protocol version to use. If not set, will be used.
+ /// See also . + ///
+ public Protocol ProtocolVersion { set { @@ -340,19 +423,24 @@ public ProtocolVersion ProtocolVersion } } - public T WithProtocolVersion(ProtocolVersion protocol) + /// + public T WithProtocolVersion(Protocol protocol) { ProtocolVersion = protocol; return (T)this; } - public T With(ProtocolVersion protocol) + /// + public T With(Protocol protocol) { ProtocolVersion = protocol; return (T)this; } - - + #endregion + #region Client Name + /// + /// Client name to be used for the client. Will be used with CLIENT SETNAME command during connection establishment. + /// public string? ClientName { set @@ -361,11 +449,13 @@ public string? ClientName } } + /// public T WithClientName(string? clientName) { ClientName = clientName; return (T)this; } + #endregion public void Dispose() => Clean(); @@ -390,20 +480,85 @@ internal ConnectionRequest Build() } } + /// + /// Represents the configuration settings for a Standalone Redis client. + /// public class StandaloneClientConfigurationBuilder : ClientConfigurationBuilder { public StandaloneClientConfigurationBuilder() : base(false) { } + /// + /// Complete the configuration with given settings. + /// public new StandaloneClientConfiguration Build() { return new StandaloneClientConfiguration() { request = base.Build() }; } + + #region DB ID + // TODO: not used + /// + /// Index of the logical database to connect to. + /// + public uint DataBaseId + { + set + { + config.database_id = value; + } + } + /// + public StandaloneClientConfigurationBuilder WithDataBaseId(uint dataBaseId) + { + DataBaseId = dataBaseId; + return this; + } + #endregion + #region Connection Retry Strategy + /// + /// Strategy used to determine how and when to reconnect, in case of connection failures.
+ /// See also + ///
+ public RetryStrategy ConnectionRetryStrategy + { + set + { + config.connection_retry_strategy = value; + } + } + /// + public StandaloneClientConfigurationBuilder WithConnectionRetryStrategy(RetryStrategy connection_retry_strategy) + { + ConnectionRetryStrategy = connection_retry_strategy; + return this; + } + /// + public StandaloneClientConfigurationBuilder With(RetryStrategy connection_retry_strategy) + { + return WithConnectionRetryStrategy(connection_retry_strategy); + } + /// + /// + /// + /// + public StandaloneClientConfigurationBuilder WithConnectionRetryStrategy(uint number_of_retries, uint factor, uint exponent_base) + { + return WithConnectionRetryStrategy(new RetryStrategy(number_of_retries, factor, exponent_base)); + } + #endregion } + /// + /// Represents the configuration settings for a Cluster Redis client.
+ /// Notes: Currently, the reconnection strategy in cluster mode is not configurable, and exponential backoff with fixed values is used. + ///
public class ClusterClientConfigurationBuilder : ClientConfigurationBuilder { public ClusterClientConfigurationBuilder() : base(true) { } + /// + /// Complete the configuration with given settings. + /// public new ClusterClientConfiguration Build() { return new ClusterClientConfiguration() { request = base.Build() };