From 3b1d59a6a56ee6d5378adad19048c1276ace523a Mon Sep 17 00:00:00 2001 From: heqianwang <158102624+heqianwang@users.noreply.github.com> Date: Fri, 24 May 2024 16:22:29 -0400 Subject: [PATCH] [IDP-1484] Add logging and retry for swagger OpenAPI spec generation (#55) * [IDP-1484] Add logging and retry for swagger OpenAPI spec generation * remove comment * Remove other comments * Retry twice for a total of 3 executions * Adjusting retry * Address retry logic and use shorter cancellationtoken * break instead of using extra bool --- .../GenerateContractProcess.cs | 3 ++ .../SwaggerManager.cs | 44 +++++++++++++------ 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/Workleap.OpenApi.MSBuild/GenerateContractProcess.cs b/src/Workleap.OpenApi.MSBuild/GenerateContractProcess.cs index 8bc74b0..42ca8c7 100644 --- a/src/Workleap.OpenApi.MSBuild/GenerateContractProcess.cs +++ b/src/Workleap.OpenApi.MSBuild/GenerateContractProcess.cs @@ -1,3 +1,5 @@ +using Microsoft.Build.Framework; + namespace Workleap.OpenApi.MSBuild; /// @@ -70,5 +72,6 @@ private async Task InstallDependencies( } await Task.WhenAll(installationTasks); + this._loggerWrapper.LogMessage("Finished installing OpenAPI dependencies.", MessageImportance.High); } } \ No newline at end of file diff --git a/src/Workleap.OpenApi.MSBuild/SwaggerManager.cs b/src/Workleap.OpenApi.MSBuild/SwaggerManager.cs index c4253d8..23dacd2 100644 --- a/src/Workleap.OpenApi.MSBuild/SwaggerManager.cs +++ b/src/Workleap.OpenApi.MSBuild/SwaggerManager.cs @@ -6,6 +6,7 @@ namespace Workleap.OpenApi.MSBuild; internal sealed class SwaggerManager : ISwaggerManager { private const string SwaggerVersion = "6.5.0"; + private const int MaxRetryCount = 3; private readonly IProcessWrapper _processWrapper; private readonly ILoggerWrapper _loggerWrapper; private readonly string _openApiWebApiAssemblyPath; @@ -46,29 +47,28 @@ public async Task InstallSwaggerCliAsync(CancellationToken cancellationToken) return; } - var retryCount = 0; - while (retryCount < 2) + for (var retryCount = 0; retryCount < MaxRetryCount; retryCount++) { var result = await this._processWrapper.RunProcessAsync( "dotnet", ["tool", "update", "Swashbuckle.AspNetCore.Cli", "--ignore-failed-sources", "--tool-path", this._swaggerDirectory, "--configfile", Path.Combine(this._openApiToolsDirectoryPath, "nuget.config"), "--version", SwaggerVersion], cancellationToken); - if (result.ExitCode != 0 && retryCount != 1) + var isLastRetry = retryCount == MaxRetryCount - 1; + if (result.ExitCode != 0) { + if (isLastRetry) + { + throw new OpenApiTaskFailedException("Swashbuckle CLI could not be installed."); + } + this._loggerWrapper.LogMessage(result.StandardOutput, MessageImportance.High); this._loggerWrapper.LogWarning(result.StandardError); this._loggerWrapper.LogWarning("Swashbuckle download failed. Retrying once more..."); - retryCount++; continue; } - if (retryCount == 1 && result.ExitCode != 0) - { - throw new OpenApiTaskFailedException("Swashbuckle CLI could not be installed."); - } - break; } } @@ -76,13 +76,29 @@ public async Task InstallSwaggerCliAsync(CancellationToken cancellationToken) public async Task GenerateOpenApiSpecAsync(string swaggerExePath, string outputOpenApiSpecPath, string documentName, CancellationToken cancellationToken) { var envVars = new Dictionary() { { "DOTNET_ROLL_FORWARD", "LatestMajor" } }; - var result = await this._processWrapper.RunProcessAsync(swaggerExePath, ["tofile", "--output", outputOpenApiSpecPath, "--yaml", this._openApiWebApiAssemblyPath, documentName], cancellationToken: cancellationToken, envVars: envVars); - this._loggerWrapper.LogMessage(result.StandardOutput, MessageImportance.High); + var swaggerCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); + swaggerCancellationToken.CancelAfter(TimeSpan.FromMinutes(1)); - if (result.ExitCode != 0) + var willRetry = true; + for (var retryCount = 0; retryCount < MaxRetryCount; retryCount++) { - this._loggerWrapper.LogWarning(result.StandardError); - throw new OpenApiTaskFailedException($"OpenApi file {outputOpenApiSpecPath} could not be created."); + var result = await this._processWrapper.RunProcessAsync(swaggerExePath, ["tofile", "--output", outputOpenApiSpecPath, "--yaml", this._openApiWebApiAssemblyPath, documentName], cancellationToken: swaggerCancellationToken.Token, envVars: envVars); + + var isLastRetry = retryCount == MaxRetryCount - 1; + if (result.ExitCode != 0) + { + if (isLastRetry) + { + throw new OpenApiTaskFailedException($"OpenApi file for {outputOpenApiSpecPath} could not be generated."); + } + + this._loggerWrapper.LogMessage(result.StandardOutput, MessageImportance.High); + this._loggerWrapper.LogWarning(result.StandardError); + this._loggerWrapper.LogWarning($"OpenAPI spec generation failed for {outputOpenApiSpecPath}. Retrying again..."); + continue; + } + + break; } return outputOpenApiSpecPath;