public void OnSuccessIsOnlyCalledOnce() { const int MaxTries = 5; const int ExpectedFailures = 0; const int ExpectedTries = 1; RetryWrapper <bool> dut = new RetryWrapper <bool>(MaxTries, CancellationToken.None, exponentialBackoffBase: 0); int actualFailures = 0; dut.OnFailure += errorArgs => actualFailures++; int actualTries = 0; RetryWrapper <bool> .InvocationResult output = dut.Invoke( tryCount => { actualTries++; return(new RetryWrapper <bool> .CallbackResult(true)); }); output.Succeeded.ShouldEqual(true); output.Result.ShouldEqual(true); actualTries.ShouldEqual(ExpectedTries); actualFailures.ShouldEqual(ExpectedFailures); }
public virtual GitRefs QueryInfoRefs(string branch) { Uri infoRefsEndpoint; try { infoRefsEndpoint = new Uri(this.enlistment.RepoUrl + GVFSConstants.InfoRefsEndpointSuffix); } catch (UriFormatException) { return(null); } RetryWrapper <GitRefs> retrier = new RetryWrapper <GitRefs>(this.MaxRetries); retrier.OnFailure += RetryWrapper <GitRefs> .StandardErrorHandler(this.Tracer, "QueryInfoRefs"); RetryWrapper <GitRefs> .InvocationResult output = retrier.Invoke( tryCount => { GitEndPointResponseData response = this.SendRequest(infoRefsEndpoint, HttpMethod.Get, null); if (response.HasErrors) { return(new RetryWrapper <GitRefs> .CallbackResult(response.Error, response.ShouldRetry)); } using (StreamReader reader = new StreamReader(response.Stream)) { List <string> infoRefsResponse = reader.RetryableReadAllLines(); return(new RetryWrapper <GitRefs> .CallbackResult(new GitRefs(infoRefsResponse, branch))); } }); return(output.Result); }
public void WillNotRetryForWhenCanceledDuringAttempts() { const int MaxTries = 5; int actualTries = 0; int expectedTries = 3; using (CancellationTokenSource tokenSource = new CancellationTokenSource()) { RetryWrapper <bool> dut = new RetryWrapper <bool>(MaxTries, tokenSource.Token, exponentialBackoffBase: 0); Assert.Throws <OperationCanceledException>( () => { RetryWrapper <bool> .InvocationResult output = dut.Invoke(tryCount => { ++actualTries; if (actualTries == expectedTries) { tokenSource.Cancel(); } return(new RetryWrapper <bool> .CallbackResult(new Exception("Test"), shouldRetry: true)); }); }); actualTries.ShouldEqual(expectedTries); } }
public void WillNotRetryWhenCancelledDuringBackoff() { const int MaxTries = 5; int actualTries = 0; int expectedTries = 2; // 2 because RetryWrapper does not wait after the first failure using (CancellationTokenSource tokenSource = new CancellationTokenSource()) { RetryWrapper <bool> dut = new RetryWrapper <bool>(MaxTries, tokenSource.Token, exponentialBackoffBase: 300); Task.Run(() => { // Wait 3 seconds and cancel Thread.Sleep(1000 * 3); tokenSource.Cancel(); }); Assert.Throws <OperationCanceledException>( () => { RetryWrapper <bool> .InvocationResult output = dut.Invoke(tryCount => { ++actualTries; return(new RetryWrapper <bool> .CallbackResult(new Exception("Test"), shouldRetry: true)); }); }); actualTries.ShouldEqual(expectedTries); } }
public virtual RetryWrapper <GitObjectTaskResult> .InvocationResult TrySendProtocolRequest( Func <int, GitEndPointResponseData, RetryWrapper <GitObjectTaskResult> .CallbackResult> onSuccess, Action <RetryWrapper <GitObjectTaskResult> .ErrorEventArgs> onFailure, HttpMethod method, Func <Uri> endPointGenerator, Func <string> requestBodyGenerator, MediaTypeWithQualityHeaderValue acceptType = null) { RetryWrapper <GitObjectTaskResult> retrier = new RetryWrapper <GitObjectTaskResult>(this.MaxRetries); if (onFailure != null) { retrier.OnFailure += onFailure; } return(retrier.Invoke( tryCount => { GitEndPointResponseData response = this.SendRequest( endPointGenerator(), method, requestBodyGenerator(), acceptType); if (response.HasErrors) { return new RetryWrapper <GitObjectTaskResult> .CallbackResult(response.Error, response.ShouldRetry, new GitObjectTaskResult(response.StatusCode)); } using (Stream responseStream = response.Stream) { return onSuccess(tryCount, response); } })); }
public void WillRetryWhenRequested() { const int MaxTries = 5; const int ExpectedFailures = 5; const int ExpectedTries = 5; RetryWrapper <bool> dut = new RetryWrapper <bool>(MaxTries, CancellationToken.None, exponentialBackoffBase: 0); int actualFailures = 0; dut.OnFailure += errorArgs => actualFailures++; int actualTries = 0; RetryWrapper <bool> .InvocationResult output = dut.Invoke( tryCount => { actualTries++; return(new RetryWrapper <bool> .CallbackResult(new Exception("Test"), shouldRetry: true)); }); output.Succeeded.ShouldEqual(false); output.Result.ShouldEqual(false); actualTries.ShouldEqual(ExpectedTries); actualFailures.ShouldEqual(ExpectedFailures); }
public virtual bool TryCopyBlobContentStream( string sha, CancellationToken cancellationToken, RequestSource requestSource, Action <Stream, long> writeAction) { RetryWrapper <bool> retrier = new RetryWrapper <bool>(this.GitObjectRequestor.RetryConfig.MaxAttempts, cancellationToken); retrier.OnFailure += errorArgs => { EventMetadata metadata = new EventMetadata(); metadata.Add("sha", sha); metadata.Add("AttemptNumber", errorArgs.TryCount); metadata.Add("WillRetry", errorArgs.WillRetry); if (errorArgs.Error != null) { metadata.Add("Exception", errorArgs.Error.ToString()); } string message = "TryCopyBlobContentStream: Failed to provide blob contents"; if (errorArgs.WillRetry) { this.Tracer.RelatedWarning(metadata, message, Keywords.Telemetry); } else { this.Tracer.RelatedError(metadata, message); } }; RetryWrapper <bool> .InvocationResult invokeResult = retrier.Invoke( tryCount => { bool success = this.Context.Repository.TryCopyBlobContentStream(sha, writeAction); if (success) { return(new RetryWrapper <bool> .CallbackResult(true)); } else { // Pass in false for retryOnFailure because the retrier in this method manages multiple attempts if (this.TryDownloadAndSaveObject(sha, cancellationToken, requestSource, retryOnFailure: false) == DownloadAndSaveObjectResult.Success) { if (this.Context.Repository.TryCopyBlobContentStream(sha, writeAction)) { return(new RetryWrapper <bool> .CallbackResult(true)); } } return(new RetryWrapper <bool> .CallbackResult(error: null, shouldRetry: true)); } }); return(invokeResult.Result); }
public void WillNotRetryForGenericExceptions() { const int MaxTries = 5; RetryWrapper <bool> dut = new RetryWrapper <bool>(MaxTries, CancellationToken.None, exponentialBackoffBase: 0); Assert.Throws <Exception>( () => { RetryWrapper <bool> .InvocationResult output = dut.Invoke(tryCount => { throw new Exception(); }); }); }
public GVFSConfig QueryGVFSConfig() { Uri gvfsConfigEndpoint; string gvfsConfigEndpointString = this.repoUrl + GVFSConstants.Endpoints.GVFSConfig; try { gvfsConfigEndpoint = new Uri(gvfsConfigEndpointString); } catch (UriFormatException e) { EventMetadata metadata = new EventMetadata(); metadata.Add("Method", nameof(this.QueryGVFSConfig)); metadata.Add("ErrorMessage", e); metadata.Add("Url", gvfsConfigEndpointString); this.Tracer.RelatedError(metadata, Keywords.Network); return(null); } long requestId = HttpRequestor.GetNewRequestId(); RetryWrapper <GVFSConfig> retrier = new RetryWrapper <GVFSConfig>(this.RetryConfig.MaxAttempts); retrier.OnFailure += RetryWrapper <GVFSConfig> .StandardErrorHandler(this.Tracer, requestId, "QueryGvfsConfig"); RetryWrapper <GVFSConfig> .InvocationResult output = retrier.Invoke( tryCount => { GitEndPointResponseData response = this.SendRequest(requestId, gvfsConfigEndpoint, HttpMethod.Get, null); if (response.HasErrors) { return(new RetryWrapper <GVFSConfig> .CallbackResult(response.Error, response.ShouldRetry)); } try { using (StreamReader reader = new StreamReader(response.Stream)) { string configString = reader.RetryableReadToEnd(); GVFSConfig config = JsonConvert.DeserializeObject <GVFSConfig>(configString); return(new RetryWrapper <GVFSConfig> .CallbackResult(config)); } } catch (JsonReaderException e) { return(new RetryWrapper <GVFSConfig> .CallbackResult(e, false)); } }); return(output.Result); }
public GVFSConfigResponse QueryGVFSConfig() { Uri gvfsConfigEndpoint; string gvfsConfigEndpointString = this.enlistment.RepoUrl + GVFSConstants.GVFSConfigEndpointSuffix; try { gvfsConfigEndpoint = new Uri(gvfsConfigEndpointString); } catch (UriFormatException e) { EventMetadata metadata = new EventMetadata(); metadata.Add("Method", nameof(this.QueryGVFSConfig)); metadata.Add("ErrorMessage", e); metadata.Add("Url", gvfsConfigEndpointString); this.tracer.RelatedError(metadata, Keywords.Network); return(null); } RetryWrapper <GVFSConfigResponse> retrier = new RetryWrapper <GVFSConfigResponse>(this.MaxRetries); retrier.OnFailure += RetryWrapper <GVFSConfigResponse> .StandardErrorHandler(this.tracer, "QueryGvfsConfig"); RetryWrapper <GVFSConfigResponse> .InvocationResult output = retrier.Invoke( tryCount => { GitEndPointResponseData response = this.SendRequest(gvfsConfigEndpoint, HttpMethod.Get, null); if (response.HasErrors) { return(new RetryWrapper <GVFSConfigResponse> .CallbackResult(response.Error, response.ShouldRetry)); } using (Stream responseStream = response.Stream) using (StreamReader reader = new StreamReader(responseStream)) { try { return(new RetryWrapper <GVFSConfigResponse> .CallbackResult( JsonConvert.DeserializeObject <GVFSConfigResponse>(reader.ReadToEnd()))); } catch (JsonReaderException e) { return(new RetryWrapper <GVFSConfigResponse> .CallbackResult(e, false)); } } }); return(output.Result); }
public virtual List <GitObjectSize> QueryForFileSizes(IEnumerable <string> objectIds) { long requestId = HttpRequestor.GetNewRequestId(); string objectIdsJson = ToJsonList(objectIds); Uri gvfsEndpoint = new Uri(this.enlistment.RepoUrl + GVFSConstants.Endpoints.GVFSSizes); EventMetadata metadata = new EventMetadata(); metadata.Add("RequestId", requestId); int objectIdCount = objectIds.Count(); if (objectIdCount > 10) { metadata.Add("ObjectIdCount", objectIdCount); } else { metadata.Add("ObjectIdJson", objectIdsJson); } this.Tracer.RelatedEvent(EventLevel.Informational, "QueryFileSizes", metadata, Keywords.Network); RetryWrapper <List <GitObjectSize> > retrier = new RetryWrapper <List <GitObjectSize> >(this.RetryConfig.MaxAttempts); retrier.OnFailure += RetryWrapper <List <GitObjectSize> > .StandardErrorHandler(this.Tracer, requestId, "QueryFileSizes"); RetryWrapper <List <GitObjectSize> > .InvocationResult requestTask = retrier.Invoke( tryCount => { GitEndPointResponseData response = this.SendRequest(requestId, gvfsEndpoint, HttpMethod.Post, objectIdsJson); if (response.HasErrors) { return(new RetryWrapper <List <GitObjectSize> > .CallbackResult(response.Error, response.ShouldRetry)); } using (StreamReader reader = new StreamReader(response.Stream)) { string objectSizesString = reader.RetryableReadToEnd(); List <GitObjectSize> objectSizes = JsonConvert.DeserializeObject <List <GitObjectSize> >(objectSizesString); return(new RetryWrapper <List <GitObjectSize> > .CallbackResult(objectSizes)); } }); return(requestTask.Result ?? new List <GitObjectSize>(0)); }
public void WillRetryOnIOException() { const int ExpectedTries = 5; RetryWrapper <bool> dut = new RetryWrapper <bool>(ExpectedTries, CancellationToken.None, exponentialBackoffBase: 0); int actualTries = 0; RetryWrapper <bool> .InvocationResult output = dut.Invoke( tryCount => { actualTries++; throw new IOException(); }); output.Succeeded.ShouldEqual(false); actualTries.ShouldEqual(ExpectedTries); }
public virtual GitRefs QueryInfoRefs(string branch) { long requestId = HttpRequestor.GetNewRequestId(); Uri infoRefsEndpoint; try { infoRefsEndpoint = new Uri(this.enlistment.RepoUrl + GVFSConstants.Endpoints.InfoRefs); } catch (UriFormatException) { return(null); } CancellationToken neverCanceledToken = new CancellationToken(canceled: false); RetryWrapper <GitRefs> retrier = new RetryWrapper <GitRefs>(this.RetryConfig.MaxAttempts, neverCanceledToken); retrier.OnFailure += RetryWrapper <GitRefs> .StandardErrorHandler(this.Tracer, requestId, "QueryInfoRefs"); RetryWrapper <GitRefs> .InvocationResult output = retrier.Invoke( tryCount => { GitEndPointResponseData response = this.SendRequest( requestId, infoRefsEndpoint, HttpMethod.Get, requestContent: null, cancellationToken: neverCanceledToken); if (response.HasErrors) { return(new RetryWrapper <GitRefs> .CallbackResult(response.Error, response.ShouldRetry)); } using (StreamReader reader = new StreamReader(response.Stream)) { List <string> infoRefsResponse = reader.RetryableReadAllLines(); return(new RetryWrapper <GitRefs> .CallbackResult(new GitRefs(infoRefsResponse, branch))); } }); return(output.Result); }
public bool TryCopyBlobContentStream(string sha, Action <Stream, long> writeAction) { RetryWrapper <bool> retrier = new RetryWrapper <bool>(this.GitObjectRequestor.RetryConfig.MaxAttempts); retrier.OnFailure += errorArgs => { EventMetadata metadata = new EventMetadata(); metadata.Add("sha", sha); metadata.Add("AttemptNumber", errorArgs.TryCount); metadata.Add("WillRetry", errorArgs.WillRetry); metadata.Add("ErrorMessage", "TryCopyBlobContentStream: Failed to provide blob contents"); this.Tracer.RelatedError(metadata); }; string firstTwoShaDigits = sha.Substring(0, 2); string remainingShaDigits = sha.Substring(2); RetryWrapper <bool> .InvocationResult invokeResult = retrier.Invoke( tryCount => { bool success = this.Context.Repository.TryCopyBlobContentStream(sha, writeAction); if (success) { return(new RetryWrapper <bool> .CallbackResult(true)); } else { // Pass in 1 for maxAttempts because the retrier in this method manages multiple attempts if (this.TryDownloadAndSaveObject(firstTwoShaDigits, remainingShaDigits, maxAttempts: 1)) { if (this.Context.Repository.TryCopyBlobContentStream(sha, writeAction)) { return(new RetryWrapper <bool> .CallbackResult(true)); } } return(new RetryWrapper <bool> .CallbackResult(error: null, shouldRetry: true)); } }); return(invokeResult.Result); }
public void WillNotMakeAnyAttemptWhenInitiallyCanceled() { const int MaxTries = 5; int actualTries = 0; RetryWrapper <bool> dut = new RetryWrapper <bool>(MaxTries, new CancellationToken(canceled: true), exponentialBackoffBase: 0); Assert.Throws <OperationCanceledException>( () => { RetryWrapper <bool> .InvocationResult output = dut.Invoke(tryCount => { ++actualTries; return(new RetryWrapper <bool> .CallbackResult(true)); }); }); actualTries.ShouldEqual(0); }
public void OnFailureIsCalledWhenEventHandlerAttached() { const int MaxTries = 5; const int ExpectedFailures = 5; RetryWrapper <bool> dut = new RetryWrapper <bool>(MaxTries, CancellationToken.None, exponentialBackoffBase: 0); int actualFailures = 0; dut.OnFailure += errorArgs => actualFailures++; RetryWrapper <bool> .InvocationResult output = dut.Invoke( tryCount => { throw new IOException(); }); output.Succeeded.ShouldEqual(false); actualFailures.ShouldEqual(ExpectedFailures); }
public virtual RetryWrapper <GitObjectTaskResult> .InvocationResult TrySendProtocolRequest( long requestId, Func <int, GitEndPointResponseData, RetryWrapper <GitObjectTaskResult> .CallbackResult> onSuccess, Action <RetryWrapper <GitObjectTaskResult> .ErrorEventArgs> onFailure, HttpMethod method, Func <Uri> endPointGenerator, Func <string> requestBodyGenerator, CancellationToken cancellationToken, MediaTypeWithQualityHeaderValue acceptType = null, bool retryOnFailure = true) { RetryWrapper <GitObjectTaskResult> retrier = new RetryWrapper <GitObjectTaskResult>( retryOnFailure ? this.RetryConfig.MaxAttempts : 1, cancellationToken); if (onFailure != null) { retrier.OnFailure += onFailure; } return(retrier.Invoke( tryCount => { using (GitEndPointResponseData response = this.SendRequest( requestId, endPointGenerator(), method, requestBodyGenerator(), cancellationToken, acceptType)) { if (response.HasErrors) { return new RetryWrapper <GitObjectTaskResult> .CallbackResult(response.Error, response.ShouldRetry, new GitObjectTaskResult(response.StatusCode)); } return onSuccess(tryCount, response); } })); }
public virtual GitRefs QueryInfoRefs(string branch) { long requestId = HttpRequestor.GetNewRequestId(); Uri infoRefsEndpoint; if (!this.TryCreateRepoEndpointUri(this.enlistment.RepoUrl, ScalarConstants.Endpoints.InfoRefs, out infoRefsEndpoint, out _)) { return(null); } RetryWrapper <GitRefs> retrier = new RetryWrapper <GitRefs>(this.RetryConfig.MaxAttempts, CancellationToken.None); retrier.OnFailure += RetryWrapper <GitRefs> .StandardErrorHandler(this.Tracer, requestId, "QueryInfoRefs"); RetryWrapper <GitRefs> .InvocationResult output = retrier.Invoke( tryCount => { using (GitEndPointResponseData response = this.SendRequest( requestId, infoRefsEndpoint, HttpMethod.Get, requestContent: null, cancellationToken: CancellationToken.None)) { if (response.HasErrors) { return(new RetryWrapper <GitRefs> .CallbackResult(response.Error, response.ShouldRetry)); } List <string> infoRefsResponse = response.RetryableReadAllLines(); return(new RetryWrapper <GitRefs> .CallbackResult(new GitRefs(infoRefsResponse, branch))); } }); return(output.Result); }
public bool TryQueryRepoInfo(bool logErrors, out VstsInfoData vstsInfo, out string errorMessage) { Uri repoInfoEndpoint; if (!this.TryCreateRepoEndpointUri(this.repoUrl, ScalarConstants.Endpoints.RepoInfo, out repoInfoEndpoint, out errorMessage)) { vstsInfo = null; return(false); } long requestId = HttpRequestor.GetNewRequestId(); RetryWrapper <VstsInfoData> retrier = new RetryWrapper <VstsInfoData>(this.RetryConfig.MaxAttempts, CancellationToken.None); retrier.OnFailure += RetryWrapper <VstsInfoData> .StandardErrorHandler( this.Tracer, requestId, "QueryVstsInfo", forceLogAsWarning : true); // Not all servers support /vsts/info RetryWrapper <VstsInfoData> .InvocationResult output = retrier.Invoke( tryCount => { using (GitEndPointResponseData response = this.SendRequest( requestId, repoInfoEndpoint, HttpMethod.Get, requestContent: null, cancellationToken: CancellationToken.None)) { if (response.HasErrors) { return(new RetryWrapper <VstsInfoData> .CallbackResult(response.Error, response.ShouldRetry)); } try { string configString = response.RetryableReadToEnd(); VstsInfoData vstsInfoData = JsonConvert.DeserializeObject <VstsInfoData>( configString, new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Ignore }); return(new RetryWrapper <VstsInfoData> .CallbackResult(vstsInfoData)); } catch (JsonReaderException e) { return(new RetryWrapper <VstsInfoData> .CallbackResult(e, shouldRetry: false)); } } }); if (output.Succeeded) { vstsInfo = output.Result; errorMessage = null; return(true); } GitObjectsHttpException httpException = output.Error as GitObjectsHttpException; HttpStatusCode? httpStatusCode = httpException?.StatusCode; vstsInfo = null; EventMetadata metadata = new EventMetadata(); metadata.Add(nameof(httpStatusCode), httpStatusCode.ToString()); metadata.Add(nameof(this.IsAnonymous), this.IsAnonymous); if (httpStatusCode == HttpStatusCode.NotFound || (httpStatusCode == HttpStatusCode.Unauthorized && this.IsAnonymous)) { errorMessage = null; this.Tracer.RelatedEvent( EventLevel.Informational, $"{nameof(this.TryQueryRepoInfo)}_NoVstsInfo", metadata); // These failures are OK because not all servers support /vsts/info return(true); } metadata.Add("Exception", output.Error.ToString()); this.Tracer.RelatedError(metadata, $"{nameof(this.TryQueryRepoInfo)} failed"); errorMessage = output.Error.Message; return(false); }
public bool TryQueryGVFSConfig(bool logErrors, out ServerGVFSConfig serverGVFSConfig, out HttpStatusCode?httpStatus) { serverGVFSConfig = null; httpStatus = null; Uri gvfsConfigEndpoint; string gvfsConfigEndpointString = this.repoUrl + GVFSConstants.Endpoints.GVFSConfig; try { gvfsConfigEndpoint = new Uri(gvfsConfigEndpointString); } catch (UriFormatException e) { EventMetadata metadata = new EventMetadata(); metadata.Add("Method", nameof(this.TryQueryGVFSConfig)); metadata.Add("Exception", e.ToString()); metadata.Add("Url", gvfsConfigEndpointString); this.Tracer.RelatedError(metadata, "UriFormatException when constructing Uri", Keywords.Network); return(false); } long requestId = HttpRequestor.GetNewRequestId(); RetryWrapper <ServerGVFSConfig> retrier = new RetryWrapper <ServerGVFSConfig>(this.RetryConfig.MaxAttempts, CancellationToken.None); if (logErrors) { retrier.OnFailure += RetryWrapper <ServerGVFSConfig> .StandardErrorHandler(this.Tracer, requestId, "QueryGvfsConfig"); } RetryWrapper <ServerGVFSConfig> .InvocationResult output = retrier.Invoke( tryCount => { using (GitEndPointResponseData response = this.SendRequest( requestId, gvfsConfigEndpoint, HttpMethod.Get, requestContent: null, cancellationToken: CancellationToken.None)) { if (response.HasErrors) { return(new RetryWrapper <ServerGVFSConfig> .CallbackResult(response.Error, response.ShouldRetry)); } try { string configString = response.RetryableReadToEnd(); ServerGVFSConfig config = JsonConvert.DeserializeObject <ServerGVFSConfig>(configString); return(new RetryWrapper <ServerGVFSConfig> .CallbackResult(config)); } catch (JsonReaderException e) { return(new RetryWrapper <ServerGVFSConfig> .CallbackResult(e, shouldRetry: false)); } } }); if (output.Succeeded) { serverGVFSConfig = output.Result; httpStatus = HttpStatusCode.OK; return(true); } GitObjectsHttpException httpException = output.Error as GitObjectsHttpException; if (httpException != null) { httpStatus = httpException.StatusCode; } return(false); }
public virtual List <GitObjectSize> QueryForFileSizes(IEnumerable <string> objectIds, CancellationToken cancellationToken) { long requestId = HttpRequestor.GetNewRequestId(); string objectIdsJson = ToJsonList(objectIds); Uri cacheServerEndpoint = new Uri(this.CacheServer.SizesEndpointUrl); Uri originEndpoint = new Uri(this.enlistment.RepoUrl + GVFSConstants.Endpoints.GVFSSizes); EventMetadata metadata = new EventMetadata(); metadata.Add("RequestId", requestId); int objectIdCount = objectIds.Count(); if (objectIdCount > 10) { metadata.Add("ObjectIdCount", objectIdCount); } else { metadata.Add("ObjectIdJson", objectIdsJson); } this.Tracer.RelatedEvent(EventLevel.Informational, "QueryFileSizes", metadata, Keywords.Network); RetryWrapper <List <GitObjectSize> > retrier = new RetryWrapper <List <GitObjectSize> >(this.RetryConfig.MaxAttempts, cancellationToken); retrier.OnFailure += RetryWrapper <List <GitObjectSize> > .StandardErrorHandler(this.Tracer, requestId, "QueryFileSizes"); RetryWrapper <List <GitObjectSize> > .InvocationResult requestTask = retrier.Invoke( tryCount => { Uri gvfsEndpoint; if (this.nextCacheServerAttemptTime < DateTime.Now) { gvfsEndpoint = cacheServerEndpoint; } else { gvfsEndpoint = originEndpoint; } using (GitEndPointResponseData response = this.SendRequest(requestId, gvfsEndpoint, HttpMethod.Post, objectIdsJson, cancellationToken)) { if (response.StatusCode == HttpStatusCode.NotFound) { this.nextCacheServerAttemptTime = DateTime.Now.AddDays(1); return(new RetryWrapper <List <GitObjectSize> > .CallbackResult(response.Error, true)); } if (response.HasErrors) { return(new RetryWrapper <List <GitObjectSize> > .CallbackResult(response.Error, response.ShouldRetry)); } string objectSizesString = response.RetryableReadToEnd(); List <GitObjectSize> objectSizes = JsonConvert.DeserializeObject <List <GitObjectSize> >(objectSizesString); return(new RetryWrapper <List <GitObjectSize> > .CallbackResult(objectSizes)); } }); return(requestTask.Result ?? new List <GitObjectSize>(0)); }
public bool TryQueryScalarConfig(bool logErrors, out ServerScalarConfig serverScalarConfig, out HttpStatusCode?httpStatus, out string errorMessage) { Uri scalarConfigEndpoint; if (!this.TryCreateRepoEndpointUri(this.repoUrl, ScalarConstants.Endpoints.ScalarConfig, out scalarConfigEndpoint, out errorMessage)) { serverScalarConfig = null; httpStatus = null; return(false); } long requestId = HttpRequestor.GetNewRequestId(); RetryWrapper <ServerScalarConfig> retrier = new RetryWrapper <ServerScalarConfig>(this.RetryConfig.MaxAttempts, CancellationToken.None); if (logErrors) { retrier.OnFailure += RetryWrapper <ServerScalarConfig> .StandardErrorHandler(this.Tracer, requestId, "QueryGvfsConfig"); } RetryWrapper <ServerScalarConfig> .InvocationResult output = retrier.Invoke( tryCount => { using (GitEndPointResponseData response = this.SendRequest( requestId, scalarConfigEndpoint, HttpMethod.Get, requestContent: null, cancellationToken: CancellationToken.None)) { if (response.HasErrors) { return(new RetryWrapper <ServerScalarConfig> .CallbackResult(response.Error, response.ShouldRetry)); } try { string configString = response.RetryableReadToEnd(); ServerScalarConfig config = JsonConvert.DeserializeObject <ServerScalarConfig>(configString); return(new RetryWrapper <ServerScalarConfig> .CallbackResult(config)); } catch (JsonReaderException e) { return(new RetryWrapper <ServerScalarConfig> .CallbackResult(e, shouldRetry: false)); } } }); if (output.Succeeded) { serverScalarConfig = output.Result; httpStatus = HttpStatusCode.OK; return(true); } httpStatus = null; GitObjectsHttpException httpException = output.Error as GitObjectsHttpException; if (httpException != null) { httpStatus = httpException.StatusCode; } errorMessage = output.Error.Message; if (logErrors) { this.Tracer.RelatedError( new EventMetadata { { "Exception", output.Error.ToString() } }, $"{nameof(this.TryQueryScalarConfig)} failed"); } serverScalarConfig = null; return(false); }
public bool TryQueryGVFSConfig(out GVFSConfig gvfsConfig) { gvfsConfig = null; Uri gvfsConfigEndpoint; string gvfsConfigEndpointString = this.repoUrl + GVFSConstants.Endpoints.GVFSConfig; try { gvfsConfigEndpoint = new Uri(gvfsConfigEndpointString); } catch (UriFormatException e) { EventMetadata metadata = new EventMetadata(); metadata.Add("Method", nameof(this.TryQueryGVFSConfig)); metadata.Add("Exception", e.ToString()); metadata.Add("Url", gvfsConfigEndpointString); this.Tracer.RelatedError(metadata, "UriFormatException when constructing Uri", Keywords.Network); return(false); } CancellationToken neverCanceledToken = new CancellationToken(canceled: false); long requestId = HttpRequestor.GetNewRequestId(); RetryWrapper <GVFSConfig> retrier = new RetryWrapper <GVFSConfig>(this.RetryConfig.MaxAttempts, neverCanceledToken); retrier.OnFailure += RetryWrapper <GVFSConfig> .StandardErrorHandler(this.Tracer, requestId, "QueryGvfsConfig"); RetryWrapper <GVFSConfig> .InvocationResult output = retrier.Invoke( tryCount => { GitEndPointResponseData response = this.SendRequest( requestId, gvfsConfigEndpoint, HttpMethod.Get, requestContent: null, cancellationToken: neverCanceledToken); if (response.HasErrors) { return(new RetryWrapper <GVFSConfig> .CallbackResult(response.Error, response.ShouldRetry)); } try { using (StreamReader reader = new StreamReader(response.Stream)) { string configString = reader.RetryableReadToEnd(); GVFSConfig config = JsonConvert.DeserializeObject <GVFSConfig>(configString); return(new RetryWrapper <GVFSConfig> .CallbackResult(config)); } } catch (JsonReaderException e) { return(new RetryWrapper <GVFSConfig> .CallbackResult(e, false)); } }); if (output.Succeeded) { gvfsConfig = output.Result; return(true); } return(false); }