Browse Source

Refactored

pull/235/head
Galip Tolga Erdem 3 years ago
parent
commit
f66ad6c5a2
  1. 1
      gateways/web/src/EShopOnAbp.WebGateway/Aggregations/ILocalizationAggregation.cs
  2. 8
      gateways/web/src/EShopOnAbp.WebGateway/Aggregations/Localization/CachedLocalizationService.cs
  3. 25
      gateways/web/src/EShopOnAbp.WebGateway/Aggregations/Localization/RemoteLocalizationService.cs
  4. 56
      gateways/web/src/EShopOnAbp.WebGateway/Aggregations/LocalizationAggregation.cs
  5. 12
      gateways/web/src/EShopOnAbp.WebGateway/ReverseProxyBuilderExtensions.cs

1
gateways/web/src/EShopOnAbp.WebGateway/Aggregations/ILocalizationAggregation.cs

@ -6,6 +6,7 @@ namespace EShopOnAbp.WebGateway.Aggregations;
public interface ILocalizationAggregation : ITransientDependency public interface ILocalizationAggregation : ITransientDependency
{ {
public string LocalizationRouteName { get; }
public string LocalizationEndpoint { get; } public string LocalizationEndpoint { get; }
public Task<ApplicationLocalizationDto> GetLocalizationAsync(LocalizationRequest input); public Task<ApplicationLocalizationDto> GetLocalizationAsync(LocalizationRequest input);
} }

8
gateways/web/src/EShopOnAbp.WebGateway/Aggregations/Localization/CachedLocalizationService.cs

@ -16,18 +16,12 @@ public class CachedLocalizationService : ISingletonDependency
LocalizationDictionary = new ConcurrentDictionary<string, ApplicationLocalizationDto>(StringComparer.OrdinalIgnoreCase); LocalizationDictionary = new ConcurrentDictionary<string, ApplicationLocalizationDto>(StringComparer.OrdinalIgnoreCase);
} }
//TODO:skip url -> Use ServiceName_Culture as cache key
public void AddOrUpdate(string serviceNameWithCulture, ApplicationLocalizationDto localizationInfo) public void AddOrUpdate(string serviceNameWithCulture, ApplicationLocalizationDto localizationInfo)
{ {
LocalizationDictionary.AddOrUpdate(serviceNameWithCulture, localizationInfo, (key, value) => localizationInfo); LocalizationDictionary.AddOrUpdate(serviceNameWithCulture, localizationInfo, (key, value) => localizationInfo);
} }
public ApplicationLocalizationDto Get(string serviceNameWithCulture) public IDictionary<string, ApplicationLocalizationDto> GetLocalizationsFromCacheAsync(string[] serviceNamesWithCulture)
{
return LocalizationDictionary.TryGetValue(serviceNameWithCulture, out var result) ? result : null;
}
public IDictionary<string, ApplicationLocalizationDto> GetMultipleLocalizationsAsync(string[] serviceNamesWithCulture)
{ {
return LocalizationDictionary return LocalizationDictionary
.Where(kv => serviceNamesWithCulture.Contains(kv.Key)) .Where(kv => serviceNamesWithCulture.Contains(kv.Key))

25
gateways/web/src/EShopOnAbp.WebGateway/Aggregations/Localization/RemoteLocalizationService.cs

@ -46,7 +46,7 @@ public class RemoteLocalizationService : IRemoteLocalizationService, ITransientD
completedTasks.Add(completedTask.Key, completedTask.Value); completedTasks.Add(completedTask.Key, completedTask.Value);
completedResult.Add(completedTask.Key, result); completedResult.Add(completedTask.Key, result);
_logger.LogInformation($"Key: {completedTask.Key}, Value: {result}"); _logger.LogInformation($"Localization Key: {completedTask.Key}, Value: {result}");
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -70,23 +70,14 @@ public class RemoteLocalizationService : IRemoteLocalizationService, ITransientD
private async Task<T> MakeRequestAsync<T>(HttpClient httpClient, string url) private async Task<T> MakeRequestAsync<T>(HttpClient httpClient, string url)
{ {
try HttpResponseMessage response = await httpClient.GetAsync(url);
{ response.EnsureSuccessStatusCode();
HttpResponseMessage response = await httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
string content = await response.Content.ReadAsStringAsync(); string content = await response.Content.ReadAsStringAsync();
var options = new JsonSerializerOptions var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};
return JsonSerializer.Deserialize<T>(content, options);
}
catch (Exception ex)
{ {
// Log or handle the exception, and return a default value or throw it again if needed PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Console.WriteLine($"Error making request to {url}: {ex.Message}"); };
throw; return JsonSerializer.Deserialize<T>(content, options);
}
} }
} }

