private ElasticsearchResponse <T> DoRequest <T>(TransportRequestState <T> requestState, int retried = 0) { if (!SniffingDisabled(requestState.RequestConfiguration)) { SniffIfInformationIsTooOld(retried); } var aliveResponse = false; int initialSeed; bool shouldPingHint; var baseUri = GetNextBaseUri(requestState, out initialSeed, out shouldPingHint); requestState.Seed = initialSeed; var uri = CreateUriToPath(baseUri, requestState.Path); bool seenError = false; try { if (shouldPingHint && !this.ConfigurationValues.DisablePings && (requestState.RequestConfiguration == null || !requestState.RequestConfiguration.PingDisabled.GetValueOrDefault(false)) ) { this.Ping(baseUri); } var streamResponse = _doRequest(requestState.Method, uri, requestState.PostData, requestState.RequestConfiguration); if (streamResponse != null && streamResponse.SuccessOrKnownError) { var error = ThrowOrGetErrorFromStreamResponse(requestState, streamResponse); var typedResponse = this.StreamToTypedResponse <T>(streamResponse, requestState.DeserializationState); typedResponse.NumberOfRetries = retried; this.SetErrorDiagnosticsAndPatchSuccess(requestState, error, typedResponse, streamResponse); aliveResponse = typedResponse.SuccessOrKnownError; return(typedResponse); } } catch (Exception e) { var maxRetries = this.GetMaximumRetries(requestState.RequestConfiguration); if (maxRetries == 0 && retried == 0) { throw; } seenError = true; return(RetryRequest <T>(requestState, baseUri, retried, e)); } finally { //make sure we always call markalive on the uri if the connection was succesful if (!seenError && aliveResponse) { this._connectionPool.MarkAlive(baseUri); } } return(RetryRequest <T>(requestState, baseUri, retried)); }
public Task <ElasticsearchResponse <T> > DoRequestAsync <T>(string method, string path, object data = null, IRequestParameters requestParameters = null) { using (var requestState = new TransportRequestState <T>(this.Settings, requestParameters, method, path)) { return(this._requestHandlerAsync.RequestAsync(requestState, data)); } }
private ElasticsearchServerError ThrowOrGetErrorFromStreamResponse <T>(TransportRequestState <T> requestState, ElasticsearchResponse <Stream> streamResponse) { ElasticsearchServerError error = null; if ((!streamResponse.Success && requestState.RequestConfiguration == null) || (!streamResponse.Success && requestState.RequestConfiguration != null && requestState.RequestConfiguration.AllowedStatusCodes.All(i => i != streamResponse.HttpStatusCode))) { if (streamResponse.Response != null) { error = this.Serializer.Deserialize <ElasticsearchServerError>(streamResponse.Response); } else { error = new ElasticsearchServerError { Status = streamResponse.HttpStatusCode.GetValueOrDefault(-1) } }; if (this.Settings.ThrowOnElasticsearchServerExceptions) { throw new ElasticsearchServerException(error); } } return(error); }
/* ASYNC *** ********************************************/ public Task <ElasticsearchResponse <T> > DoRequestAsync <T>(string method, string path, object data = null, IRequestParameters requestParameters = null) { using (var requestState = new TransportRequestState <T>(this.Settings, requestParameters, method, path)) { var bytes = PostData(data); requestState.TickSerialization(bytes); return(this.DoRequestAsync <T>(requestState) .ContinueWith(t => { var tcs = new TaskCompletionSource <ElasticsearchResponse <T> >(); if (t.Exception != null) { tcs.SetException(t.Exception.Flatten()); requestState.SetResult(null); } else { tcs.SetResult(t.Result); requestState.SetResult(t.Result); } return tcs.Task; }).Unwrap() ); } }
private Task <ElasticsearchResponse <Stream> > CallIntoConnectionAsync <T>(TransportRequestState <T> requestState) { var uri = requestState.CreatePathOnCurrentNode(); var postData = requestState.PostData; var requestConfiguration = requestState.RequestConfiguration; var method = requestState.Method.ToLowerInvariant(); try { switch (method) { case "head": return(this.Connection.Head(uri, requestConfiguration)); case "get": return(this.Connection.Get(uri, requestConfiguration)); case "post": return(this.Connection.Post(uri, postData, requestConfiguration)); case "put": return(this.Connection.Put(uri, postData, requestConfiguration)); case "delete": return(postData == null || postData.Length == 0 ? this.Connection.Delete(uri, requestConfiguration) : this.Connection.Delete(uri, postData, requestConfiguration)); default: throw new Exception("Unknown HTTP method " + requestState.Method); } } catch (Exception e) { var tcs = new TaskCompletionSource <ElasticsearchResponse <Stream> >(); tcs.SetException(e); return(tcs.Task); } }
private Task <ElasticsearchResponse <T> > DoRequestAsync <T>(TransportRequestState <T> requestState) { this.SniffIfInformationIsTooOld(requestState); var uriRequiresPing = this.SelectNextNode(requestState); if (uriRequiresPing) { return(this.PingAsync(requestState) .ContinueWith(t => { if (t.IsFaulted) { requestState.SeenExceptions.Add(t.Exception.InnerException); return this.RetryRequestAsync(requestState); } if (t.IsCompleted) { return this.FinishOrRetryRequestAsync(requestState); } return null; }).Unwrap()); } return(FinishOrRetryRequestAsync(requestState)); }
private Task <ElasticsearchResponse <T> > DoRequestAsync <T>(TransportRequestState <T> requestState, int retried = 0) { SniffIfInformationIsTooOld(retried); int initialSeed; bool shouldPingHint; var baseUri = this.GetNextBaseUri(requestState, out initialSeed, out shouldPingHint); requestState.Seed = initialSeed; var uri = CreateUriToPath(baseUri, requestState.Path); if (shouldPingHint && !this._configurationValues.DisablePings) { return(this.PingAsync(baseUri) .ContinueWith(t => { if (t.IsCompleted) { return this._doRequestAsyncOrRetry(requestState, retried, uri, baseUri); } return this.RetryRequestAsync(requestState, baseUri, retried, t.Exception); }).Unwrap()); } return(_doRequestAsyncOrRetry(requestState, retried, uri, baseUri)); }
/* ASYNC *** */ public Task <ElasticsearchResponse <T> > DoRequestAsync <T>(string method, string path, object data = null, IRequestParameters requestParameters = null) { using (var tracer = new ElasticsearchResponseTracer <T>(this.Settings.TraceEnabled)) { var postData = PostData(data); var requestState = new TransportRequestState <T>(tracer, method, path, postData, requestParameters); return(this.DoRequestAsync <T>(requestState) .ContinueWith(t => { var tcs = new TaskCompletionSource <ElasticsearchResponse <T> >(); if (t.Exception != null) { tcs.SetException(t.Exception.Flatten()); } else { tcs.SetResult(t.Result); } requestState.Tracer.SetResult(t.Result); return tcs.Task; }).Unwrap()); } }
private Task <ElasticsearchResponse <T> > _doRequestAsyncOrRetry <T>( TransportRequestState <T> requestState, int retried, Uri uri, Uri baseUri) { return (_doRequestAsync(requestState.Method, uri, requestState.PostData, requestState.RequestConfiguration).ContinueWith(t => { if (t.IsCanceled) { return null; } if (t.IsFaulted) { return this.RetryRequestAsync <T>(requestState, baseUri, retried, t.Exception); } if (t.Result.SuccessOrKnownError) { return this.StreamToTypedResponseAsync <T>(t.Result, requestState.DeserializationState) .ContinueWith(tt => { tt.Result.NumberOfRetries = retried; return tt; }).Unwrap(); } return this.RetryRequestAsync <T>(requestState, baseUri, retried); }).Unwrap()); }
public IList <Uri> Sniff() { var pingTimeout = this.Settings.PingTimeout.GetValueOrDefault(50); var requestOverrides = new RequestConfiguration() .ConnectTimeout(pingTimeout) .RequestTimeout(pingTimeout) .DisableSniffing(); var requestParameters = new FluentRequestParameters() .RequestConfiguration(r => requestOverrides); var path = "_nodes/_all/clear?timeout=" + pingTimeout; using (var tracer = new ElasticsearchResponseTracer <Stream>(this.Settings.TraceEnabled)) { var requestState = new TransportRequestState <Stream>(tracer, "GET", path, requestParameters: requestParameters); var response = this.DoRequest(requestState); if (response.Response == null) { return(null); } using (response.Response) { return(Sniffer.FromStream(response, response.Response, this.Serializer)); } } }
private Task <ElasticsearchResponse <T> > _doRequestAsyncOrRetry <T>( TransportRequestState <T> requestState, int retried, Uri uri, Uri baseUri) { return (_doRequestAsync(requestState.Method, uri, requestState.PostData, requestState.RequestConfiguration).ContinueWith(t => { if (t.IsCanceled) { return null; } if (t.IsFaulted) { return this.RetryRequestAsync <T>(requestState, baseUri, retried, t.Exception); } if (t.Result.SuccessOrKnownError) { var error = ThrowOrGetErrorFromStreamResponse(requestState, t.Result); return this.StreamToTypedResponseAsync <T>(t.Result, requestState.DeserializationState) .ContinueWith(tt => { tt.Result.NumberOfRetries = retried; this.SetErrorDiagnosticsAndPatchSuccess(requestState, error, tt.Result, t.Result); if (tt.Result.SuccessOrKnownError) { this._connectionPool.MarkAlive(baseUri); } return tt; }).Unwrap(); } return this.RetryRequestAsync <T>(requestState, baseUri, retried); }).Unwrap()); }
private static string CreateMaxRetryExceptionMessage <T>(TransportRequestState <T> requestState, Exception e) { string innerException = null; if (e != null) { var aggregate = e as AggregateException; if (aggregate != null) { aggregate = aggregate.Flatten(); var innerExceptions = aggregate.InnerExceptions .Select(ae => MaxRetryInnerMessage.F(ae.GetType().Name, ae.Message, ae.StackTrace)) .ToList(); innerException = "\r\n" + string.Join("\r\n", innerExceptions); } else { innerException = "\r\n" + MaxRetryInnerMessage.F(e.GetType().Name, e.Message, e.StackTrace); } } var exceptionMessage = MaxRetryExceptionMessage .F(requestState.Method, requestState.Path, requestState.Retried, innerException); return(exceptionMessage); }
private Task <ElasticsearchResponse <T> > FinishOrRetryRequestAsync <T>(TransportRequestState <T> requestState) { var rq = requestState.InitiateRequest(RequestType.ElasticsearchCall); return(CallIntoConnectionAsync(requestState) .ContinueWith(t => { var retried = requestState.Retried; if (t.IsCanceled) { return null; } var maxRetries = this.GetMaximumRetries(requestState.RequestConfiguration); if (t.IsFaulted) { rq.Dispose(); requestState.SeenExceptions.Add(t.Exception); if (!requestState.UsingPooling || maxRetries == 0 && retried == 0) { throw t.Exception; } return this.RetryRequestAsync <T>(requestState); } if (t.Result.SuccessOrKnownError || ( maxRetries == 0 && retried == 0 && !SniffOnFaultDiscoveredMoreNodes(requestState, retried, t.Result)) ) { rq.Finish(t.Result.Success, t.Result.HttpStatusCode); rq.Dispose(); var error = ThrowOrGetErrorFromStreamResponse(requestState, t.Result); return this.StreamToTypedResponseAsync <T>(t.Result, requestState) .ContinueWith(tt => { this.SetErrorDiagnosticsAndPatchSuccess(requestState, error, tt.Result, t.Result); if (tt.Result.SuccessOrKnownError) { this._connectionPool.MarkAlive(requestState.CurrentNode); } return tt; }).Unwrap(); } if (t.Result != null) { rq.Finish(t.Result.Success, t.Result.HttpStatusCode); } rq.Dispose(); return this.RetryRequestAsync <T>(requestState); }).Unwrap()); }
private IList <Uri> Sniff(ITransportRequestState ownerState = null) { var pingTimeout = this.Settings.PingTimeout.GetValueOrDefault(50); var requestOverrides = new RequestConfiguration { ConnectTimeout = pingTimeout, RequestTimeout = pingTimeout, DisableSniff = true //sniff call should never recurse }; var requestParameters = new RequestParameters { RequestConfiguration = requestOverrides }; try { var path = "_nodes/_all/clear?timeout=" + pingTimeout; ElasticsearchResponse <Stream> response; using (var requestState = new TransportRequestState <Stream>(this.Settings, requestParameters, "GET", path)) { response = this.DoRequest(requestState); //inform the owing request state of the requests the sniffs did. if (requestState.RequestMetrics != null && ownerState != null) { foreach (var r in requestState.RequestMetrics.Where(p => p.RequestType == RequestType.ElasticsearchCall)) { r.RequestType = RequestType.Sniff; } if (ownerState.RequestMetrics == null) { ownerState.RequestMetrics = new List <RequestMetrics>(); } ownerState.RequestMetrics.AddRange(requestState.RequestMetrics); } if (response.Response == null) { return(null); } using (response.Response) { return(Sniffer.FromStream(response, response.Response, this.Serializer)); } } } catch (MaxRetryException e) { throw new MaxRetryException(new SniffException(e)); } }
private Task <ElasticsearchResponse <T> > RetryRequestAsync <T>(TransportRequestState <T> requestState) { var maxRetries = this.GetMaximumRetries(requestState.RequestConfiguration); this._connectionPool.MarkDead(requestState.CurrentNode, this.ConfigurationValues.DeadTimeout, this.ConfigurationValues.MaxDeadTimeout); this.SniffOnConnectionFailure(requestState); ThrowMaxRetryExceptionWhenNeeded(requestState, maxRetries); return(this.DoRequestAsync <T>(requestState)); }
private Uri GetNextBaseUri <T>(TransportRequestState <T> requestState, out int initialSeed, out bool shouldPingHint) { if (requestState.RequestConfiguration != null && requestState.RequestConfiguration.ForcedNode != null) { initialSeed = 0; shouldPingHint = false; return(requestState.RequestConfiguration.ForcedNode); } var baseUri = this._connectionPool.GetNext(requestState.Seed, out initialSeed, out shouldPingHint); return(baseUri); }
/* SYNC *** */ public ElasticsearchResponse <T> DoRequest <T>(string method, string path, object data = null, IRequestParameters requestParameters = null) { using (var tracer = new ElasticsearchResponseTracer <T>(this.Settings.TraceEnabled)) { var postData = PostData(data); var requestState = new TransportRequestState <T>(tracer, method, path, postData, requestParameters); var result = this.DoRequest <T>(requestState); tracer.SetResult(result); return(result); } }
/* SYNC *** ********************************************/ public ElasticsearchResponse <T> DoRequest <T>(string method, string path, object data = null, IRequestParameters requestParameters = null) { using (var requestState = new TransportRequestState <T>(this.Settings, requestParameters, method, path)) { var bytes = PostData(data); requestState.TickSerialization(bytes); var result = this.DoRequest <T>(requestState); requestState.SetResult(result); return(result); } }
private void SetErrorDiagnosticsAndPatchSuccess <T>(TransportRequestState <T> requestState, ElasticsearchServerError error, ElasticsearchResponse <T> typedResponse, ElasticsearchResponse <Stream> streamResponse) { if (error != null) { typedResponse.Success = false; typedResponse.OriginalException = new ElasticsearchServerException(error); } if (!typedResponse.Success && requestState.RequestConfiguration != null && requestState.RequestConfiguration.AllowedStatusCodes.HasAny(i => i == streamResponse.HttpStatusCode)) { typedResponse.Success = true; } }
private static void ThrowMaxRetryExceptionWhenNeeded <T>(TransportRequestState <T> requestState, int maxRetries) { if (requestState.Retried < maxRetries) { return; } var innerExceptions = requestState.SeenExceptions.Where(e => e != null).ToList(); var innerException = !innerExceptions.HasAny() ? null : (innerExceptions.Count() == 1) ? innerExceptions.First() : new AggregateException(requestState.SeenExceptions); var exceptionMessage = CreateMaxRetryExceptionMessage(requestState, innerException); throw new MaxRetryException(exceptionMessage, innerException); }
/* SYNC *** */ public ElasticsearchResponse <T> DoRequest <T>(string method, string path, object data = null, IRequestParameters requestParameters = null) { using (var tracer = new ElasticsearchResponseTracer <T>(this.Settings.TraceEnabled)) { var postData = PostData(data); var requestState = new TransportRequestState <T>(tracer, method, path, postData, requestParameters); var result = this.DoRequest <T>(requestState); var objectNeedsResponseRef = result.Response as IResponseWithRequestInformation; if (objectNeedsResponseRef != null) { objectNeedsResponseRef.RequestInformation = result; } tracer.SetResult(result); return(result); } }
private Task <ElasticsearchResponse <T> > RetryRequestAsync <T>(TransportRequestState <T> requestState, Uri baseUri, int retried, Exception e = null) { var maxRetries = this.GetMaximumRetries(requestState.RequestConfiguration); var exceptionMessage = MaxRetryExceptionMessage.F(requestState.Method, requestState.Path, retried); this._connectionPool.MarkDead(baseUri, this._configurationValues.DeadTimeout, this._configurationValues.MaxDeadTimeout); if (this._configurationValues.SniffsOnConnectionFault && retried == 0) { this.SniffClusterState(); } if (retried < maxRetries) { return(this.DoRequestAsync <T>(requestState, ++retried)); } throw new MaxRetryException(exceptionMessage, e); }
private ElasticsearchResponse <T> RetryRequest <T>(TransportRequestState <T> requestState, Uri baseUri, int retried, Exception e = null) { var maxRetries = this.GetMaximumRetries(requestState.RequestConfiguration); var exceptionMessage = MaxRetryExceptionMessage.F(requestState.Method, requestState.Path.IsNullOrEmpty() ? "/" : "", retried); this._connectionPool.MarkDead(baseUri, this._configurationValues.DeadTimeout, this._configurationValues.MaxDeadTimeout); if (!SniffingDisabled(requestState.RequestConfiguration) && this._configurationValues.SniffsOnConnectionFault && retried == 0) { this.SniffClusterState(); } if (retried >= maxRetries) { throw new MaxRetryException(exceptionMessage, e); } return(this.DoRequest <T>(requestState, ++retried)); }
private ElasticsearchServerError ThrowOrGetErrorFromStreamResponse <T>( TransportRequestState <T> requestState, ElasticsearchResponse <Stream> streamResponse) { ElasticsearchServerError error = null; if ((!streamResponse.Success && requestState.RequestConfiguration == null) || (!streamResponse.Success && requestState.RequestConfiguration != null && requestState.RequestConfiguration.AllowedStatusCodes.All(i => i != streamResponse.HttpStatusCode))) { if (streamResponse.Response != null && !this.Settings.KeepRawResponse) { var e = this.Serializer.Deserialize <OneToOneServerException>(streamResponse.Response); error = ElasticsearchServerError.Create(e); } else if (streamResponse.Response != null && this.Settings.KeepRawResponse) { var ms = new MemoryStream(); streamResponse.Response.CopyTo(ms); ms.Position = 0; streamResponse.ResponseRaw = ms.ToArray(); var e = this.Serializer.Deserialize <OneToOneServerException>(ms); error = ElasticsearchServerError.Create(e); ms.Position = 0; streamResponse.Response = ms; } else { error = new ElasticsearchServerError { Status = streamResponse.HttpStatusCode.GetValueOrDefault(-1) } }; if (this.Settings.ThrowOnElasticsearchServerExceptions) { throw new ElasticsearchServerException(error); } } return(error); }
private ElasticsearchResponse <Stream> CallInToConnection <T>(TransportRequestState <T> requestState) { var uri = requestState.CreatePathOnCurrentNode(); var postData = requestState.PostData; var requestConfiguration = requestState.RequestConfiguration; switch (requestState.Method.ToLowerInvariant()) { case "post": return(this.Connection.PostSync(uri, postData, requestConfiguration)); case "put": return(this.Connection.PutSync(uri, postData, requestConfiguration)); case "head": return(this.Connection.HeadSync(uri, requestConfiguration)); case "get": return(this.Connection.GetSync(uri, requestConfiguration)); case "delete": return(postData == null || postData.Length == 0 ? this.Connection.DeleteSync(uri, requestConfiguration) : this.Connection.DeleteSync(uri, postData, requestConfiguration)); } throw new Exception("Unknown HTTP method " + requestState.Method); }
private ElasticsearchResponse <T> DoRequest <T>(TransportRequestState <T> requestState) { var retried = requestState.Retried; this.SniffIfInformationIsTooOld(requestState); var aliveResponse = false; var nodeRequiresPinging = this.SelectNextNode(requestState); var seenError = false; var maxRetries = this.GetMaximumRetries(requestState.RequestConfiguration); try { if (nodeRequiresPinging) { var pingSuccess = this.Ping(requestState); if (!pingSuccess) { return(RetryRequest <T>(requestState)); } } ElasticsearchResponse <Stream> streamResponse; using (var rq = requestState.InitiateRequest(RequestType.ElasticsearchCall)) { streamResponse = this.CallInToConnection(requestState); rq.Finish(streamResponse.Success, streamResponse.HttpStatusCode); } if (streamResponse.SuccessOrKnownError || ( maxRetries == 0 && retried == 0 && !SniffOnFaultDiscoveredMoreNodes(requestState, retried, streamResponse)) ) { var error = ThrowOrGetErrorFromStreamResponse(requestState, streamResponse); var typedResponse = this.StreamToTypedResponse <T>(streamResponse, requestState); this.SetErrorDiagnosticsAndPatchSuccess(requestState, error, typedResponse, streamResponse); aliveResponse = typedResponse.SuccessOrKnownError; return(typedResponse); } } catch (MaxRetryException) { throw; } catch (ElasticsearchServerException) { throw; } catch (Exception e) { requestState.SeenExceptions.Add(e); if (!requestState.UsingPooling || maxRetries == 0 && retried == 0) { if (_throwMaxRetry) { new MaxRetryException(e); } else { throw; } } seenError = true; return(RetryRequest <T>(requestState)); } finally { //make sure we always call markalive on the uri if the connection was succesful if (!seenError && aliveResponse) { this._connectionPool.MarkAlive(requestState.CurrentNode); } } return(RetryRequest <T>(requestState)); }
/* STREAM HANDLING ********************************************/ private ElasticsearchServerError ThrowOrGetErrorFromStreamResponse <T>( TransportRequestState <T> requestState, ElasticsearchResponse <Stream> streamResponse) { if (((streamResponse.HttpStatusCode.HasValue && streamResponse.HttpStatusCode.Value <= 0) || !streamResponse.HttpStatusCode.HasValue) && streamResponse.OriginalException != null) { throw streamResponse.OriginalException; } if (IsValidResponse(requestState, streamResponse)) { return(null); } ElasticsearchServerError error = null; var type = typeof(T); if (typeof(Stream).IsAssignableFrom(typeof(T)) || typeof(T) == typeof(VoidResponse)) { return(null); } if (streamResponse.Response != null && !(this.Settings.KeepRawResponse || this.TypeOfResponseCopiesDirectly <T>())) { var e = this.Serializer.Deserialize <OneToOneServerException>(streamResponse.Response); error = ElasticsearchServerError.Create(e); } else if (streamResponse.Response != null) { var ms = new MemoryStream(); streamResponse.Response.CopyTo(ms); ms.Position = 0; streamResponse.ResponseRaw = this.Settings.KeepRawResponse ? ms.ToArray() : null; try { var e = this.Serializer.Deserialize <OneToOneServerException>(ms); error = ElasticsearchServerError.Create(e); } catch (Exception) { var raw = ms.ToArray().Utf8String(); } ms.Position = 0; streamResponse.Response.Close(); streamResponse.Response = ms; } else { error = new ElasticsearchServerError { Status = streamResponse.HttpStatusCode.GetValueOrDefault(-1) } }; if (this.Settings.ThrowOnElasticsearchServerExceptions) { throw new ElasticsearchServerException(error); } return(error); }