Ejemplo n.º 1
0
 public OperationMetadata(OperationMetadata operationMetadata)
 {
     Url         = operationMetadata.Url;
     Credentials = new OperationCredentials(operationMetadata.Credentials.ApiKey, operationMetadata.Credentials.Credentials);
 }
Ejemplo n.º 2
0
        public async Task <T> ExecuteWithReplicationAsync <T>(string method, string primaryUrl, OperationCredentials primaryCredentials, int currentRequest, int currentReadStripingBase, Func <OperationMetadata, Task <T> > operation)
        {
            var localReplicationDestinations = ReplicationDestinationsUrls; // thread safe copy
            var primaryOperation             = new OperationMetadata(primaryUrl, primaryCredentials);

            var shouldReadFromAllServers = conventions.FailoverBehavior.HasFlag(FailoverBehavior.ReadFromAllServers);
            var operationResult          = new AsyncOperationResult <T>();

            if (shouldReadFromAllServers && method == "GET")
            {
                var replicationIndex = currentReadStripingBase % (localReplicationDestinations.Count + 1);
                // if replicationIndex == destinations count, then we want to use the master
                // if replicationIndex < 0, then we were explicitly instructed to use the master
                if (replicationIndex < localReplicationDestinations.Count && replicationIndex >= 0)
                {
                    // if it is failing, ignore that, and move to the master or any of the replicas
                    if (ShouldExecuteUsing(localReplicationDestinations[replicationIndex], primaryOperation, currentRequest, method, false, error: null))
                    {
                        operationResult = await TryOperationAsync(operation, localReplicationDestinations[replicationIndex], primaryOperation, true).ConfigureAwait(false);

                        if (operationResult.Success)
                        {
                            return(operationResult.Result);
                        }
                    }
                }
            }

            if (ShouldExecuteUsing(primaryOperation, primaryOperation, currentRequest, method, true, error: null))
            {
                operationResult = await TryOperationAsync(operation, primaryOperation, null, !operationResult.WasTimeout && localReplicationDestinations.Count > 0)
                                  .ConfigureAwait(false);

                if (operationResult.Success)
                {
                    return(operationResult.Result);
                }

                IncrementFailureCount(primaryOperation.Url);
                if (!operationResult.WasTimeout && IsFirstFailure(primaryOperation.Url))
                {
                    operationResult = await TryOperationAsync(operation, primaryOperation, null, localReplicationDestinations.Count > 0).ConfigureAwait(false);

                    if (operationResult.Success)
                    {
                        return(operationResult.Result);
                    }
                    IncrementFailureCount(primaryOperation.Url);
                }
            }

            for (var i = 0; i < localReplicationDestinations.Count; i++)
            {
                var replicationDestination = localReplicationDestinations[i];
                if (ShouldExecuteUsing(replicationDestination, primaryOperation, currentRequest, method, false, operationResult.Error) == false)
                {
                    continue;
                }

                var hasMoreReplicationDestinations = localReplicationDestinations.Count > i + 1;
                operationResult = await TryOperationAsync(operation, replicationDestination, primaryOperation, !operationResult.WasTimeout && hasMoreReplicationDestinations).ConfigureAwait(false);

                if (operationResult.Success)
                {
                    return(operationResult.Result);
                }

                IncrementFailureCount(replicationDestination.Url);
                if (!operationResult.WasTimeout && IsFirstFailure(replicationDestination.Url))
                {
                    operationResult = await TryOperationAsync(operation, replicationDestination, primaryOperation, hasMoreReplicationDestinations).ConfigureAwait(false);

                    // tuple = await TryOperationAsync(operation, replicationDestination, primaryOperation, localReplicationDestinations.Count > i + 1).ConfigureAwait(false);
                    if (operationResult.Success)
                    {
                        return(operationResult.Result);
                    }
                    IncrementFailureCount(replicationDestination.Url);
                }
            }

            // this should not be thrown, but since I know the value of should...
            throw new InvalidOperationException(@"Attempted to connect to master and all replicas have failed, giving up.
There is a high probability of a network problem preventing access to all the replicas.
Failed to get in touch with any of the " + (1 + localReplicationDestinations.Count) + " Raven instances.");
        }
Ejemplo n.º 3
0
        internal static async Task <Stream> DownloadAsyncImpl(IHoldProfilingInformation self, HttpJsonRequestFactory requestFactory, FilesConvention conventions,
                                                              NameValueCollection operationsHeaders, string path, string filename, Reference <RavenJObject> metadataRef, long? @from, long?to, string baseUrl, OperationCredentials credentials)
        {
            var request = requestFactory.CreateHttpJsonRequest(new CreateHttpJsonRequestParams(self, baseUrl + path + Uri.EscapeDataString(filename), "GET", credentials, conventions)).AddOperationHeaders(operationsHeaders);

            if (@from != null)
            {
                if (to != null)
                {
                    request.AddRange(@from.Value, to.Value);
                }
                else
                {
                    request.AddRange(@from.Value);
                }
            }

            try
            {
                var response = await request.ExecuteRawResponseAsync().ConfigureAwait(false);

                if (response.StatusCode == HttpStatusCode.NotFound)
                {
                    throw new FileNotFoundException("The file requested does not exists on the file system.", baseUrl + path + filename);
                }

                await response.AssertNotFailingResponse().ConfigureAwait(false);

                if (metadataRef != null)
                {
                    metadataRef.Value = response.HeadersToObject();
                }

                return(new DisposableStream(await response.GetResponseStreamWithHttpDecompression().ConfigureAwait(false), request.Dispose));
            }
            catch (Exception e)
            {
                throw e.SimplifyException();
            }
        }
Ejemplo n.º 4
0
 public CreateHttpJsonRequestParams(IHoldProfilingInformation self, string url, HttpMethod method, OperationCredentials credentials, ConventionBase convention, IRequestTimeMetric requestTimeMetric = null, TimeSpan?timeout = null)
     : this(self, url, method, new RavenJObject(), credentials, convention, requestTimeMetric, timeout)
 {
 }
Ejemplo n.º 5
0
            /// <summary>
            /// Create new time series on the server.
            /// </summary>
            /// <param name="timeSeriesDocument">Settings for the time series. If null, default settings will be used, and the name specified in the client ctor will be used</param>
            /// <param name="shouldUpdateIfExists">Indicates if time series should be updated if they exist.</param>
            /// <param name="credentials">Credentials used for this operation.</param>
            /// <param name="token">Cancellation token used for this operation.</param>
            public async Task <TimeSeriesStore> CreateTimeSeriesAsync(TimeSeriesDocument timeSeriesDocument, bool shouldUpdateIfExists = false, OperationCredentials credentials = null, CancellationToken token = default(CancellationToken))
            {
                if (timeSeriesDocument == null)
                {
                    throw new ArgumentNullException("timeSeriesDocument");
                }

                parent.AssertInitialized();

                var timeSeriesName = timeSeriesDocument.Id.Replace(Constants.TimeSeries.Prefix, "");
                var requestUri     = parent.Url + "admin/ts/" + timeSeriesName;

                if (shouldUpdateIfExists)
                {
                    requestUri += "?update=true";
                }

                using (var request = parent.CreateHttpJsonRequest(requestUri, HttpMethods.Put))
                {
                    try
                    {
                        await request.WriteAsync(RavenJObject.FromObject(timeSeriesDocument)).WithCancellation(token).ConfigureAwait(false);
                    }
                    catch (ErrorResponseException e)
                    {
                        if (e.StatusCode == HttpStatusCode.Conflict)
                        {
                            throw new InvalidOperationException("Cannot create time series with the name '" + timeSeriesName + "' because it already exists. Use CreateOrUpdateTimeSeriesAsync in case you want to update an existing time series", e);
                        }

                        throw;
                    }
                }

                return(new TimeSeriesStore
                {
                    Name = timeSeriesName,
                    Url = parent.Url,
                    Credentials = credentials ?? parent.Credentials
                });
            }
Ejemplo n.º 6
0
 public OperationMetadata(string url, ICredentials credentials, string apiKey = null)
 {
     Url         = url;
     Credentials = new OperationCredentials(apiKey, credentials);
 }
Ejemplo n.º 7
0
 public OperationMetadata(OperationMetadata operationMetadata)
 {
     Url                = operationMetadata.Url;
     Credentials        = new OperationCredentials(operationMetadata.Credentials.ApiKey, operationMetadata.Credentials.Credentials);
     ClusterInformation = new ClusterInformation(operationMetadata.ClusterInformation.IsInCluster, operationMetadata.ClusterInformation.IsLeader);
 }
Ejemplo n.º 8
0
        private async Task <AsyncOperationResult <T> > TryExecutingOperationsOnSecondaryNodes <T>(Func <string, string, Task <T> > operation, CancellationToken token, List <TimeSeriesReplicationDestination> localReplicationDestinations, OperationCredentials operationCredentials)
        {
            for (var i = 0; i < localReplicationDestinations.Count; i++)
            {
                token.ThrowCancellationIfNotDefault();

                var replicationDestination = localReplicationDestinations[i];
                if (ShouldExecuteUsing(replicationDestination.TimeSeriesUrl, operationCredentials, token) == false)
                {
                    continue;
                }

                var hasMoreReplicationDestinations = localReplicationDestinations.Count > i + 1;
                var operationResult = await TryExecuteOperationAsync(replicationDestination.ServerUrl, replicationDestination.TimeSeriesName, operation, hasMoreReplicationDestinations, operationCredentials, token).ConfigureAwait(false);

                if (operationResult.Success)
                {
                    return(operationResult);
                }

                failureTimeSeries.IncrementFailureCount(replicationDestination.ServerUrl);
                if (!operationResult.WasTimeout && failureTimeSeries.IsFirstFailure(replicationDestination.ServerUrl))
                {
                    operationResult = await TryExecuteOperationAsync(replicationDestination.ServerUrl, replicationDestination.TimeSeriesName, operation, hasMoreReplicationDestinations, operationCredentials, token).ConfigureAwait(false);

                    if (operationResult.Success)
                    {
                        return(operationResult);
                    }

                    failureTimeSeries.IncrementFailureCount(replicationDestination.ServerUrl);
                }
            }

            return(new AsyncOperationResult <T>
            {
                Result = default(T),
                Success = false
            });
        }
Ejemplo n.º 9
0
        private async Task <AsyncOperationResult <T> > TryExecuteOperationOnPrimaryNode <T>(string timeSeriesStoreUrl, Func <string, string, Task <T> > operation, CancellationToken token, OperationCredentials operationCredentials)
        {
            if (ShouldExecuteUsing(timeSeriesStoreUrl, operationCredentials, token))
            {
                var operationResult = await TryExecuteOperationAsync(timeSeriesStoreUrl, timeSeriesStore.Name, operation, true, operationCredentials, token).ConfigureAwait(false);

                if (operationResult.Success)
                {
                    return(operationResult);
                }

                failureTimeSeries.IncrementFailureCount(timeSeriesStoreUrl);
            }

            return(new AsyncOperationResult <T>
            {
                Result = default(T),
                Success = false
            });
        }
Ejemplo n.º 10
0
        private async Task <AsyncOperationResult <T> > TryExecuteOperationWithLoadBalancing <T>(string timeSeriesStoreUrl, Func <string, string, Task <T> > operation, CancellationToken token, List <TimeSeriesReplicationDestination> localReplicationDestinations, OperationCredentials operationCredentials)
        {
            //essentially do round robin load balancing here
            var replicationIndex = currentReadStripingBase % (localReplicationDestinations.Count + 1);
            AsyncOperationResult <T> operationResult;

            if (ShouldReadFromSecondaryNode(replicationIndex, localReplicationDestinations))
            {
                var storeUrl  = localReplicationDestinations[replicationIndex].ServerUrl;
                var storeName = localReplicationDestinations[replicationIndex].TimeSeriesName;
                if (ShouldExecuteUsing(storeUrl, operationCredentials, token))
                {
                    operationResult = await TryExecuteOperationAsync(storeUrl, storeName, operation, true, operationCredentials, token).ConfigureAwait(false);

                    if (operationResult.Success)
                    {
                        return(operationResult);
                    }
                }
            }
            else //read from primary node
            {
                if (ShouldExecuteUsing(timeSeriesStoreUrl, operationCredentials, token))
                {
                    operationResult = await TryExecuteOperationAsync(timeSeriesStoreUrl, timeSeriesStore.Name, operation, true, operationCredentials, token).ConfigureAwait(false);

                    if (operationResult.Success)
                    {
                        return(operationResult);
                    }
                }
            }

            return(new AsyncOperationResult <T>
            {
                Result = default(T),
                Success = false
            });
        }
Ejemplo n.º 11
0
        private async Task <AsyncOperationResult <T> > TryExecuteOperationAsync <T>(string url, string timeSeriesStoreName, Func <string, string, Task <T> > operation, bool avoidThrowing, OperationCredentials credentials, CancellationToken cancellationToken)
        {
            var  tryWithPrimaryCredentials = failureTimeSeries.IsFirstFailure(url);
            bool shouldTryAgain            = false;

            try
            {
                cancellationToken.ThrowCancellationIfNotDefault(); //canceling the task here potentially will stop the recursion
                var result = await operation(url, timeSeriesStoreName).ConfigureAwait(false);

                failureTimeSeries.ResetFailureCount(url);
                return(new AsyncOperationResult <T>
                {
                    Result = result,
                    Success = true
                });
            }
            catch (Exception e)
            {
                var ae = e as AggregateException;
                ErrorResponseException errorResponseException;
                if (ae != null)
                {
                    errorResponseException = ae.ExtractSingleInnerException() as ErrorResponseException;
                }
                else
                {
                    errorResponseException = e as ErrorResponseException;
                }
                if (tryWithPrimaryCredentials && credentials.HasCredentials() && errorResponseException != null)
                {
                    failureTimeSeries.IncrementFailureCount(url);

                    if (errorResponseException.StatusCode == HttpStatusCode.Unauthorized)
                    {
                        shouldTryAgain = true;
                    }
                }

                if (shouldTryAgain == false)
                {
                    if (avoidThrowing == false)
                    {
                        throw;
                    }

                    bool wasTimeout;
                    var  isServerDown = HttpConnectionHelper.IsServerDown(e, out wasTimeout);

                    if (avoidThrowing == false)
                    {
                        throw;
                    }

                    if (e.Data.Contains(Constants.RequestFailedExceptionMarker) && isServerDown)
                    {
                        return(new AsyncOperationResult <T>
                        {
                            Success = false,
                            WasTimeout = wasTimeout,
                            Error = e
                        });
                    }

                    if (isServerDown)
                    {
                        return(new AsyncOperationResult <T>
                        {
                            Success = false,
                            WasTimeout = wasTimeout,
                            Error = e
                        });
                    }
                    throw;
                }
            }
            return(await TryExecuteOperationAsync(url, timeSeriesStoreName, operation, avoidThrowing, credentials, cancellationToken).ConfigureAwait(false));
        }
Ejemplo n.º 12
0
        private async Task <AsyncOperationResult <T> > TryExecuteOperationWithFailover <T>(string timeSeriesStoreUrl, Func <string, string, Task <T> > operation, CancellationToken token, OperationCredentials operationCredentials, bool shouldFailImmediately, List <TimeSeriesReplicationDestination> localReplicationDestinations)
        {
            var operationResult = await TryExecuteOperationOnPrimaryNode(timeSeriesStoreUrl, operation, token, operationCredentials).ConfigureAwait(false);

            if (operationResult.Success)
            {
                return(operationResult);
            }

            if (shouldFailImmediately)
            {
                throw new InvalidOperationException(@"Attempted to connect to master and failed. Since there is FailImmediately flag specified in FailoverBehavior, failing the operation.");
            }

            operationResult = await TryExecutingOperationsOnSecondaryNodes(operation, token, localReplicationDestinations, operationCredentials).ConfigureAwait(false);

            if (operationResult.Success)
            {
                return(operationResult);
            }

            return(new AsyncOperationResult <T>
            {
                Result = default(T),
                Success = false
            });
        }
Ejemplo n.º 13
0
 public Task <T> ExecuteWithReplicationAsync <T>(string method, string primaryUrl, OperationCredentials primaryCredentials, int currentRequest, int currentReadStripingBase, Func <OperationMetadata, Task <T> > operation, CancellationToken token)
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 14
0
 public OperationMetadata(string url, OperationCredentials credentials)
 {
     Url         = url;
     Credentials = credentials != null ? new OperationCredentials(credentials.ApiKey, credentials.Credentials) : new OperationCredentials(null, null);
 }
Ejemplo n.º 15
0
 public CreateHttpJsonRequestParams(IHoldProfilingInformation self, string url, string method, OperationCredentials credentials, DocumentConvention convention)
     : this(self, url, method, new RavenJObject(), credentials, convention)
 {
 }
Ejemplo n.º 16
0
        public async Task <T> ExecuteWithReplicationAsync <T>(string timeSeriesStoreUrl, HttpMethod method, Func <string, string, Task <T> > operation, CancellationToken token)
        {
            Debug.Assert(typeof(T).FullName.Contains("Task") == false);

            if (currentlyExecuting && TimeSeriesConventions.AllowMultipleAsyncOperations == false)
            {
                throw new InvalidOperationException("Only a single concurrent async request is allowed per async store instance.");
            }

            currentlyExecuting = true;
            try
            {
                var operationCredentials         = new OperationCredentials(timeSeriesStore.Credentials.ApiKey, timeSeriesStore.Credentials.Credentials);
                var localReplicationDestinations = ReplicationDestinationsAccordingToFailover; // thread safe copy

                //check for supported flags
                var shouldReadFromAllServers = (TimeSeriesConventions.FailoverBehavior & FailoverBehavior.ReadFromAllServers) != 0;
                var shouldFailImmediately    = (TimeSeriesConventions.FailoverBehavior & FailoverBehavior.FailImmediately) != 0;

                AsyncOperationResult <T> operationResult;

                if (shouldReadFromAllServers && localReplicationDestinations.Count > 0 && !shouldFailImmediately)
                {
                    operationResult = await TryExecuteOperationWithLoadBalancing(timeSeriesStoreUrl, operation, token, localReplicationDestinations, operationCredentials).ConfigureAwait(false);

                    if (operationResult.Success)
                    {
                        return(operationResult.Result);
                    }

                    RefreshReplicationInformation(); //force refresh of cluster information -> we failed to do round-robin, maybe some servers are down?
                }

                //if we did load balancing and got to this point, this means we failed to connect to the designated server, and then the following
                //logic would server as 'retry' strategy -> failed to do round-robin -> retry nodes one-by-one

                //otherwise we didn't do load balancing; therefore go the usual route -> try to read from primary and if fails -> try to read from secondary

                operationResult = await TryExecuteOperationAsync(timeSeriesStoreUrl, timeSeriesStore.Name, operation, false, operationCredentials, token).ConfigureAwait(false);

                if (operationResult.Success)
                {
                    return(operationResult.Result);
                }

                //maybe it's transient failure? if so, try again
                if (operationResult.Success == false && failureTimeSeries.IsFirstFailure(timeSeriesStoreUrl))
                {
                    RefreshReplicationInformation();
                    operationResult = await TryExecuteOperationWithFailover(timeSeriesStoreUrl, operation, token, operationCredentials, shouldFailImmediately, localReplicationDestinations).ConfigureAwait(false);

                    if (operationResult.Success)
                    {
                        return(operationResult.Result);
                    }
                }

                // this should not be thrown, but sometimes, things go _really_ wrong...
                throw new InvalidOperationException(@"Attempted to connect to master and all replicas have failed, giving up.
                        There is a high probability of a network problem preventing access to all the replicas.
                        Failed to get in touch with any of the " + (1 + localReplicationDestinations.Count) + " TimeSeries instances.");
            }
            catch (AggregateException e)
            {
                var singleException = e.ExtractSingleInnerException();
                if (singleException != null)
                {
                    throw singleException;
                }

                throw;
            }
            finally
            {
                Interlocked.Increment(ref currentReadStripingBase);
                currentlyExecuting = false;
            }
        }
Ejemplo n.º 17
0
 public CreateHttpJsonRequestParams(IHoldProfilingInformation self, string url, string method, RavenJObject metadata, OperationCredentials credentials, DocumentConvention convention)
 {
     Owner       = self;
     Url         = url;
     Method      = method;
     Metadata    = metadata;
     Credentials = credentials;
     Convention  = convention;
     operationsHeadersCollection = new NameValueCollection();
 }
Ejemplo n.º 18
0
        protected ITimeSeriesStore NewRemoteTimeSeriesStore(int port = 8079, RavenDbServer ravenDbServer = null, bool createDefaultTimeSeries = true, OperationCredentials credentials = null)
        {
            ravenDbServer = GetNewServer(requestedStorage: "voron", databaseName: DefaultTimeSeriesName + "Database", port: port);

            var timeSeriesStore = new TimeSeriesStore
            {
                Url         = GetServerUrl(true, ravenDbServer.SystemDatabase.ServerUrl),
                Credentials = credentials ?? new OperationCredentials(null, CredentialCache.DefaultNetworkCredentials),
                Name        = DefaultTimeSeriesName + (timeSeriesStores.Count + 1)
            };

            timeSeriesStore.Initialize(createDefaultTimeSeries);
            timeSeriesStores.Add(timeSeriesStore);
            return(timeSeriesStore);
        }
Ejemplo n.º 19
0
 public OperationMetadata(string url, OperationCredentials credentials, ClusterInformation clusterInformation)
 {
     Url                = url;
     Credentials        = credentials != null ? new OperationCredentials(credentials.ApiKey, credentials.Credentials) : new OperationCredentials(null, null);
     ClusterInformation = clusterInformation != null ? new ClusterInformation(clusterInformation.IsInCluster, clusterInformation.IsLeader) : ClusterInformation.NotInCluster;
 }
Ejemplo n.º 20
0
        private void InitializeSecurity()
        {
            if (convention.HandleUnauthorizedResponseAsync != null)
            {
                return; // already setup by the user
            }
            if (string.IsNullOrEmpty(ApiKey) == false)
            {
                Credentials = null;
            }

            credentialsThatShouldBeUsedOnlyInOperationsWithoutReplication = new OperationCredentials(ApiKey, Credentials);

            var basicAuthenticator   = new BasicAuthenticator(JsonRequestFactory.EnableBasicAuthenticationOverUnsecuredHttpEvenThoughPasswordsWouldBeSentOverTheWireInClearTextToBeStolenByHackers);
            var securedAuthenticator = new SecuredAuthenticator();

            JsonRequestFactory.ConfigureRequest += basicAuthenticator.ConfigureRequest;
            JsonRequestFactory.ConfigureRequest += securedAuthenticator.ConfigureRequest;

            convention.HandleForbiddenResponseAsync = (forbiddenResponse, credentials) =>
            {
                if (credentials.ApiKey == null)
                {
                    AssertForbiddenCredentialSupportWindowsAuth(forbiddenResponse);
                    return(null);
                }

                return(null);
            };

            convention.HandleUnauthorizedResponseAsync = (unauthorizedResponse, credentials) =>
            {
                var oauthSource = unauthorizedResponse.Headers.GetFirstValue("OAuth-Source");

#if DEBUG && FIDDLER
                // Make sure to avoid a cross DNS security issue, when running with Fiddler
                if (string.IsNullOrEmpty(oauthSource) == false)
                {
                    oauthSource = oauthSource.Replace("localhost:", "localhost.fiddler:");
                }
#endif

                // Legacy support
                if (string.IsNullOrEmpty(oauthSource) == false &&
                    oauthSource.EndsWith("/OAuth/API-Key", StringComparison.CurrentCultureIgnoreCase) == false)
                {
                    return(basicAuthenticator.HandleOAuthResponseAsync(oauthSource, credentials.ApiKey));
                }

                if (credentials.ApiKey == null)
                {
                    AssertUnauthorizedCredentialSupportWindowsAuth(unauthorizedResponse, credentials.Credentials);
                    return(null);
                }

                if (string.IsNullOrEmpty(oauthSource))
                {
                    oauthSource = ServerUrl + "/OAuth/API-Key";
                }

                return(securedAuthenticator.DoOAuthRequestAsync(ServerUrl, oauthSource, credentials.ApiKey));
            };
        }
Ejemplo n.º 21
0
 public CreateHttpJsonRequestParams(IHoldProfilingInformation self, string url, HttpMethod method, RavenJObject metadata, OperationCredentials credentials, ConventionBase convention, IRequestTimeMetric requestTimeMetric = null, TimeSpan?timeout = null)
 {
     Owner                       = self;
     Url                         = url;
     Method                      = method;
     Metadata                    = metadata;
     Credentials                 = credentials;
     Convention                  = convention;
     RequestTimeMetric           = requestTimeMetric;
     Timeout                     = timeout;
     operationsHeadersCollection = new NameValueCollection();
     ShouldCacheRequest          = convention != null ? convention.ShouldCacheRequest : urlParam => false;
 }
Ejemplo n.º 22
0
        internal HttpJsonRequest(
            CreateHttpJsonRequestParams requestParams,
            HttpJsonRequestFactory factory)
        {
            _credentials        = requestParams.DisableAuthentication == false ? requestParams.Credentials : null;
            disabledAuthRetries = requestParams.DisableAuthentication;

            Url    = requestParams.Url;
            Method = requestParams.Method;

            if (requestParams.Timeout.HasValue)
            {
                Timeout = requestParams.Timeout.Value;
            }
            else
            {
                Timeout = TimeSpan.FromSeconds(100); // default HttpClient timeout
#if DEBUG
                if (Debugger.IsAttached)
                {
                    Timeout = TimeSpan.FromMinutes(5);
                }
#endif
            }

            this.factory      = factory;
            owner             = requestParams.Owner;
            conventions       = requestParams.Convention;
            requestTimeMetric = requestParams.RequestTimeMetric;

            recreateHandler = factory.httpMessageHandler ?? (
                () =>
            {
                var useDefaultCredentials = _credentials != null && _credentials.HasCredentials() == false;
                ICredentials credentialsToUse = null;
                if (_credentials != null)
                {
                    var networkCredentials = _credentials.Credentials as NetworkCredential;
                    if (networkCredentials != null && factory.authenticationScheme != null)
                    {
                        var credentialCache = new CredentialCache();
                        var uri = new Uri(requestParams.Url);
                        credentialCache.Add(new Uri(string.Format("{0}://{1}:{2}/", uri.Scheme, uri.Host, uri.Port)), factory.authenticationScheme, networkCredentials);

                        credentialsToUse = credentialCache;
                    }
                    else
                    {
                        credentialsToUse = _credentials.Credentials;
                    }
                }
#if !DNXCORE50
                var handler = new WebRequestHandler
                {
                    AllowAutoRedirect = false,
                    UseDefaultCredentials = useDefaultCredentials,
                    Credentials = credentialsToUse
                };
#else
                var handler = new HttpClientHandler
                {
                    AllowAutoRedirect = false,
                    UseDefaultCredentials = useDefaultCredentials,
                    Credentials = credentialsToUse
                };
#endif
                return(handler);
            }
                );

            httpClient = factory.httpClientCache.GetClient(Timeout, _credentials, recreateHandler);

            if (factory.DisableRequestCompression == false && requestParams.DisableRequestCompression == false)
            {
                if (Method == HttpMethods.Post || Method == HttpMethods.Put || Method == HttpMethods.Patch || Method == HttpMethods.Eval)
                {
                    httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Encoding", "gzip");
                    httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
                }

                if (factory.acceptGzipContent)
                {
                    httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
                }
            }

            headers.Add("Raven-Client-Version", ClientVersion);
            WriteMetadata(requestParams.Metadata);
            requestParams.UpdateHeaders(headers);
        }
        public async Task <T> ExecuteWithReplicationAsync <T>(HttpMethod method,
                                                              string primaryUrl,
                                                              OperationCredentials primaryCredentials,
                                                              int currentRequest,
                                                              int currentReadStripingBase,
                                                              Func <OperationMetadata, IRequestTimeMetric, Task <T> > operation,
                                                              CancellationToken token = default(CancellationToken))
        {
            Debug.Assert(typeof(T).FullName.Contains("Task") == false);

            var localReplicationDestinations = ReplicationDestinationsUrls; // thread safe copy
            var primaryOperation             = new OperationMetadata(primaryUrl, primaryCredentials, null);

            var operationResult          = new AsyncOperationResult <T>();
            var shouldReadFromAllServers = Conventions.FailoverBehavior.HasFlag(FailoverBehavior.ReadFromAllServers);

            var allowReadFromSecondariesWhenRequestTimeSlaThresholdIsPassed = Conventions.FailoverBehavior.HasFlag(FailoverBehavior.AllowReadFromSecondariesWhenRequestTimeSlaThresholdIsReached);
            var primaryRequestTimeMetric = requestTimeMetricGetter?.Invoke(primaryOperation.Url);
            var complexTimeMetric        = new ComplexTimeMetric();

            if (method == HttpMethods.Get && (shouldReadFromAllServers || allowReadFromSecondariesWhenRequestTimeSlaThresholdIsPassed))
            {
                var replicationIndex = -1;
                if (allowReadFromSecondariesWhenRequestTimeSlaThresholdIsPassed && shouldReadFromAllServers)
                {
                    if (requestTimeMetricGetter != null && primaryRequestTimeMetric != null)
                    {
                        complexTimeMetric.AddCurrent(primaryRequestTimeMetric); // want to decrease everything
                        foreach (var destination in localReplicationDestinations)
                        {
                            complexTimeMetric.AddCurrent(requestTimeMetricGetter(destination.Url));
                        }

                        replicationIndex = currentReadStripingBase % (localReplicationDestinations.Count + 1); // include primary
                        for (var i = 0; i < localReplicationDestinations.Count + 1; i++)
                        {
                            IRequestTimeMetric metric;
                            if (replicationIndex >= localReplicationDestinations.Count) // primary
                            {
                                metric = primaryRequestTimeMetric;
                            }
                            else
                            {
                                metric = requestTimeMetricGetter(localReplicationDestinations[replicationIndex].Url);
                            }

                            if (metric.RateSurpassed(Conventions) == false)
                            {
                                complexTimeMetric.AddCurrent(metric);
                                break;
                            }

                            replicationIndex = (replicationIndex + 1) % (localReplicationDestinations.Count + 1);
                        }
                    }
                }
                else if (allowReadFromSecondariesWhenRequestTimeSlaThresholdIsPassed)
                {
                    if (primaryRequestTimeMetric != null)
                    {
                        complexTimeMetric.AddCurrent(primaryRequestTimeMetric);

                        if (complexTimeMetric.RateSurpassed(Conventions))
                        {
                            replicationIndex = currentReadStripingBase % localReplicationDestinations.Count; // this will skip the primary
                        }
                    }
                }
                else if (shouldReadFromAllServers)
                {
                    replicationIndex = currentReadStripingBase % (localReplicationDestinations.Count + 1);
                }

                // if replicationIndex == destinations count, then we want to use the master
                // if replicationIndex < 0, then we were explicitly instructed to use the master
                if (replicationIndex < localReplicationDestinations.Count && replicationIndex >= 0)
                {
                    var destination = localReplicationDestinations[replicationIndex];
                    // if it is failing, ignore that, and move to the master or any of the replicas
                    if (ShouldExecuteUsing(destination, primaryOperation, method, false, null, token))
                    {
                        if (requestTimeMetricGetter != null)
                        {
                            complexTimeMetric.AddCurrent(requestTimeMetricGetter(destination.Url));
                        }

                        operationResult = await TryOperationAsync(operation, destination, primaryOperation, complexTimeMetric, true, token).ConfigureAwait(false);

                        if (operationResult.Success)
                        {
                            return(operationResult.Result);
                        }
                    }
                }
            }

            if (ShouldExecuteUsing(primaryOperation, primaryOperation, method, true, null, token))
            {
                if (primaryRequestTimeMetric != null)
                {
                    complexTimeMetric.AddCurrent(primaryRequestTimeMetric);
                }

                operationResult = await TryOperationAsync(operation, primaryOperation, null, complexTimeMetric, !operationResult.WasTimeout && localReplicationDestinations.Count > 0, token)
                                  .ConfigureAwait(false);

                if (operationResult.Success)
                {
                    return(operationResult.Result);
                }

                FailureCounters.IncrementFailureCount(primaryOperation.Url);
                if (operationResult.WasTimeout == false && FailureCounters.IsFirstFailure(primaryOperation.Url))
                {
                    operationResult = await TryOperationAsync(operation, primaryOperation, null, complexTimeMetric, localReplicationDestinations.Count > 0, token).ConfigureAwait(false);

                    if (operationResult.Success)
                    {
                        return(operationResult.Result);
                    }

                    FailureCounters.IncrementFailureCount(primaryOperation.Url);
                }
            }

            for (var i = 0; i < localReplicationDestinations.Count; i++)
            {
                token.ThrowCancellationIfNotDefault();

                var destination = localReplicationDestinations[i];
                if (ShouldExecuteUsing(destination, primaryOperation, method, false, operationResult.Error, token) == false)
                {
                    continue;
                }

                if (requestTimeMetricGetter != null)
                {
                    complexTimeMetric.AddCurrent(requestTimeMetricGetter(destination.Url));
                }

                var hasMoreReplicationDestinations = localReplicationDestinations.Count > i + 1;
                operationResult = await TryOperationAsync(operation, destination, primaryOperation, complexTimeMetric, !operationResult.WasTimeout && hasMoreReplicationDestinations, token).ConfigureAwait(false);

                if (operationResult.Success)
                {
                    return(operationResult.Result);
                }

                FailureCounters.IncrementFailureCount(destination.Url);
                if (operationResult.WasTimeout == false && FailureCounters.IsFirstFailure(destination.Url))
                {
                    operationResult = await TryOperationAsync(operation, destination, primaryOperation, complexTimeMetric, hasMoreReplicationDestinations, token).ConfigureAwait(false);

                    // tuple = await TryOperationAsync(operation, replicationDestination, primaryOperation, localReplicationDestinations.Count > i + 1).ConfigureAwait(false);
                    if (operationResult.Success)
                    {
                        return(operationResult.Result);
                    }
                    FailureCounters.IncrementFailureCount(destination.Url);
                }
            }

            // this should not be thrown, but since I know the value of should...
            throw new InvalidOperationException(@"Attempted to connect to master and all replicas have failed, giving up.
There is a high probability of a network problem preventing access to all the replicas.
Failed to get in touch with any of the " + (1 + localReplicationDestinations.Count) + " Raven instances.");
        }
Ejemplo n.º 24
0
        public virtual T ExecuteWithReplication <T>(string method, string primaryUrl, OperationCredentials primaryCredentials, int currentRequest, int currentReadStripingBase, Func <OperationMetadata, T> operation)
        {
            T   result;
            var timeoutThrown = false;

            var localReplicationDestinations = ReplicationDestinationsUrls;             // thread safe copy
            var primaryOperation             = new OperationMetadata(primaryUrl, primaryCredentials);

            var shouldReadFromAllServers = conventions.FailoverBehavior.HasFlag(FailoverBehavior.ReadFromAllServers);

            if (shouldReadFromAllServers && method == "GET")
            {
                var replicationIndex = currentReadStripingBase % (localReplicationDestinations.Count + 1);
                // if replicationIndex == destinations count, then we want to use the master
                // if replicationIndex < 0, then we were explicitly instructed to use the master
                if (replicationIndex < localReplicationDestinations.Count && replicationIndex >= 0)
                {
                    // if it is failing, ignore that, and move to the master or any of the replicas
                    if (ShouldExecuteUsing(localReplicationDestinations[replicationIndex].Url, currentRequest, method, false))
                    {
                        if (TryOperation(operation, localReplicationDestinations[replicationIndex], primaryOperation, true, out result, out timeoutThrown))
                        {
                            return(result);
                        }
                    }
                }
            }

            if (ShouldExecuteUsing(primaryOperation.Url, currentRequest, method, true))
            {
                if (TryOperation(operation, primaryOperation, null, !timeoutThrown && localReplicationDestinations.Count > 0, out result, out timeoutThrown))
                {
                    return(result);
                }
                if (!timeoutThrown && IsFirstFailure(primaryOperation.Url) &&
                    TryOperation(operation, primaryOperation, null, localReplicationDestinations.Count > 0, out result, out timeoutThrown))
                {
                    return(result);
                }
                IncrementFailureCount(primaryOperation.Url);
            }

            for (var i = 0; i < localReplicationDestinations.Count; i++)
            {
                var replicationDestination = localReplicationDestinations[i];
                if (ShouldExecuteUsing(replicationDestination.Url, currentRequest, method, false) == false)
                {
                    continue;
                }
                if (TryOperation(operation, replicationDestination, primaryOperation, !timeoutThrown, out result, out timeoutThrown))
                {
                    return(result);
                }
                if (!timeoutThrown && IsFirstFailure(replicationDestination.Url) &&
                    TryOperation(operation, replicationDestination, primaryOperation, localReplicationDestinations.Count > i + 1, out result,
                                 out timeoutThrown))
                {
                    return(result);
                }
                IncrementFailureCount(replicationDestination.Url);
            }
            // this should not be thrown, but since I know the value of should...
            throw new InvalidOperationException(@"Attempted to connect to master and all replicas have failed, giving up.
There is a high probability of a network problem preventing access to all the replicas.
Failed to get in touch with any of the " + (1 + localReplicationDestinations.Count) + " Raven instances.");
        }
Ejemplo n.º 25
0
        internal HttpJsonRequest(
            CreateHttpJsonRequestParams requestParams,
            HttpJsonRequestFactory factory)
        {
            try
            {
                _credentials        = requestParams.DisableAuthentication == false ? requestParams.Credentials : null;
                disabledAuthRetries = requestParams.DisableAuthentication;

                Url    = requestParams.Url;
                Method = requestParams.Method;

                if (requestParams.Timeout.HasValue)
                {
                    Timeout = requestParams.Timeout.Value;
                }
                else
                {
                    Timeout = TimeSpan.FromSeconds(100);                     // default HttpClient timeout
#if DEBUG
                    if (Debugger.IsAttached)
                    {
                        Timeout = TimeSpan.FromMinutes(5);
                    }
#endif
                }

                this.factory = factory;
                owner        = requestParams.Owner;
                conventions  = requestParams.Convention;

                if (factory.httpMessageHandler != null)
                {
                    recreateHandler = () => factory.httpMessageHandler;
                }
                else
                {
                    recreateHandler = () => new WebRequestHandler
                    {
                        UseDefaultCredentials = _credentials != null && _credentials.HasCredentials() == false,
                        Credentials           = _credentials != null ? _credentials.Credentials : null,
                    };
                }

                httpClient = factory.httpClientCache.GetClient(Timeout, _credentials, recreateHandler);

                if (factory.DisableRequestCompression == false && requestParams.DisableRequestCompression == false)
                {
                    if (Method == "POST" || Method == "PUT" || Method == "PATCH" || Method == "EVAL")
                    {
                        httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Encoding", "gzip");
                        httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
                    }

                    httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
                }

                headers.Add("Raven-Client-Version", ClientVersion);
                WriteMetadata(requestParams.Metadata);
                requestParams.UpdateHeaders(headers);
            }
            catch (Exception)
            {
                throw;
            }
        }
Ejemplo n.º 26
0
 public OperationMetadata(string url, OperationCredentials credentials)
 {
     Url         = url;
     Credentials = new OperationCredentials(credentials.ApiKey, credentials.Credentials);
 }
Ejemplo n.º 27
0
 public static HttpJsonRequest ToJsonRequest(this string url, AsyncServerClient requestor, OperationCredentials credentials, DocumentConvention convention)
 {
     return(requestor.jsonRequestFactory.CreateHttpJsonRequest(new CreateHttpJsonRequestParams(requestor, url, "GET", credentials, convention)));
 }
Ejemplo n.º 28
0
        internal static async Task <RavenJObject> GetMetadataForAsyncImpl(IHoldProfilingInformation self, HttpJsonRequestFactory requestFactory, FilesConvention conventions,
                                                                          NameValueCollection operationsHeaders, string filename, string baseUrl, OperationCredentials credentials)
        {
            using (var request = requestFactory.CreateHttpJsonRequest(new CreateHttpJsonRequestParams(self, baseUrl + "/files?name=" + Uri.EscapeDataString(filename), "HEAD", credentials, conventions)).AddOperationHeaders(operationsHeaders))
            {
                try
                {
                    await request.ExecuteRequestAsync().ConfigureAwait(false);

                    var response = request.Response;

                    var metadata = response.HeadersToObject();
                    metadata[Constants.MetadataEtagField] = metadata[Constants.MetadataEtagField].Value <string>().Trim('\"');
                    return(metadata);
                }
                catch (Exception e)
                {
                    try
                    {
                        throw e.SimplifyException();
                    }
                    catch (FileNotFoundException)
                    {
                        return(null);
                    }
                }
            }
        }