Browse Source

implement timeout for singleton HttpClient #7618

pull/7619/head
Alper Ebicoglu 6 years ago
parent
commit
fa477b9e47
  1. 8
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClient.cs
  2. 51
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClientFactory.cs
  3. 101
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs
  4. 28
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/MyGetPackageListFinder.cs
  5. 23
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackagesUpdater.cs

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

@ -67,7 +67,12 @@ namespace Volo.Abp.Cli.Http
}; };
} }
cancellationToken ??= CancellationToken.None; if (cancellationToken == null)
{
var cancellationTokenSource = new CancellationTokenSource();
cancellationTokenSource.CancelAfter(DefaultTimeout);
cancellationToken = cancellationTokenSource.Token;
}
return await HttpPolicyExtensions return await HttpPolicyExtensions
.HandleTransientHttpError() .HandleTransientHttpError()
@ -95,5 +100,6 @@ namespace Volo.Abp.Cli.Http
.ExecuteAsync(async () => await this.GetAsync(url, cancellationToken.Value)); .ExecuteAsync(async () => await this.GetAsync(url, cancellationToken.Value));
} }
} }
} }

51
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClientFactory.cs

@ -1,5 +1,7 @@
using System; using System;
using System.Threading;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Threading;
namespace Volo.Abp.Cli.Http namespace Volo.Abp.Cli.Http
{ {
@ -7,32 +9,67 @@ namespace Volo.Abp.Cli.Http
{ {
private static CliHttpClient _authenticatedHttpClient; private static CliHttpClient _authenticatedHttpClient;
private static CliHttpClient _unauthenticatedHttpClient; private static CliHttpClient _unauthenticatedHttpClient;
private readonly ICancellationTokenProvider _cancellationTokenProvider;
public CliHttpClient CreateClient(bool needsAuthentication = true) public CliHttpClientFactory(ICancellationTokenProvider cancellationTokenProvider)
{
_cancellationTokenProvider = cancellationTokenProvider;
}
public CliHttpClient CreateClient(bool needsAuthentication = true, TimeSpan? timeout = null)
{ {
if (needsAuthentication) if (needsAuthentication)
{ {
return CreateAuthenticatedHttpClient(); return CreateAuthenticatedHttpClient(timeout);
} }
return CreateUnAuthenticatedHttpClient(); return CreateUnAuthenticatedHttpClient(timeout);
}
public CancellationToken GetCancellationToken(TimeSpan? timeout = null)
{
if (timeout == null)
{
if (_cancellationTokenProvider == null)
{
var cancellationTokenSource = new CancellationTokenSource();
cancellationTokenSource.CancelAfter(CliHttpClient.DefaultTimeout);
return cancellationTokenSource.Token;
}
else
{
return _cancellationTokenProvider.Token;
}
}
else
{
var cancellationTokenSource = new CancellationTokenSource();
cancellationTokenSource.CancelAfter(Convert.ToInt32(timeout.Value.TotalMilliseconds));
return cancellationTokenSource.Token;
}
} }
private static CliHttpClient CreateAuthenticatedHttpClient() private static CliHttpClient CreateAuthenticatedHttpClient(TimeSpan? timeout = null)
{ {
if (_authenticatedHttpClient == null) if (_authenticatedHttpClient == null)
{ {
_authenticatedHttpClient = new CliHttpClient(setBearerToken: true); _authenticatedHttpClient = new CliHttpClient(setBearerToken: true)
{
Timeout = System.Threading.Timeout.InfiniteTimeSpan
};
} }
return _authenticatedHttpClient; return _authenticatedHttpClient;
} }
private static CliHttpClient CreateUnAuthenticatedHttpClient() private static CliHttpClient CreateUnAuthenticatedHttpClient(TimeSpan? timeout = null)
{ {
if (_unauthenticatedHttpClient == null) if (_unauthenticatedHttpClient == null)
{ {
_unauthenticatedHttpClient = new CliHttpClient(setBearerToken: false); _unauthenticatedHttpClient = new CliHttpClient(setBearerToken: false)
{
Timeout = System.Threading.Timeout.InfiniteTimeSpan
};
} }
return _unauthenticatedHttpClient; return _unauthenticatedHttpClient;

101
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs

@ -9,6 +9,7 @@ using System.Net.Http;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Cli.Http; using Volo.Abp.Cli.Http;
using Volo.Abp.Cli.ProjectBuilding.Templates.App; using Volo.Abp.Cli.ProjectBuilding.Templates.App;
@ -28,22 +29,23 @@ namespace Volo.Abp.Cli.ProjectBuilding
public ILogger<AbpIoSourceCodeStore> Logger { get; set; } public ILogger<AbpIoSourceCodeStore> Logger { get; set; }
protected AbpCliOptions Options { get; } protected AbpCliOptions Options { get; }
protected IJsonSerializer JsonSerializer { get; } protected IJsonSerializer JsonSerializer { get; }
protected IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; } protected IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; }
protected ICancellationTokenProvider CancellationTokenProvider { get; } protected ICancellationTokenProvider CancellationTokenProvider { get; }
private readonly CliHttpClientFactory _cliHttpClientFactory;
public AbpIoSourceCodeStore( public AbpIoSourceCodeStore(
IOptions<AbpCliOptions> options, IOptions<AbpCliOptions> options,
IJsonSerializer jsonSerializer, IJsonSerializer jsonSerializer,
IRemoteServiceExceptionHandler remoteServiceExceptionHandler, IRemoteServiceExceptionHandler remoteServiceExceptionHandler,
ICancellationTokenProvider cancellationTokenProvider) ICancellationTokenProvider cancellationTokenProvider,
CliHttpClientFactory cliHttpClientFactory)
{ {
JsonSerializer = jsonSerializer; JsonSerializer = jsonSerializer;
RemoteServiceExceptionHandler = remoteServiceExceptionHandler; RemoteServiceExceptionHandler = remoteServiceExceptionHandler;
CancellationTokenProvider = cancellationTokenProvider; CancellationTokenProvider = cancellationTokenProvider;
_cliHttpClientFactory = cliHttpClientFactory;
Options = options.Value; Options = options.Value;
Logger = NullLogger<AbpIoSourceCodeStore>.Instance; Logger = NullLogger<AbpIoSourceCodeStore>.Instance;
@ -134,24 +136,17 @@ namespace Volo.Abp.Cli.ProjectBuilding
try try
{ {
using (var client = new CliHttpClient(TimeSpan.FromMinutes(10))) var client = _cliHttpClientFactory.CreateClient();
var stringContent = new StringContent(
JsonSerializer.Serialize(new GetLatestSourceCodeVersionDto { Name = name, IncludePreReleases = includePreReleases }),
Encoding.UTF8,
MimeTypes.Application.Json
);
using (var response = await client.PostAsync(url, stringContent, _cliHttpClientFactory.GetCancellationToken(TimeSpan.FromMinutes(10))))
{ {
var response = await client.PostAsync(
url,
new StringContent(
JsonSerializer.Serialize(
new GetLatestSourceCodeVersionDto { Name = name, IncludePreReleases = includePreReleases }
),
Encoding.UTF8,
MimeTypes.Application.Json
),
CancellationTokenProvider.Token
);
await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response); await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response);
var result = await response.Content.ReadAsStringAsync(); var result = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<GetVersionResultDto>(result).Version; return JsonSerializer.Deserialize<GetVersionResultDto>(result).Version;
} }
} }
@ -164,32 +159,25 @@ namespace Volo.Abp.Cli.ProjectBuilding
private async Task<string> GetTemplateNugetVersionAsync(string name, string type, string version) private async Task<string> GetTemplateNugetVersionAsync(string name, string type, string version)
{ {
var url = $"{CliUrls.WwwAbpIo}api/download/{type}/get-nuget-version/";
try try
{ {
using (var client = new CliHttpClient(TimeSpan.FromMinutes(10))) var url = $"{CliUrls.WwwAbpIo}api/download/{type}/get-nuget-version/";
{ var client = _cliHttpClientFactory.CreateClient();
var response = await client.PostAsync(
url,
new StringContent(
JsonSerializer.Serialize(
new GetTemplateNugetVersionDto { Name = name, Version = version}
),
Encoding.UTF8,
MimeTypes.Application.Json
),
CancellationTokenProvider.Token
);
await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response); var stringContent = new StringContent(
JsonSerializer.Serialize(new GetTemplateNugetVersionDto { Name = name, Version = version }),
Encoding.UTF8,
MimeTypes.Application.Json
);
using (var response = await client.PostAsync(url, stringContent, _cliHttpClientFactory.GetCancellationToken(TimeSpan.FromMinutes(10))))
{
await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response);
var result = await response.Content.ReadAsStringAsync(); var result = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<GetVersionResultDto>(result).Version; return JsonSerializer.Deserialize<GetVersionResultDto>(result).Version;
} }
} }
catch (Exception ex) catch (Exception)
{ {
return null; return null;
} }
@ -203,36 +191,35 @@ namespace Volo.Abp.Cli.ProjectBuilding
try try
{ {
using (var client = new CliHttpClient(TimeSpan.FromMinutes(10))) var client = _cliHttpClientFactory.CreateClient();
{
if (input.TemplateSource.IsNullOrWhiteSpace()) if (input.TemplateSource.IsNullOrWhiteSpace())
{ {
responseMessage = await client.PostAsync( responseMessage = await client.PostAsync(
url, url,
new StringContent(JsonSerializer.Serialize(input), Encoding.UTF8, MimeTypes.Application.Json), new StringContent(JsonSerializer.Serialize(input), Encoding.UTF8, MimeTypes.Application.Json),
CancellationTokenProvider.Token _cliHttpClientFactory.GetCancellationToken(TimeSpan.FromMinutes(10))
); );
} }
else else
{ {
responseMessage = await client.GetAsync(input.TemplateSource, CancellationTokenProvider.Token); responseMessage = await client.GetAsync(input.TemplateSource, _cliHttpClientFactory.GetCancellationToken());
} }
await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage); await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage);
var resultAsBytes = await responseMessage.Content.ReadAsByteArrayAsync();
responseMessage.Dispose();
return await responseMessage.Content.ReadAsByteArrayAsync(); return resultAsBytes;
}
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine("Error occured while downloading source-code from {0} : {1}{2}{3}", Console.WriteLine("Error occured while downloading source-code from {0} : {1}{2}{3}", url, responseMessage?.ToString(), Environment.NewLine, ex.Message);
url, responseMessage?.ToString(), Environment.NewLine, ex.Message);
throw; throw;
} }
} }
private bool IsNetworkSource(string source) private static bool IsNetworkSource(string source)
{ {
return source.ToLower().StartsWith("http"); return source.ToLower().StartsWith("http");
} }