56
gateways/web/src/EShopOnAbp.WebGateway/Aggregations/LocalizationAggregation.cs

@ -2,7 +2,6 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using EShopOnAbp.WebGateway.Aggregations.Localization; using EShopOnAbp.WebGateway.Aggregations.Localization;
using Microsoft.Extensions.Logging;
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
namespace EShopOnAbp.WebGateway.Aggregations; namespace EShopOnAbp.WebGateway.Aggregations;
@ -10,48 +9,64 @@ namespace EShopOnAbp.WebGateway.Aggregations;
public class LocalizationAggregation : ILocalizationAggregation public class LocalizationAggregation : ILocalizationAggregation
{ {
//Yarp localization route name //Yarp localization route name
public string LocalizationEndpoint { get; } = "EshopOnAbpLocalization"; public string LocalizationRouteName { get; } = "EshopOnAbpLocalization";
private readonly ILogger<LocalizationAggregation> _logger; public string LocalizationEndpoint { get; } = "api/abp/application-localization";
private readonly CachedLocalizationService _cachedLocalizationService; private readonly CachedLocalizationService _cachedLocalizationService;
private readonly RemoteLocalizationService _remoteLocalizationService; private readonly IRemoteLocalizationService _remoteLocalizationService;
public LocalizationAggregation(ILogger<LocalizationAggregation> logger, CachedLocalizationService cachedLocalizationService, RemoteLocalizationService remoteLocalizationService) public LocalizationAggregation(CachedLocalizationService cachedLocalizationService,
IRemoteLocalizationService remoteLocalizationService)
{ {
_logger = logger;
_cachedLocalizationService = cachedLocalizationService; _cachedLocalizationService = cachedLocalizationService;
_remoteLocalizationService = remoteLocalizationService; _remoteLocalizationService = remoteLocalizationService;
} }
public async Task<ApplicationLocalizationDto> GetLocalizationAsync(LocalizationRequest input) public async Task<ApplicationLocalizationDto> GetLocalizationAsync(LocalizationRequest input)
{ {
// Check the cache service // Check the cache service
var cachedLocalization = _cachedLocalizationService.GetMultipleLocalizationsAsync(input.LocalizationEndpoints.Keys.ToArray()); var cachedLocalization = _cachedLocalizationService
.GetLocalizationsFromCacheAsync(input.LocalizationEndpoints.Keys.ToArray());
// Compare cache with input service list // Compare cache with input service list
var missingLocalizationKeys = GetMissingLocalizations(cachedLocalization, input.LocalizationEndpoints); var missingLocalizationKeys = GetMissingLocalizations(cachedLocalization, input.LocalizationEndpoints);
if (missingLocalizationKeys.Count != 0) if (missingLocalizationKeys.Count != 0)
{ {
// Make request to remote localization service // Make request to remote localization service to get missing localizations
var remoteLocalizationResults = await _remoteLocalizationService var remoteLocalizationResults =
.GetMultipleLocalizationsAsync(input.LocalizationEndpoints await GetLocalizationsFromRemoteAsync(missingLocalizationKeys, input.LocalizationEndpoints);
.Where(kv=> missingLocalizationKeys.Contains(kv.Key))
.ToDictionary(k=>k.Key,v=>v.Value)); // Update localization cache
foreach (var result in remoteLocalizationResults) foreach (var result in remoteLocalizationResults)
{ {
_cachedLocalizationService.AddOrUpdate(result.Key, result.Value); _cachedLocalizationService.AddOrUpdate(result.Key, result.Value);
} }
cachedLocalization = _cachedLocalizationService.GetMultipleLocalizationsAsync(input.LocalizationEndpoints.Keys.ToArray());
cachedLocalization = _cachedLocalizationService
.GetLocalizationsFromCacheAsync(input.LocalizationEndpoints.Keys.ToArray());
} }
//merge result //merge result
ApplicationLocalizationDto mergedResult = MergeLocalizations(cachedLocalization); ApplicationLocalizationDto mergedResult = MergeLocalizations(cachedLocalization);
//return result //return result
return mergedResult; return mergedResult;
} }
private List<string> GetMissingLocalizations(IDictionary<string,ApplicationLocalizationDto> serviceNameWithLocalization, Dictionary<string,string> serviceNameWithUrls) private async Task<Dictionary<string, ApplicationLocalizationDto>> GetLocalizationsFromRemoteAsync(
List<string> missingLocalizationKeys, Dictionary<string, string> localizationEndpoints)
{
return await _remoteLocalizationService
.GetMultipleLocalizationsAsync(localizationEndpoints
.Where(kv => missingLocalizationKeys.Contains(kv.Key))
.ToDictionary(k => k.Key, v => v.Value));
}
private List<string> GetMissingLocalizations(
IDictionary<string, ApplicationLocalizationDto> serviceNameWithLocalization,
Dictionary<string, string> serviceNameWithUrls)
{ {
List<string> missingKeysInCache = serviceNameWithUrls.Keys.Except(serviceNameWithLocalization.Keys).ToList(); List<string> missingKeysInCache = serviceNameWithUrls.Keys.Except(serviceNameWithLocalization.Keys).ToList();
List<string> missingKeysInUrls = serviceNameWithLocalization.Keys.Except(serviceNameWithUrls.Keys).ToList(); List<string> missingKeysInUrls = serviceNameWithLocalization.Keys.Except(serviceNameWithUrls.Keys).ToList();
@ -59,10 +74,11 @@ public class LocalizationAggregation : ILocalizationAggregation
return missingKeysInCache.Concat(missingKeysInUrls).ToList(); return missingKeysInCache.Concat(missingKeysInUrls).ToList();
} }
private ApplicationLocalizationDto MergeLocalizations(IDictionary<string, ApplicationLocalizationDto> localizationResults) private ApplicationLocalizationDto MergeLocalizations(
IDictionary<string, ApplicationLocalizationDto> localizationResults)
{ {
var localizationDto = new ApplicationLocalizationDto(); var localizationDto = new ApplicationLocalizationDto();
foreach (var localization in localizationResults) foreach (var localization in localizationResults)
{ {
foreach (var resource in localization.Value.Resources) foreach (var resource in localization.Value.Resources)

12
gateways/web/src/EShopOnAbp.WebGateway/ReverseProxyBuilderExtensions.cs

@ -13,8 +13,6 @@ namespace EShopOnAbp.WebGateway;
public static class ReverseProxyBuilderExtensions public static class ReverseProxyBuilderExtensions
{ {
public static string LocalizationPath = "api/abp/application-localization";
public static ReverseProxyConventionBuilder MapReverseProxyWithLocalization(this IEndpointRouteBuilder endpoints) public static ReverseProxyConventionBuilder MapReverseProxyWithLocalization(this IEndpointRouteBuilder endpoints)
{ {
return endpoints.MapReverseProxy(proxyBuilder => return endpoints.MapReverseProxy(proxyBuilder =>
@ -24,11 +22,11 @@ public static class ReverseProxyBuilderExtensions
var endpoint = context.GetEndpoint(); var endpoint = context.GetEndpoint();
var localizationAggregation = context.RequestServices.GetRequiredService<ILocalizationAggregation>(); var localizationAggregation = context.RequestServices.GetRequiredService<ILocalizationAggregation>();
if (localizationAggregation.LocalizationEndpoint == endpoint?.DisplayName) if (localizationAggregation.LocalizationRouteName == endpoint?.DisplayName)
{ {
LocalizationRequest input = CreateLocalizationRequestInput(context); LocalizationRequest requestInput = CreateLocalizationRequestInput(context, localizationAggregation.LocalizationEndpoint);
var result = await localizationAggregation.GetLocalizationAsync(input); var result = await localizationAggregation.GetLocalizationAsync(requestInput);
await context.Response.WriteAsync(JsonSerializer.Serialize(result, new JsonSerializerOptions await context.Response.WriteAsync(JsonSerializer.Serialize(result, new JsonSerializerOptions
{ {
PropertyNamingPolicy = JsonNamingPolicy.CamelCase, PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
@ -44,14 +42,14 @@ public static class ReverseProxyBuilderExtensions
}); });
} }
private static LocalizationRequest CreateLocalizationRequestInput(HttpContext context) private static LocalizationRequest CreateLocalizationRequestInput(HttpContext context, string localizationPath)
{ {
var proxyConfig = context.RequestServices.GetRequiredService<IProxyConfigProvider>(); var proxyConfig = context.RequestServices.GetRequiredService<IProxyConfigProvider>();
context.Request.Query.TryGetValue("CultureName", out var cultureName); context.Request.Query.TryGetValue("CultureName", out var cultureName);
var input = new LocalizationRequest(cultureName); var input = new LocalizationRequest(cultureName);
string path = $"{LocalizationPath}?cultureName={cultureName}&onlyDynamics=false"; string path = $"{localizationPath}?cultureName={cultureName}&onlyDynamics=false";
var clusterList = GetClusters(proxyConfig); var clusterList = GetClusters(proxyConfig);
foreach (var cluster in clusterList) foreach (var cluster in clusterList)

Loading…
Cancel
Save