Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
            }
        }
Пример #4
0
        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);
            }
        }
Пример #5
0
        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);
                }
            }));
        }
Пример #6
0
        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);
        }
Пример #8
0
        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(); });
            });
        }
Пример #9
0
        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);
        }
Пример #10
0
        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);
        }
Пример #11
0
        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));
        }
Пример #12
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);
        }
Пример #13
0
        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);
        }
Пример #14
0
        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);
        }
Пример #15
0
        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);
        }
Пример #16
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);
        }
Пример #17
0
        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);
        }
Пример #19
0
        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);
        }
Пример #20
0
        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);
        }
Пример #21
0
        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));
        }
Пример #22
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);
        }
Пример #23
0
        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);
        }