public OperationMetadata(OperationMetadata operationMetadata) { Url = operationMetadata.Url; Credentials = new OperationCredentials(operationMetadata.Credentials.ApiKey, operationMetadata.Credentials.Credentials); }
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."); }
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(); } }
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) { }
/// <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 }); }
public OperationMetadata(string url, ICredentials credentials, string apiKey = null) { Url = url; Credentials = new OperationCredentials(apiKey, credentials); }
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); }
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 }); }
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 }); }
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 }); }
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)); }
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 }); }
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(); }
public OperationMetadata(string url, OperationCredentials credentials) { Url = url; Credentials = credentials != null ? new OperationCredentials(credentials.ApiKey, credentials.Credentials) : new OperationCredentials(null, null); }
public CreateHttpJsonRequestParams(IHoldProfilingInformation self, string url, string method, OperationCredentials credentials, DocumentConvention convention) : this(self, url, method, new RavenJObject(), credentials, convention) { }
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; } }
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(); }
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); }
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; }
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)); }; }
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; }
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."); }
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."); }
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; } }
public OperationMetadata(string url, OperationCredentials credentials) { Url = url; Credentials = new OperationCredentials(credentials.ApiKey, credentials.Credentials); }
public static HttpJsonRequest ToJsonRequest(this string url, AsyncServerClient requestor, OperationCredentials credentials, DocumentConvention convention) { return(requestor.jsonRequestFactory.CreateHttpJsonRequest(new CreateHttpJsonRequestParams(requestor, url, "GET", credentials, convention))); }
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); } } } }