@@ -43,6 +43,14 @@ public sealed class GreptimeClientOptions
4343 /// </summary>
4444 public TimeSpan WriteTimeout { get ; set ; } = TimeSpan . FromSeconds ( 30 ) ;
4545
46+ /// <summary>
47+ /// Gets or sets the load-balancing strategy used when multiple
48+ /// <see cref="Endpoints"/> are configured. Ignored for the single-endpoint
49+ /// case, which always uses a direct channel. Defaults to
50+ /// <see cref="LoadBalancingStrategy.Random"/>.
51+ /// </summary>
52+ public LoadBalancingStrategy LoadBalancing { get ; set ; } = LoadBalancingStrategy . Random ;
53+
4654 /// <summary>
4755 /// Returns the effective endpoint list: trimmed, non-whitespace entries of
4856 /// <see cref="Endpoints"/> when the caller populated that list. Falls back
@@ -77,11 +85,15 @@ public void Validate()
7785 var endpoints = ResolveEndpoints ( ) ;
7886 if ( endpoints . Count == 0 )
7987 {
80- var allWhitespace = Endpoints != null && Endpoints . Count > 0 ;
88+ if ( Endpoints != null && Endpoints . Count > 0 )
89+ {
90+ throw new ArgumentException (
91+ "Endpoints was set but contained no non-whitespace entries." ,
92+ nameof ( Endpoints ) ) ;
93+ }
94+
8195 throw new ArgumentException (
82- allWhitespace
83- ? "Endpoints was set but contained no non-whitespace entries."
84- : "At least one endpoint is required (set Endpoints)." ,
96+ "At least one endpoint is required. Set Endpoints; the deprecated Endpoint property is empty or whitespace." ,
8597 nameof ( Endpoints ) ) ;
8698 }
8799
@@ -102,6 +114,15 @@ public void Validate()
102114 nameof ( Endpoints ) ) ;
103115 }
104116
117+ // Reject path/query/fragment: the multi-endpoint balancer uses host:port only
118+ // (BalancerAddress), so a path would silently diverge from the single-endpoint case.
119+ if ( uri . AbsolutePath is not ( "" or "/" ) || ! string . IsNullOrEmpty ( uri . Query ) || ! string . IsNullOrEmpty ( uri . Fragment ) )
120+ {
121+ throw new ArgumentException (
122+ $ "Endpoint '{ endpoint } ' must be a host:port URI without a path, query, or fragment.",
123+ nameof ( Endpoints ) ) ;
124+ }
125+
105126 firstScheme ??= uri . Scheme ;
106127 if ( ! string . Equals ( uri . Scheme , firstScheme , StringComparison . Ordinal ) )
107128 {
@@ -130,6 +151,25 @@ public void Validate()
130151 }
131152}
132153
154+ /// <summary>
155+ /// Client-side load-balancing strategy used when multiple endpoints are
156+ /// configured.
157+ /// </summary>
158+ public enum LoadBalancingStrategy
159+ {
160+ /// <summary>
161+ /// Pick a ready endpoint uniformly at random for each call. Default.
162+ /// Avoids the lock-step herding pattern that round-robin can produce when
163+ /// many short-lived clients start at the same time.
164+ /// </summary>
165+ Random = 0 ,
166+
167+ /// <summary>
168+ /// Cycle through ready endpoints in order.
169+ /// </summary>
170+ RoundRobin = 1 ,
171+ }
172+
133173/// <summary>
134174/// Authentication options for GreptimeDB.
135175/// </summary>
0 commit comments