예제 #1
0
        /* 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()
                       );
            }
        }
예제 #2
0
        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));
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
        private ElasticsearchResponse <T> CoordinateRequest <T>(TransportRequestState <T> requestState, int maxRetries, int retried, ref bool aliveResponse)
        {
            var pingRetryRequest = this.SelectNextNode(requestState);

            if (pingRetryRequest != null)
            {
                return(pingRetryRequest);
            }

            var streamResponse = this.DoElasticsearchCall(requestState);

            aliveResponse = streamResponse.SuccessOrKnownError;

            if (!this.DoneProcessing(streamResponse, requestState, maxRetries, retried))
            {
                return(null);
            }

            ElasticsearchServerError error = null;
            var typedResponse = this.ReturnStreamOrVoidResponse(requestState, streamResponse)
                                ?? this.ReturnTypedResponse(requestState, streamResponse, out error);

            this.OptionallyCloseResponseStreamAndSetSuccess(requestState, error, typedResponse, streamResponse);
            if (error != null && this._settings.ThrowOnElasticsearchServerExceptions)
            {
                throw new ElasticsearchServerException(error);
            }
            return(typedResponse);
        }
        protected void ThrowMaxRetryExceptionWhenNeeded <T>(TransportRequestState <T> requestState, int maxRetries)
        {
            bool tookToLong = _delegator.TookTooLongToRetry(requestState);

            //not out of date and we havent depleted our retries, get the hell out of here
            if (!tookToLong && requestState.Retried < maxRetries)
            {
                return;
            }

            List <Exception> innerExceptions = requestState.SeenExceptions.Where(e => e != null).ToList();
            Exception        innerException  = !innerExceptions.HasAny()
                ? null
                : (innerExceptions.Count() == 1)
                    ? innerExceptions.First()
                    : new AggregateException(requestState.SeenExceptions);

            //When we are not using pooling we forcefully rethrow the exception
            //and never wrap it in a maxretry exception
            if (!requestState.UsingPooling && innerException != null)
            {
                throw innerException;
            }

            string exceptionMessage = tookToLong
                ? CreateTookTooLongExceptionMessage(requestState, innerException)
                : CreateMaxRetryExceptionMessage(requestState, innerException);

            throw new MaxRetryException(exceptionMessage, innerException);
        }
예제 #6
0
        private OrientdbResponse <Stream> CallInToConnection <T>(TransportRequestState <T> requestState)
        {
            Uri uri = requestState.CreatePathOnCurrentNode();

            byte[] postData = requestState.PostData;
            IRequestConfiguration requestConfiguration = requestState.RequestConfiguration;

            switch (requestState.Method.ToLowerInvariant())
            {
            case "post":
                return(_connection.PostSync(uri, postData, requestConfiguration));

            case "put":
                return(_connection.PutSync(uri, postData, requestConfiguration));

            case "head":
                return(_connection.HeadSync(uri, requestConfiguration));

            case "get":
                return(_connection.GetSync(uri, requestConfiguration));

            case "delete":
                return(postData == null || postData.Length == 0
                        ? _connection.DeleteSync(uri, requestConfiguration)
                        : _connection.DeleteSync(uri, postData, requestConfiguration));
            }
            throw new Exception("Unknown HTTP method " + requestState.Method);
        }
예제 #7
0
        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);
        }
예제 #8
0
        private OrientdbResponse <T> CoordinateRequest <T>(TransportRequestState <T> requestState, int maxRetries,
                                                           int retried, ref bool aliveResponse)
        {
            OrientdbResponse <T> pingRetryRequest = SelectNextNode(requestState);

            if (pingRetryRequest != null)
            {
                return(pingRetryRequest);
            }

            OrientdbResponse <Stream> streamResponse = DoOrientdbCall(requestState);

            aliveResponse = streamResponse.SuccessOrKnownError;

            if (!DoneProcessing(streamResponse, requestState, maxRetries, retried))
            {
                return(null);
            }

            OrientdbServerError  error         = null;
            OrientdbResponse <T> typedResponse = ReturnStreamOrVoidResponse(requestState, streamResponse)
                                                 ?? ReturnTypedResponse(requestState, streamResponse, out error);

            OptionallyCloseResponseStreamAndSetSuccess(requestState, error, typedResponse, streamResponse);
            if (error != null && _settings.ThrowOnOrientdbServerExceptions)
            {
                throw new OrientdbServerException(error);
            }
            return(typedResponse);
        }
예제 #9
0
        IList <Uri> ITransportDelegator.Sniff(ITransportRequestState ownerState = null)
        {
            int pingTimeout      = Settings.PingTimeout.GetValueOrDefault(DefaultPingTimeout);
            var requestOverrides = new RequestConfiguration
            {
                ConnectTimeout = pingTimeout,
                RequestTimeout = pingTimeout,
                DisableSniff   = true //sniff call should never recurse
            };

            var requestParameters = new RequestParameters {
                RequestConfiguration = requestOverrides
            };

            try
            {
                string path = "_nodes/_all/clear?timeout=" + pingTimeout;
                OrientdbResponse <Stream> response;
                using (var requestState = new TransportRequestState <Stream>(Settings, requestParameters, "GET", path))
                {
                    response = _requestHandler.Request(requestState);

                    //inform the owing request state of the requests the sniffs did.
                    if (requestState.RequestMetrics != null && ownerState != null)
                    {
                        foreach (
                            RequestMetrics r in
                            requestState.RequestMetrics.Where(p => p.RequestType == RequestType.OrientdbCall))
                        {
                            r.RequestType = RequestType.Sniff;
                        }


                        if (ownerState.RequestMetrics == null)
                        {
                            ownerState.RequestMetrics = new List <RequestMetrics>();
                        }
                        ownerState.RequestMetrics.AddRange(requestState.RequestMetrics);
                    }
                    if (response.HttpStatusCode.HasValue && response.HttpStatusCode == (int)HttpStatusCode.Unauthorized)
                    {
                        throw new OrientdbAuthenticationException(response);
                    }
                    if (response.Response == null)
                    {
                        return(null);
                    }

                    using (response.Response)
                    {
                        return(Sniffer.FromStream(response, response.Response, Serializer));
                    }
                }
            }
            catch (MaxRetryException e)
            {
                throw new MaxRetryException(new SniffException(e));
            }
        }
예제 #10
0
 public Task <OrientdbResponse <T> > DoRequestAsync <T>(string method, string path, object data = null,
                                                        IRequestParameters requestParameters    = null)
 {
     using (var requestState = new TransportRequestState <T>(Settings, requestParameters, method, path))
     {
         return(_requestHandlerAsync.RequestAsync(requestState, data));
     }
 }
        protected string CreateMaxRetryExceptionMessage <T>(TransportRequestState <T> requestState, Exception e)
        {
            string innerException   = CreateInnerExceptionMessage(requestState, e);
            string exceptionMessage = MaxRetryExceptionMessage
                                      .F(requestState.Method, requestState.Path, requestState.Retried, innerException);

            return(exceptionMessage);
        }
예제 #12
0
        private Task <ElasticsearchResponse <T> > FinishOrRetryRequestAsync <T>(TransportRequestState <T> requestState)
        {
            var rq = requestState.InitiateRequest(RequestType.ElasticsearchCall);

            return(CallIntoConnectionAsync(requestState)
                   .ContinueWith(t => HandleStreamResponse(t, rq, requestState))
                   .Unwrap());
        }
        protected string CreateTookTooLongExceptionMessage <T>(TransportRequestState <T> requestState, Exception e)
        {
            string   innerException   = CreateInnerExceptionMessage(requestState, e);
            TimeSpan timeout          = _settings.MaxRetryTimeout.GetValueOrDefault(TimeSpan.FromMilliseconds(_settings.Timeout));
            string   exceptionMessage = TookTooLongExceptionMessage
                                        .F(requestState.Method, requestState.Path, requestState.Retried, innerException, timeout);

            return(exceptionMessage);
        }
예제 #14
0
        private ElasticsearchResponse <T> DoRequest <T>(TransportRequestState <T> requestState)
        {
            var sniffAuthResponse = this.TrySniffOnStaleClusterState(requestState);

            if (sniffAuthResponse != null)
            {
                return(sniffAuthResponse);
            }

            bool aliveResponse = false;
            bool seenError     = false;
            int  retried       = requestState.Retried;
            int  maxRetries    = this._delegator.GetMaximumRetries(requestState.RequestConfiguration);

            try
            {
                var response = this.CoordinateRequest(requestState, maxRetries, retried, ref aliveResponse);
                if (response != null)
                {
                    return(response);
                }
            }
            catch (ElasticsearchAuthenticationException e)
            {
                return(this.HandleAuthenticationException(requestState, e));
            }
            catch (MaxRetryException)
            {
                //TODO ifdef ExceptionDispatchInfo.Capture(ex).Throw();
                throw;
            }
            catch (ElasticsearchServerException)
            {
                //TODO ifdef ExceptionDispatchInfo.Capture(ex).Throw();
                throw;
            }
            catch (Exception e)
            {
                requestState.SeenExceptions.Add(e);
                if (!requestState.UsingPooling || maxRetries == 0 && retried == 0)
                {
                    //TODO ifdef ExceptionDispatchInfo.Capture(ex).Throw();
                    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(this.RetryRequest(requestState));
        }
예제 #15
0
        public OrientdbResponse <T> Request <T>(TransportRequestState <T> requestState, object data = null)
        {
            byte[] postData = PostData(data);
            requestState.TickSerialization(postData);

            OrientdbResponse <T> response = DoRequest(requestState);

            requestState.SetResult(response);
            return(response);
        }
예제 #16
0
        protected void SetAuthenticationExceptionOnRequestState <T>(
            TransportRequestState <T> requestState,
            ElasticsearchAuthenticationException exception,
            TaskCompletionSource <ElasticsearchResponse <T> > tcs)
        {
            var result = this.HandleAuthenticationException(requestState, exception);

            tcs.SetResult(result);
            requestState.SetResult(result);
        }
예제 #17
0
        public ElasticsearchResponse <T> Request <T>(TransportRequestState <T> requestState, object data = null)
        {
            var postData = PostData(data);

            requestState.TickSerialization(postData);

            var response = this.DoRequest <T>(requestState);

            requestState.SetResult(response);
            return(response);
        }
 /// <summary>
 ///     Determines whether the stream response is our final stream response:
 ///     IF response is success or known error
 ///     OR maxRetries is 0 and retried is 0 (maxRetries could change in between retries to 0)
 ///     AND sniff on connection fault does not find more nodes (causing maxRetry to grow)
 ///     AND maxretries is no retried
 /// </summary>
 protected bool DoneProcessing <T>(
     OrientdbResponse <Stream> streamResponse,
     TransportRequestState <T> requestState,
     int maxRetries,
     int retried)
 {
     return((streamResponse != null && streamResponse.SuccessOrKnownError) ||
            (maxRetries == 0 &&
             retried == 0 &&
             !_delegator.SniffOnFaultDiscoveredMoreNodes(requestState, retried, streamResponse)
            ));
 }
예제 #19
0
        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));
            }
        }
예제 #20
0
 /// <summary>
 /// Determines whether the stream response is our final stream response:
 /// IF response is success or known error
 /// OR maxRetries is 0 and retried is 0 (maxRetries could change in between retries to 0)
 /// AND sniff on connection fault does not find more nodes (causing maxRetry to grow)
 /// AND maxretries is no retried
 /// </summary>
 protected bool DoneProcessing <T>(
     ElasticsearchResponse <Stream> streamResponse,
     TransportRequestState <T> requestState,
     int maxRetries,
     int retried)
 {
     return(streamResponse.SuccessOrKnownError ||
            (maxRetries == 0 &&
             retried == 0 &&
             !this._delegator.SniffOnFaultDiscoveredMoreNodes(requestState, retried, streamResponse)
            ));
 }
예제 #21
0
        private Task <ElasticsearchResponse <T> > RetryRequestAsync <T>(TransportRequestState <T> requestState)
        {
            var maxRetries = this._delegator.GetMaximumRetries(requestState.RequestConfiguration);

            this._connectionPool.MarkDead(requestState.CurrentNode, this._settings.DeadTimeout, this._settings.MaxDeadTimeout);

            this._delegator.SniffOnConnectionFailure(requestState);

            this.ThrowMaxRetryExceptionWhenNeeded(requestState, maxRetries);

            return(this.DoRequestAsync <T>(requestState));
        }
예제 #22
0
        private ElasticsearchResponse <T> RetryRequest <T>(TransportRequestState <T> requestState)
        {
            var maxRetries = this.GetMaximumRetries(requestState.RequestConfiguration);

            this._connectionPool.MarkDead(requestState.CurrentNode, this.ConfigurationValues.DeadTimeout, this.ConfigurationValues.MaxDeadTimeout);

            SniffOnConnectionFailure(requestState);

            ThrowMaxRetryExceptionWhenNeeded(requestState, maxRetries);

            return(this.DoRequest <T>(requestState));
        }
예제 #23
0
        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();
                    if (maxRetries == 0 && retried == 0)
                    {
                        throw t.Exception;
                    }
                    requestState.SeenExceptions.Add(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());
        }
예제 #24
0
        public Task <ElasticsearchResponse <T> > RequestAsync <T>(TransportRequestState <T> requestState, object data = null)
        {
            // Serialize request and inform requestState so it can keep track of serialization times
            var bytes = PostData(data);

            requestState.TickSerialization(bytes);

            return(this.DoRequestAsync <T>(requestState)
                   // When the request returns again inform the request state so it can do its bookkeeping
                   .ContinueWith(t => this.SetResultOnRequestState(t, requestState))
                   .Unwrap());
        }
예제 #25
0
        private ElasticsearchResponse <Stream> DoElasticsearchCall <T>(TransportRequestState <T> requestState)
        {
            // Do the actual request by calling into IConnection
            // We wrap it in a IRequestTimings to audit the request
            ElasticsearchResponse <Stream> streamResponse;

            using (var requestAudit = requestState.InitiateRequest(RequestType.ElasticsearchCall))
            {
                streamResponse = this.CallInToConnection(requestState);
                requestAudit.Finish(streamResponse.Success, streamResponse.HttpStatusCode);
            }
            return(streamResponse);
        }
예제 #26
0
        private OrientdbResponse <Stream> DoOrientdbCall <T>(TransportRequestState <T> requestState)
        {
            // Do the actual request by calling into IConnection
            // We wrap it in a IRequestTimings to audit the request
            OrientdbResponse <Stream> streamResponse;

            using (IRequestTimings requestAudit = requestState.InitiateRequest(RequestType.OrientdbCall))
            {
                streamResponse = CallInToConnection(requestState);
                requestAudit.Finish(streamResponse.Success, streamResponse.HttpStatusCode);
            }
            return(streamResponse);
        }
 /// <summary>
 ///     Sniffs when the cluster state is stale, when sniffing returns a 401 return a response for T to return directly
 /// </summary>
 protected OrientdbResponse <T> TrySniffOnStaleClusterState <T>(TransportRequestState <T> requestState)
 {
     try
     {
         //If connectionSettings is configured to sniff periodically, sniff when stale.
         _delegator.SniffOnStaleClusterState(requestState);
         return(null);
     }
     catch (OrientdbAuthenticationException e)
     {
         return(HandleAuthenticationException(requestState, e));
     }
 }
예제 #28
0
        /* 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);
            }
        }
        protected ElasticsearchResponse <T> HandleAuthenticationException <T>(TransportRequestState <T> requestState, ElasticsearchAuthException exception)
        {
            if (requestState.ClientSettings.ThrowOnElasticsearchServerExceptions)
            {
                throw exception.ToElasticsearchServerException();
            }

            var response = ElasticsearchResponse.CloneFrom <T>(exception.Response, default(T));

            response.Request       = requestState.PostData;
            response.RequestUrl    = requestState.Path;
            response.RequestMethod = requestState.Method;
            return(response);
        }
예제 #30
0
        private ElasticsearchResponse <T> SelectNextNode <T>(TransportRequestState <T> requestState)
        {
            // Select the next node to hit and signal whether the selected node needs a ping
            var nodeRequiresPinging = this._delegator.SelectNextNode(requestState);

            if (!nodeRequiresPinging)
            {
                return(null);
            }

            var pingSuccess = this._delegator.Ping(requestState);

            // If ping is not successful retry request on the next node the connection pool selects
            return(!pingSuccess?RetryRequest <T>(requestState) : null);
        }