Browse Source

closes #3811

pull/3721/head^2
Alper Ebicoglu 6 years ago
parent
commit
89361480ed
  1. 56
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClient.cs
  2. 39
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs
  3. 97
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs

56
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClient.cs

@ -1,9 +1,15 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using IdentityModel.Client;
using Polly;
using Polly.Extensions.Http;
using Volo.Abp.Cli.Auth;
using Microsoft.Extensions.Logging;
namespace Volo.Abp.Cli.Http
{
@ -41,5 +47,55 @@ namespace Volo.Abp.Cli.Http
client.SetBearerToken(accessToken);
}
}
public async Task<HttpResponseMessage> GetHttpResponseMessageWithRetryAsync<T>
(
string url,
CancellationToken? cancellationToken = null,
ILogger<T> logger = null,
IEnumerable<TimeSpan> sleepDurations = null
)
{
if (sleepDurations == null)
{
sleepDurations = new[]
{
TimeSpan.FromSeconds(2),
TimeSpan.FromSeconds(4),
TimeSpan.FromSeconds(7)
};
}
if (!cancellationToken.HasValue)
{
cancellationToken = CancellationToken.None;
}
return await HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => !msg.IsSuccessStatusCode)
.WaitAndRetryAsync(sleepDurations,
(responseMessage, timeSpan, retryCount, context) =>
{
if (responseMessage.Exception != null)
{
string httpErrorCode = responseMessage.Result == null ?
httpErrorCode = string.Empty :
"HTTP-" + (int)responseMessage.Result.StatusCode + ", ";
logger?.LogWarning(
$"{retryCount}. HTTP request attempt failed to {url} with an error: {httpErrorCode}{responseMessage.Exception.Message}. " +
$"Waiting {timeSpan.TotalSeconds} secs for the next try...");
}
else if (responseMessage.Result != null)
{
logger?.LogWarning(
$"{retryCount}. HTTP request attempt failed to {url} with an error: {(int)responseMessage.Result.StatusCode}-{responseMessage.Result.ReasonPhrase}. " +
$"Waiting {timeSpan.TotalSeconds} secs for the next try...");
}
})
.ExecuteAsync(async () => await this.GetAsync(url, cancellationToken.Value));
}
}
}

39
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs

