Browse Source

#1403: Simplify ApiDescriptionCache

pull/1406/head
Halil İbrahim Kalkan 7 years ago
parent
commit
5636dd4fb5
  1. 1
      framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ISingletonDependency.cs
  2. 44
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionCache.cs
  3. 54
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs
  4. 7
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/IApiDescriptionCache.cs
  5. 2
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/IApiDescriptionFinder.cs
  6. 1
      framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IAmbientUnitOfWork.cs

1
framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ISingletonDependency.cs

@ -2,5 +2,6 @@
{
public interface ISingletonDependency
{
}
}

44
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionCache.cs

@ -2,8 +2,6 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Nito.AsyncEx;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Modeling;
@ -12,55 +10,29 @@ namespace Volo.Abp.Http.Client.DynamicProxying
{
public class ApiDescriptionCache : IApiDescriptionCache, ISingletonDependency
{
private readonly IDynamicProxyHttpClientFactory _httpClientFactory;
private readonly Dictionary<string, ApplicationApiDescriptionModel> _cache;
private readonly AsyncLock _asyncLock;
private readonly SemaphoreSlim _semaphoreSlim;
public ApiDescriptionCache(IDynamicProxyHttpClientFactory httpClientFactory)
public ApiDescriptionCache()
{
_httpClientFactory = httpClientFactory;
_cache = new Dictionary<string, ApplicationApiDescriptionModel>();
_asyncLock = new AsyncLock();
_semaphoreSlim = new SemaphoreSlim(1, 1);
}
public async Task<ApplicationApiDescriptionModel> GetAsync(string baseUrl, CancellationToken cancellationToken = default)
public async Task<ApplicationApiDescriptionModel> GetAsync(
string baseUrl,
Func<Task<ApplicationApiDescriptionModel>> factory)
{
using (await _asyncLock.LockAsync(cancellationToken))
using (await _semaphoreSlim.LockAsync())
{
var model = _cache.GetOrDefault(baseUrl);
if (model == null)
{
_cache[baseUrl] = model = await GetFromServerAsync(baseUrl);
_cache[baseUrl] = model = await factory();
}
return model;
}
}
private async Task<ApplicationApiDescriptionModel> GetFromServerAsync(string baseUrl)
{
using (var client = _httpClientFactory.Create())
{
var response = await client.GetAsync(baseUrl.EnsureEndsWith('/') + "api/abp/api-definition");
if (!response.IsSuccessStatusCode)
{
throw new AbpException("Remote service returns error!");
}
var content = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject(
content,
typeof(ApplicationApiDescriptionModel),
new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
return (ApplicationApiDescriptionModel)result;
}
}
}
}

54
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs

@ -2,23 +2,34 @@
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Modeling;
using Volo.Abp.Threading;
namespace Volo.Abp.Http.Client.DynamicProxying
{
public class ApiDescriptionFinder : IApiDescriptionFinder, ISingletonDependency
{
private readonly IApiDescriptionCache _descriptionCache;
public ICancellationTokenProvider CancellationTokenProvider { get; set; }
public ApiDescriptionFinder(IApiDescriptionCache descriptionCache)
protected IDynamicProxyHttpClientFactory HttpClientFactory { get; }
protected IApiDescriptionCache Cache { get; }
public ApiDescriptionFinder(
IApiDescriptionCache cache,
IDynamicProxyHttpClientFactory httpClientFactory)
{
_descriptionCache = descriptionCache;
Cache = cache;
HttpClientFactory = httpClientFactory;
CancellationTokenProvider = NullCancellationTokenProvider.Instance;
}
public async Task<ActionApiDescriptionModel> FindActionAsync(string baseUrl, Type serviceType, MethodInfo method)
{
var apiDescription = await _descriptionCache.GetAsync(baseUrl);
var apiDescription = await GetApiDescriptionAsync(baseUrl);
//TODO: Cache finding?
@ -57,7 +68,40 @@ namespace Volo.Abp.Http.Client.DynamicProxying
}
}
throw new AbpException("Could not found remote action for method: " + method);
throw new AbpException($"Could not found remote action for method: {method} on the URL: {baseUrl}");
}
public virtual async Task<ApplicationApiDescriptionModel> GetApiDescriptionAsync(string baseUrl)
{
return await Cache.GetAsync(baseUrl, () => GetApiDescriptionFromServerAsync(baseUrl));
}
protected virtual async Task<ApplicationApiDescriptionModel> GetApiDescriptionFromServerAsync(string baseUrl)
{
using (var client = HttpClientFactory.Create())
{
var response = await client.GetAsync(
baseUrl.EnsureEndsWith('/') + "api/abp/api-definition",
CancellationTokenProvider.Token
);
if (!response.IsSuccessStatusCode)
{
throw new AbpException("Remote service returns error!");
}
var content = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject(
content,
typeof(ApplicationApiDescriptionModel),
new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
return (ApplicationApiDescriptionModel)result;
}
}
}
}

7
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/IApiDescriptionCache.cs

@ -1,4 +1,4 @@
using System.Threading;
using System;
using System.Threading.Tasks;
using Volo.Abp.Http.Modeling;
@ -6,6 +6,9 @@ namespace Volo.Abp.Http.Client.DynamicProxying
{
public interface IApiDescriptionCache
{
Task<ApplicationApiDescriptionModel> GetAsync(string baseUrl, CancellationToken cancellationToken = default);
Task<ApplicationApiDescriptionModel> GetAsync(
string baseUrl,
Func<Task<ApplicationApiDescriptionModel>> factory
);
}
}

2
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/IApiDescriptionFinder.cs

@ -8,5 +8,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying
public interface IApiDescriptionFinder
{
Task<ActionApiDescriptionModel> FindActionAsync(string baseUrl, Type serviceType, MethodInfo invocationMethod);
Task<ApplicationApiDescriptionModel> GetApiDescriptionAsync(string baseUrl);
}
}

1
framework/src/Volo.Abp.Uow/Volo/Abp/Uow/IAmbientUnitOfWork.cs

@ -2,5 +2,6 @@
{
public interface IAmbientUnitOfWork : IUnitOfWorkAccessor
{
}
}
Loading…
Cancel
Save