From 3da46c012c74ad3d2cdc20dec1049a8afbe08404 Mon Sep 17 00:00:00 2001 From: Michael Simons Date: Thu, 14 Apr 2022 16:20:25 -0500 Subject: [PATCH] Add retry to omnisharp download (#13639) --- .../Config.cs | 1 + .../HttpClientExtensions.cs | 16 +++-- .../OmniSharpTests.cs | 4 +- .../Utilities.cs | 58 +++++++++++++++++++ 4 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/Utilities.cs diff --git a/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/Config.cs b/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/Config.cs index 67b5bfc78..fc077fb19 100644 --- a/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/Config.cs +++ b/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/Config.cs @@ -30,6 +30,7 @@ internal static class Config public static string? SdkTarballPath { get; } = Environment.GetEnvironmentVariable(SdkTarballPathEnv); public static string TargetRid { get; } = Environment.GetEnvironmentVariable(TargetRidEnv) ?? throw new InvalidOperationException($"'{Config.TargetRidEnv}' must be specified"); + public static string TargetArchitecture { get; } = TargetRid.Split('-')[1]; public static bool WarnOnPoisonDiffs { get; } = bool.TryParse(Environment.GetEnvironmentVariable(WarnPoisonDiffsEnv), out bool excludeOnlineTests) && excludeOnlineTests; public static bool WarnOnSdkContentDiffs { get; } = diff --git a/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/HttpClientExtensions.cs b/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/HttpClientExtensions.cs index 77115c981..b0f778fa6 100644 --- a/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/HttpClientExtensions.cs +++ b/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/HttpClientExtensions.cs @@ -6,15 +6,23 @@ using System; using System.IO; using System.Net.Http; using System.Threading.Tasks; +using Xunit.Abstractions; namespace Microsoft.DotNet.SourceBuild.SmokeTests; internal static class HttpClientExtensions { - public static async Task DownloadFileAsync(this HttpClient client, Uri uri, string path) + public static async Task DownloadFileAsync(this HttpClient client, Uri uri, string path, ITestOutputHelper outputHelper) { - using Stream stream = await client.GetStreamAsync(uri); - using FileStream fileStream = new(path, FileMode.OpenOrCreate); - await stream.CopyToAsync(fileStream); + outputHelper.WriteLine($"Downloading {uri}"); + + await Utilities.RetryAsync( + async () => + { + using Stream stream = await client.GetStreamAsync(uri); + using FileStream fileStream = new(path, FileMode.OpenOrCreate); + await stream.CopyToAsync(fileStream); + }, + outputHelper); } } diff --git a/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/OmniSharpTests.cs b/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/OmniSharpTests.cs index 50788019c..56f14043b 100644 --- a/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/OmniSharpTests.cs +++ b/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/OmniSharpTests.cs @@ -60,9 +60,9 @@ public class OmniSharpTests : SmokeTests if (!Directory.Exists(OmniSharpDirectory)) { using HttpClient client = new(); - string omniSharpTarballFile = "omnisharp-linux-x64.tar.gz"; + string omniSharpTarballFile = $"omnisharp-linux-{Config.TargetArchitecture}.tar.gz"; Uri omniSharpTarballUrl = new($"https://github.com/OmniSharp/omnisharp-roslyn/releases/latest/download/{omniSharpTarballFile}"); - await client.DownloadFileAsync(omniSharpTarballUrl, omniSharpTarballFile); + await client.DownloadFileAsync(omniSharpTarballUrl, omniSharpTarballFile, OutputHelper); Directory.CreateDirectory(OmniSharpDirectory); ExecuteHelper.ExecuteProcessValidateExitCode("tar", $"xzf {omniSharpTarballFile} -C {OmniSharpDirectory}", OutputHelper); diff --git a/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/Utilities.cs b/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/Utilities.cs new file mode 100644 index 000000000..d706d3972 --- /dev/null +++ b/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/Utilities.cs @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit.Abstractions; + +namespace Microsoft.DotNet.SourceBuild.SmokeTests; + +public static class Utilities +{ + public static async Task RetryAsync(Func executor, ITestOutputHelper outputHelper) + { + await Utilities.RetryAsync( + async () => + { + try + { + await executor(); + return null; + } + catch (Exception e) + { + return e; + } + }, + outputHelper); + } + + private static async Task RetryAsync(Func> executor, ITestOutputHelper outputHelper) + { + const int maxRetries = 5; + const int waitFactor = 5; + + int retryCount = 0; + + Exception? exception = await executor(); + while (exception != null) + { + retryCount++; + if (retryCount >= maxRetries) + { + throw new InvalidOperationException($"Failed after {retryCount} retries.", exception); + } + + int waitTime = Convert.ToInt32(Math.Pow(waitFactor, retryCount - 1)); + if (outputHelper != null) + { + outputHelper.WriteLine($"Retry {retryCount}/{maxRetries}, retrying in {waitTime} seconds..."); + } + + Thread.Sleep(TimeSpan.FromSeconds(waitTime)); + exception = await executor(); + } + } +}