@ -13,6 +13,7 @@ using Volo.Abp.Cli.Http;
using Volo.Abp.Cli.ProjectBuilding;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Json;
using Volo.Abp.Threading;
namespace Volo.Abp.Cli.Licensing
{
@ -20,14 +21,21 @@ namespace Volo.Abp.Cli.Licensing
{
protected IJsonSerializer JsonSerializer { get; }
protected IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; }
protected ICancellationTokenProvider CancellationTokenProvider { get; }
private readonly ILogger<AbpIoApiKeyService> _logger;
private DeveloperApiKeyResult _apiKeyResult = null;
public AbpIoApiKeyService(IJsonSerializer jsonSerializer, IRemoteServiceExceptionHandler remoteServiceExceptionHandler, ILogger<AbpIoApiKeyService> logger)
public AbpIoApiKeyService(
IJsonSerializer jsonSerializer,
ICancellationTokenProvider cancellationTokenProvider,
IRemoteServiceExceptionHandler remoteServiceExceptionHandler,
ILogger<AbpIoApiKeyService> logger)
{
JsonSerializer = jsonSerializer;
RemoteServiceExceptionHandler = remoteServiceExceptionHandler;
_logger = logger;
CancellationTokenProvider = cancellationTokenProvider;
}
public async Task<DeveloperApiKeyResult> GetApiKeyOrNullAsync(bool invalidateCache = false)
@ -51,31 +59,10 @@ namespace Volo.Abp.Cli.Licensing
using (var client = new CliHttpClient())
{
var response = await HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => !msg.IsSuccessStatusCode)
.WaitAndRetryAsync(new[]
{
TimeSpan.FromSeconds(1),
TimeSpan.FromSeconds(3),
TimeSpan.FromSeconds(7)
},
(responseMessage, timeSpan, retryCount, context) =>
{
if (responseMessage.Exception != null)
{
_logger.LogWarning(
$"{retryCount}. request attempt failed to {url} with an error: \"{responseMessage.Exception.Message}\". " +
$"Waiting {timeSpan.TotalSeconds} secs for the next try...");
}
else if (responseMessage.Result != null)
{
_logger.LogWarning(
$"{retryCount}. request attempt failed {url} with {(int)responseMessage.Result.StatusCode}-{responseMessage.Result.ReasonPhrase}. " +
$"Waiting {timeSpan.TotalSeconds} secs for the next try...");
}
})
.ExecuteAsync(async () => await client.GetAsync(url));
var response = await client.GetHttpResponseMessageWithRetryAsync(
url: url,
cancellationToken: CancellationTokenProvider.Token,
logger: _logger);
if (!response.IsSuccessStatusCode)
{

97
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs

@ -1,16 +1,10 @@
using Newtonsoft.Json;
using NuGet.Versioning;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Polly;
using Polly.Extensions.Http;
using Volo.Abp.Cli.Auth;
using Volo.Abp.Cli.Http;
using Volo.Abp.Cli.Licensing;
@ -29,6 +23,8 @@ namespace Volo.Abp.Cli.NuGet
protected ICancellationTokenProvider CancellationTokenProvider { get; }
protected IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; }
private readonly IApiKeyService _apiKeyService;
private List<string> _proPackageList;
private DeveloperApiKeyResult _apiKeyResult;
public NuGetService(
IJsonSerializer jsonSerializer,
@ -45,20 +41,20 @@ namespace Volo.Abp.Cli.NuGet
public async Task<SemanticVersion> GetLatestVersionOrNullAsync(string packageId, bool includePreviews = false, bool includeNightly = false)
{
List<string> proPackageList = null;
if (AuthService.IsLoggedIn())
{
proPackageList = await GetProPackageListAsync();
if (_proPackageList == null)
{
_proPackageList = await GetProPackageListAsync();
}
}
string url;
if (includeNightly)
{
url =
$"https://www.myget.org/F/abp-nightly/api/v3/flatcontainer/{packageId.ToLowerInvariant()}/index.json";
url = $"https://www.myget.org/F/abp-nightly/api/v3/flatcontainer/{packageId.ToLowerInvariant()}/index.json";
}
else if (proPackageList?.Contains(packageId) ?? false)
else if (_proPackageList?.Contains(packageId) ?? false)
{
url = await GetNuGetUrlForCommercialPackage(packageId);
}
@ -67,15 +63,13 @@ namespace Volo.Abp.Cli.NuGet
url = $"https://api.nuget.org/v3-flatcontainer/{packageId.ToLowerInvariant()}/index.json";
}
using (var client = new CliHttpClient(setBearerToken: false))
{
var responseMessage = await GetHttpResponseMessageWithRetryAsync(client, url);
if (!responseMessage.IsSuccessStatusCode)
{
throw new Exception($"ERROR: Remote server returns '{responseMessage.StatusCode}'");
}
var responseMessage = await client.GetHttpResponseMessageWithRetryAsync(
url,
cancellationToken: CancellationTokenProvider.Token,
logger: Logger
);
await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage);
@ -98,62 +92,41 @@ namespace Volo.Abp.Cli.NuGet
private async Task<string> GetNuGetUrlForCommercialPackage(string packageId)
{
var apiKeyResult = await _apiKeyService.GetApiKeyOrNullAsync();
return CliUrls.GetNuGetPackageInfoUrl(apiKeyResult.ApiKey, packageId);
}
if (_apiKeyResult == null)
{
_apiKeyResult = await _apiKeyService.GetApiKeyOrNullAsync();
}
private async Task<HttpResponseMessage> GetHttpResponseMessageWithRetryAsync(HttpClient client, string url)
{
return await HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => !msg.IsSuccessStatusCode)
.WaitAndRetryAsync(new[]
{
TimeSpan.FromSeconds(2),
TimeSpan.FromSeconds(4),
TimeSpan.FromSeconds(7)
},
(responseMessage, timeSpan, retryCount, context) =>
{
if (responseMessage.Exception != null)
{
Logger.LogWarning(
$"{retryCount}. HTTP request attempt failed to {url} with an error: HTTP {(int)responseMessage.Result.StatusCode}-{responseMessage.Exception.Message}. " +
$"Waiting {timeSpan.TotalSeconds} secs for the next try...");
}
else if (responseMessage.Result != null)
{
Logger.LogWarning(
$"{retryCount}. HTTP request attempt failed to {url} with an error: {(int)responseMessage.Result.StatusCode}-{responseMessage.Result.ReasonPhrase}. " +
$"Waiting {timeSpan.TotalSeconds} secs for the next try...");
}
})
.ExecuteAsync(async () => await client.GetAsync(url, CancellationTokenProvider.Token));
return CliUrls.GetNuGetPackageInfoUrl(_apiKeyResult.ApiKey, packageId);
}
private async Task<List<string>> GetProPackageListAsync()
{
using var client = new CliHttpClient();
var responseMessage = await client.GetAsync(
$"{CliUrls.WwwAbpIo}api/app/nugetPackage/proPackageNames",
CancellationTokenProvider.Token
var url = $"{CliUrls.WwwAbpIo}api/app/nugetPackage/proPackageNames";
var responseMessage = await client.GetHttpResponseMessageWithRetryAsync(
url: url,
cancellationToken: CancellationTokenProvider.Token,
logger: Logger
);
if (!responseMessage.IsSuccessStatusCode)
if (responseMessage.IsSuccessStatusCode)
{
var exceptionMessage = "Remote server returns '" + (int)responseMessage.StatusCode + "-" + responseMessage.ReasonPhrase + "'. ";
var remoteServiceErrorMessage = await RemoteServiceExceptionHandler.GetAbpRemoteServiceErrorAsync(responseMessage);
return JsonSerializer.Deserialize<List<string>>(await responseMessage.Content.ReadAsStringAsync());
}
if (remoteServiceErrorMessage != null)
{
exceptionMessage += remoteServiceErrorMessage;
}
Logger.LogInformation(exceptionMessage);
return null;
var exceptionMessage = "Remote server returns '" + (int)responseMessage.StatusCode + "-" + responseMessage.ReasonPhrase + "'. ";
var remoteServiceErrorMessage = await RemoteServiceExceptionHandler.GetAbpRemoteServiceErrorAsync(responseMessage);
if (remoteServiceErrorMessage != null)
{
exceptionMessage += remoteServiceErrorMessage;
}
return JsonSerializer.Deserialize<List<string>>(await responseMessage.Content.ReadAsStringAsync());
Logger.LogError(exceptionMessage);
return null;
}
public class NuGetVersionResultDto

Loading…
Cancel
Save