1515#if ELASTICSEARCH_SERVERLESS
1616using Elastic . Clients . Elasticsearch . Serverless . Requests ;
1717#else
18+
1819using Elastic . Clients . Elasticsearch . Requests ;
20+
1921#endif
2022
2123#if ELASTICSEARCH_SERVERLESS
2224namespace Elastic . Clients . Elasticsearch . Serverless ;
2325#else
26+
2427namespace Elastic . Clients . Elasticsearch ;
2528#endif
2629
@@ -153,16 +156,14 @@ private ValueTask<TResponse> DoRequestCoreAsync<TRequest, TResponse, TRequestPar
153156 ( int ) ProductCheckStatus . NotChecked
154157 ) ;
155158
156- // TODO: Re-enable product check
157- //return productCheckStatus switch
158- //{
159- // (int)ProductCheckStatus.NotChecked => SendRequestWithProductCheck(),
160- // (int)ProductCheckStatus.InProgress or
161- // (int)ProductCheckStatus.Succeeded => SendRequest(),
162- // (int)ProductCheckStatus.Failed => throw new UnsupportedProductException(UnsupportedProductException.InvalidProductError),
163- // _ => throw new InvalidOperationException("unreachable")
164- //};
165- return SendRequest ( ) ;
159+ return productCheckStatus switch
160+ {
161+ ( int ) ProductCheckStatus . NotChecked => SendRequestWithProductCheck ( ) ,
162+ ( int ) ProductCheckStatus . InProgress or
163+ ( int ) ProductCheckStatus . Succeeded => SendRequest ( ) ,
164+ ( int ) ProductCheckStatus . Failed => throw new UnsupportedProductException ( UnsupportedProductException . InvalidProductError ) ,
165+ _ => throw new InvalidOperationException ( "unreachable" )
166+ } ;
166167
167168 ValueTask < TResponse > SendRequest ( )
168169 {
@@ -176,98 +177,85 @@ ValueTask<TResponse> SendRequest()
176177 . Request < TResponse > ( new EndpointPath ( request . HttpMethod , resolvedUrl ) , postData , in openTelemetryData , request . RequestConfig ) ) ;
177178 }
178179
179- //async ValueTask<TResponse> SendRequestWithProductCheck()
180- //{
181- // try
182- // {
183- // return await SendRequestWithProductCheckCore().ConfigureAwait(false);
184- // }
185- // catch
186- // {
187- // // Re-try product check on next request.
188-
189- // // 32-bit read/write operations are atomic and due to the initial memory barrier, we can be sure that
190- // // no other thread executes the product check at the same time. Locked access is not required here.
191- // if (_productCheckStatus is (int)ProductCheckStatus.InProgress)
192- // _productCheckStatus = (int)ProductCheckStatus.NotChecked;
193-
194- // throw;
195- // }
196- //}
197-
198- //async ValueTask<TResponse> SendRequestWithProductCheckCore()
199- //{
200- // // Attach product check header
201-
202- // var hadRequestConfig = false;
203- // HeadersList? originalHeaders = null;
204-
205- // if (request.RequestConfiguration is null)
206- // request.RequestParameters.RequestConfiguration = new RequestConfiguration();
207- // else
208- // {
209- // originalHeaders = request.RequestParameters.RequestConfiguration.ResponseHeadersToParse;
210- // hadRequestConfig = true;
211- // }
212-
213- // request.RequestParameters.RequestConfiguration.ResponseHeadersToParse = request.RequestParameters.RequestConfiguration.ResponseHeadersToParse.Count == 0
214- // ? new HeadersList("x-elastic-product")
215- // : new HeadersList(request.RequestParameters.RequestConfiguration.ResponseHeadersToParse, "x-elastic-product");
216-
217- // // Send request
218-
219- // var (resolvedUrl, _, resolvedRouteValues, postData) = PrepareRequest<TRequest, TRequestParameters>(request, forceConfiguration);
220- // var openTelemetryData = PrepareOpenTelemetryData<TRequest, TRequestParameters>(request, resolvedRouteValues);
221-
222- // TResponse response;
223-
224- // if (isAsync)
225- // {
226- // response = await _transport
227- // .RequestAsync<TResponse>(request.HttpMethod, resolvedUrl, postData, request.RequestParameters, in openTelemetryData, cancellationToken)
228- // .ConfigureAwait(false);
229- // }
230- // else
231- // {
232- // response = _transport
233- // .Request<TResponse>(request.HttpMethod, resolvedUrl, postData, request.RequestParameters, in openTelemetryData);
234- // }
235-
236- // // Evaluate product check result
237-
238- // var hasSuccessStatusCode = response.ApiCallDetails.HttpStatusCode is >= 200 and <= 299;
239- // if (hasSuccessStatusCode)
240- // {
241- // var productCheckSucceeded = response.ApiCallDetails.TryGetHeader("x-elastic-product", out var values) &&
242- // values.FirstOrDefault(x => x.Equals("Elasticsearch", StringComparison.Ordinal)) is not null;
243-
244- // _productCheckStatus = productCheckSucceeded
245- // ? (int)ProductCheckStatus.Succeeded
246- // : (int)ProductCheckStatus.Failed;
247-
248- // if (_productCheckStatus == (int)ProductCheckStatus.Failed)
249- // throw new UnsupportedProductException(UnsupportedProductException.InvalidProductError);
250- // }
251-
252- // if (request.RequestParameters.RequestConfiguration is null)
253- // return response;
254-
255- // // Reset request configuration
256-
257- // if (!hadRequestConfig)
258- // request.RequestParameters.RequestConfiguration = null;
259- // else if (originalHeaders is { Count: > 0 })
260- // request.RequestParameters.RequestConfiguration.ResponseHeadersToParse = originalHeaders.Value;
261-
262- // if (!hasSuccessStatusCode)
263- // {
264- // // The product check is unreliable for non success status codes.
265- // // We have to re-try on the next request.
266- // _productCheckStatus = (int)ProductCheckStatus.NotChecked;
267- // }
268-
269- // return response;
270- //}
180+ async ValueTask < TResponse > SendRequestWithProductCheck ( )
181+ {
182+ try
183+ {
184+ return await SendRequestWithProductCheckCore ( ) . ConfigureAwait ( false ) ;
185+ }
186+ catch
187+ {
188+ // Re-try product check on next request.
189+
190+ // 32-bit read/write operations are atomic and due to the initial memory barrier, we can be sure that
191+ // no other thread executes the product check at the same time. Locked access is not required here.
192+ if ( _productCheckStatus is ( int ) ProductCheckStatus . InProgress )
193+ _productCheckStatus = ( int ) ProductCheckStatus . NotChecked ;
194+
195+ throw ;
196+ }
197+ }
198+
199+ async ValueTask < TResponse > SendRequestWithProductCheckCore ( )
200+ {
201+ // Attach product check header
202+
203+ // TODO: The copy constructor should accept null values
204+ var requestConfig = ( request . RequestConfig is null )
205+ ? new RequestConfiguration ( )
206+ {
207+ ResponseHeadersToParse = new HeadersList ( "x-elastic-product" )
208+ }
209+ : new RequestConfiguration ( request . RequestConfig )
210+ {
211+ ResponseHeadersToParse = ( request . RequestConfig . ResponseHeadersToParse is { Count : > 0 } )
212+ ? new HeadersList ( request . RequestConfig . ResponseHeadersToParse , "x-elastic-product" )
213+ : new HeadersList ( "x-elastic-product" )
214+ } ;
215+
216+ // Send request
217+
218+ var ( resolvedUrl , _, resolvedRouteValues , postData ) = PrepareRequest < TRequest , TRequestParameters > ( request ) ;
219+ var openTelemetryData = PrepareOpenTelemetryData < TRequest , TRequestParameters > ( request , resolvedRouteValues ) ;
220+
221+ TResponse response ;
222+
223+ if ( isAsync )
224+ {
225+ response = await _transport
226+ . RequestAsync < TResponse > ( new EndpointPath ( request . HttpMethod , resolvedUrl ) , postData , in openTelemetryData , requestConfig , cancellationToken )
227+ . ConfigureAwait ( false ) ;
228+ }
229+ else
230+ {
231+ response = _transport
232+ . Request < TResponse > ( new EndpointPath ( request . HttpMethod , resolvedUrl ) , postData , in openTelemetryData , requestConfig ) ;
233+ }
234+
235+ // Evaluate product check result
236+
237+ var hasSuccessStatusCode = response . ApiCallDetails . HttpStatusCode is >= 200 and <= 299 ;
238+ if ( ! hasSuccessStatusCode )
239+ {
240+ // The product check is unreliable for non success status codes.
241+ // We have to re-try on the next request.
242+ _productCheckStatus = ( int ) ProductCheckStatus . NotChecked ;
243+
244+ return response ;
245+ }
246+
247+ var productCheckSucceeded = response . ApiCallDetails . TryGetHeader ( "x-elastic-product" , out var values ) &&
248+ values . FirstOrDefault ( x => x . Equals ( "Elasticsearch" , StringComparison . Ordinal ) ) is not null ;
249+
250+ _productCheckStatus = productCheckSucceeded
251+ ? ( int ) ProductCheckStatus . Succeeded
252+ : ( int ) ProductCheckStatus . Failed ;
253+
254+ if ( _productCheckStatus == ( int ) ProductCheckStatus . Failed )
255+ throw new UnsupportedProductException ( UnsupportedProductException . InvalidProductError ) ;
256+
257+ return response ;
258+ }
271259 }
272260
273261 private static OpenTelemetryData PrepareOpenTelemetryData < TRequest , TRequestParameters > ( TRequest request , Dictionary < string , string > resolvedRouteValues )
0 commit comments