28
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/MyGetPackageListFinder.cs

@ -6,17 +6,23 @@ using Microsoft.Extensions.Logging.Abstractions;
using Newtonsoft.Json; using Newtonsoft.Json;
using Volo.Abp.Cli.Http; using Volo.Abp.Cli.Http;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Threading;
namespace Volo.Abp.Cli.ProjectModification namespace Volo.Abp.Cli.ProjectModification
{ {
public class MyGetPackageListFinder : ISingletonDependency public class MyGetPackageListFinder : ISingletonDependency
{ {
private MyGetApiResponse _response;
public ILogger<MyGetPackageListFinder> Logger { get; set; } public ILogger<MyGetPackageListFinder> Logger { get; set; }
public MyGetPackageListFinder() private MyGetApiResponse _response;
private readonly CliHttpClientFactory _cliHttpClientFactory;
protected ICancellationTokenProvider CancellationTokenProvider { get; }
public MyGetPackageListFinder(CliHttpClientFactory cliHttpClientFactory,
ICancellationTokenProvider cancellationTokenProvider)
{ {
_cliHttpClientFactory = cliHttpClientFactory;
CancellationTokenProvider = cancellationTokenProvider;
Logger = NullLogger<MyGetPackageListFinder>.Instance; Logger = NullLogger<MyGetPackageListFinder>.Instance;
} }
@ -29,18 +35,20 @@ namespace Volo.Abp.Cli.ProjectModification
try try
{ {
using (var client = new CliHttpClient(TimeSpan.FromMinutes(10))) var client = _cliHttpClientFactory.CreateClient();
using (var responseMessage = await client.GetAsync(
$"{CliUrls.WwwAbpIo}api/myget/packages/",
_cliHttpClientFactory.GetCancellationToken(TimeSpan.FromMinutes(10))))
{ {
var responseMessage = await client.GetAsync( _response = JsonConvert.DeserializeObject<MyGetApiResponse>(
$"{CliUrls.WwwAbpIo}api/myget/packages/" Encoding.Default.GetString(await responseMessage.Content.ReadAsByteArrayAsync())
); );
_response = JsonConvert.DeserializeObject<MyGetApiResponse>(Encoding.Default.GetString(await responseMessage.Content.ReadAsByteArrayAsync()));
} }
} }
catch (Exception) catch (Exception ex)
{ {
Logger.LogError("Unable to get latest preview version."); Logger.LogError("Unable to get latest preview version. Error: " + ex.Message);
throw; throw;
} }

23
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackagesUpdater.cs

@ -27,15 +27,18 @@ namespace Volo.Abp.Cli.ProjectModification
private readonly PackageJsonFileFinder _packageJsonFileFinder; private readonly PackageJsonFileFinder _packageJsonFileFinder;
private readonly NpmGlobalPackagesChecker _npmGlobalPackagesChecker; private readonly NpmGlobalPackagesChecker _npmGlobalPackagesChecker;
private readonly Dictionary<string, string> _fileVersionStorage = new Dictionary<string, string>(); private readonly Dictionary<string, string> _fileVersionStorage = new Dictionary<string, string>();
private readonly CliHttpClientFactory _cliHttpClientFactory;
public NpmPackagesUpdater( public NpmPackagesUpdater(
PackageJsonFileFinder packageJsonFileFinder, PackageJsonFileFinder packageJsonFileFinder,
NpmGlobalPackagesChecker npmGlobalPackagesChecker, NpmGlobalPackagesChecker npmGlobalPackagesChecker,
ICancellationTokenProvider cancellationTokenProvider) ICancellationTokenProvider cancellationTokenProvider,
CliHttpClientFactory cliHttpClientFactory)
{ {
_packageJsonFileFinder = packageJsonFileFinder; _packageJsonFileFinder = packageJsonFileFinder;
_npmGlobalPackagesChecker = npmGlobalPackagesChecker; _npmGlobalPackagesChecker = npmGlobalPackagesChecker;
CancellationTokenProvider = cancellationTokenProvider; CancellationTokenProvider = cancellationTokenProvider;
_cliHttpClientFactory = cliHttpClientFactory;
Logger = NullLogger<NpmPackagesUpdater>.Instance; Logger = NullLogger<NpmPackagesUpdater>.Instance;
} }
@ -151,16 +154,14 @@ namespace Volo.Abp.Cli.ProjectModification
{ {
try try
{ {
using (var client = new CliHttpClient(TimeSpan.FromMinutes(1))) var client = _cliHttpClientFactory.CreateClient();
using (var response = await client.GetHttpResponseMessageWithRetryAsync(
url: $"{CliUrls.WwwAbpIo}api/myget/apikey/",
cancellationToken: CancellationTokenProvider.Token,
logger: Logger
))
{ {
using (var response = await client.GetHttpResponseMessageWithRetryAsync( return Encoding.Default.GetString(await response.Content.ReadAsByteArrayAsync());
url: $"{CliUrls.WwwAbpIo}api/myget/apikey/",
cancellationToken: CancellationTokenProvider.Token,
logger: Logger
))
{
return Encoding.Default.GetString(await response.Content.ReadAsByteArrayAsync());
}
} }
} }
catch (Exception) catch (Exception)
@ -356,7 +357,7 @@ namespace Volo.Abp.Cli.ProjectModification
protected virtual string ExtractVersions(string output) protected virtual string ExtractVersions(string output)
{ {
var arrayStart = output.IndexOf('['); var arrayStart = output.IndexOf('[');
return output.Substring(arrayStart, output.IndexOf(']') - arrayStart + 1); return output.Substring(arrayStart, output.IndexOf(']') - arrayStart + 1);
} }
protected virtual bool SpecifiedVersionExists(string version, JProperty package) protected virtual bool SpecifiedVersionExists(string version, JProperty package)

Loading…
Cancel
Save