Skip to content

Commit

Permalink
feat: redis & caller
Browse files Browse the repository at this point in the history
* chore: Caller adds handling of Service exception reporting

* chore: adjust GlobalException

* chore: Fix redis set error

* chore: Response supports null

Co-authored-by: zhenlei520 <[email protected]>
  • Loading branch information
zhenlei520 and zhenlei520 authored Feb 15, 2022
1 parent a9b31c1 commit 4fdfd4f
Show file tree
Hide file tree
Showing 22 changed files with 154 additions and 76 deletions.
4 changes: 2 additions & 2 deletions MASA.Utils.sln
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MASA.Utils.Caller.DaprClien
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MASA.Utils.Exceptions", "src\MASA.Utils.Exceptions\MASA.Utils.Exceptions.csproj", "{A43369A4-ECFC-46C4-AC04-B981AF7FE35D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MASA.Utils.Data.Elasticsearch", "src\Data\MASA.Utils.Data.Elasticsearch\MASA.Utils.Data.Elasticsearch.csproj", "{2FCFEA0A-146E-4F8F-ABCB-DE5A3553A263}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MASA.Utils.Data.Elasticsearch", "src\Data\MASA.Utils.Data.Elasticsearch\MASA.Utils.Data.Elasticsearch.csproj", "{2FCFEA0A-146E-4F8F-ABCB-DE5A3553A263}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MASA.Utils.Expressions", "src\Extensions\MASA.Utils.Expressions\MASA.Utils.Expressions.csproj", "{4116F6E9-BFD8-48CE-9453-CFE99650057D}"
EndProject
Expand All @@ -71,7 +71,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MASA.Utils.Security.Authent
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MASA.Utils.Security.Cryptography", "src\Security\MASA.Utils.Security.Cryptography\MASA.Utils.Security.Cryptography.csproj", "{B59A8DF4-6591-42CE-A9F8-BD0806B4A4C4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MASA.Utils.Security.Cryptography.Tests", "test\MASA.Utils.Security.Cryptography.Tests\MASA.Utils.Security.Cryptography.Tests.csproj", "{BBC2C38F-D758-468F-95E6-DC4688A2D1C0}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MASA.Utils.Security.Cryptography.Tests", "test\MASA.Utils.Security.Cryptography.Tests\MASA.Utils.Security.Cryptography.Tests.csproj", "{BBC2C38F-D758-468F-95E6-DC4688A2D1C0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static ICachingBuilder ConfigureMemoryCacheClient(this ICachingBuilder bu
throw new ArgumentNullException(nameof(configureOptions));
}

builder.Services.Configure<MasaMemoryCacheOptions>(builder.Name, configureOptions);
builder.Services.Configure(builder.Name, configureOptions);

return builder;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public class RedisConfigurationOptions : DistributedCacheEntryOptions
/// <summary>
/// Gets the servers.
/// </summary>
public List<RedisServerOptions> Servers { get; set; } = new List<RedisServerOptions>();
public List<RedisServerOptions> Servers { get; set; } = new();

/// <summary>
/// Gets or sets whether connect/configuration timeouts should be explicitly notified via a TimeoutException.
Expand Down
2 changes: 1 addition & 1 deletion src/Caching/MASA.Utils.Caching.Redis/RedisCacheClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ public async Task SetAsync<T>(string key, T value, CombinedCacheEntryOptions<T>?
await _db.ScriptEvaluateAsync(
SET_SCRIPT,
new RedisKey[] { key },
GetRedisValues(options.DistributedCacheEntryOptions, () => bytesValue)
GetRedisValues(options.DistributedCacheEntryOptions, () => new[] { (RedisValue)bytesValue })
).ConfigureAwait(false);
}

Expand Down
18 changes: 9 additions & 9 deletions src/Caller/MASA.Utils.Caller.Core/AbstractCallerProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ namespace MASA.Utils.Caller.Core;

public abstract class AbstractCallerProvider : ICallerProvider
{
public abstract Task<TResponse> SendAsync<TResponse>(HttpRequestMessage request, CancellationToken cancellationToken = default);
public abstract Task<TResponse?> SendAsync<TResponse>(HttpRequestMessage request, CancellationToken cancellationToken = default);

public abstract HttpRequestMessage CreateRequest(HttpMethod method, string? methodName);

Expand All @@ -20,10 +20,10 @@ public virtual Task<HttpResponseMessage> SendAsync(HttpMethod method, string? me
public virtual Task<HttpResponseMessage> SendAsync<TRequest>(HttpMethod method, string? methodName, TRequest data, CancellationToken cancellationToken = default)
{
HttpRequestMessage request = CreateRequest(method, methodName, data);
return SendAsync(request);
return SendAsync(request, cancellationToken);
}

public virtual Task<TResponse> SendAsync<TRequest, TResponse>(HttpMethod method, string? methodName, TRequest data, CancellationToken cancellationToken = default)
public virtual Task<TResponse?> SendAsync<TRequest, TResponse>(HttpMethod method, string? methodName, TRequest data, CancellationToken cancellationToken = default)
{
HttpRequestMessage request = CreateRequest(method, methodName, data);
return SendAsync<TResponse>(request, cancellationToken);
Expand Down Expand Up @@ -71,13 +71,13 @@ public virtual Task<HttpResponseMessage> GetAsync(string? methodName, Dictionary
return GetAsync(methodName, cancellationToken);
}

public Task<TResponse> GetAsync<TResponse>(string? methodName, CancellationToken cancellationToken= default)
public Task<TResponse?> GetAsync<TResponse>(string? methodName, CancellationToken cancellationToken= default)
{
HttpRequestMessage request = CreateRequest(HttpMethod.Get, methodName);
return SendAsync<TResponse>(request, cancellationToken);
}

public Task<TResponse> GetAsync<TResponse>(string? methodName, Dictionary<string, string> data, CancellationToken cancellationToken= default)
public Task<TResponse?> GetAsync<TResponse>(string? methodName, Dictionary<string, string> data, CancellationToken cancellationToken= default)
{
HttpRequestMessage request = CreateRequest(HttpMethod.Get, methodName, data);
return SendAsync<TResponse>(request, cancellationToken);
Expand Down Expand Up @@ -106,7 +106,7 @@ public virtual Task<HttpResponseMessage> PostAsync<TRequest>(string? methodName,
return SendAsync(request, cancellationToken);
}

public virtual Task<TResponse> PostAsync<TRequest, TResponse>(string? methodName, TRequest data, CancellationToken cancellationToken= default)
public virtual Task<TResponse?> PostAsync<TRequest, TResponse>(string? methodName, TRequest data, CancellationToken cancellationToken= default)
{
HttpRequestMessage request = CreateRequest(HttpMethod.Post, methodName, data);
return SendAsync<TResponse>(request, cancellationToken);
Expand All @@ -121,7 +121,7 @@ public virtual Task<HttpResponseMessage> PatchAsync<TRequest>(string? methodName
return SendAsync(request, cancellationToken);
}

public virtual Task<TResponse> PatchAsync<TRequest, TResponse>(string? methodName, TRequest data, CancellationToken cancellationToken= default)
public virtual Task<TResponse?> PatchAsync<TRequest, TResponse>(string? methodName, TRequest data, CancellationToken cancellationToken= default)
{
HttpRequestMessage request = CreateRequest(HttpMethod.Post, methodName, data);
return SendAsync<TResponse>(request, cancellationToken);
Expand All @@ -136,7 +136,7 @@ public virtual Task<HttpResponseMessage> PutAsync<TRequest>(string? methodName,
return SendAsync(request, cancellationToken);
}

public virtual Task<TResponse> PutAsync<TRequest, TResponse>(string? methodName, TRequest data, CancellationToken cancellationToken= default)
public virtual Task<TResponse?> PutAsync<TRequest, TResponse>(string? methodName, TRequest data, CancellationToken cancellationToken= default)
{
var request = CreateRequest(HttpMethod.Put, methodName, data);
return SendAsync<TResponse>(request, cancellationToken);
Expand All @@ -151,7 +151,7 @@ public virtual Task<HttpResponseMessage> DeleteAsync<TRequest>(string? methodNam
return SendAsync(request, cancellationToken);
}

public virtual Task<TResponse> DeleteAsync<TRequest, TResponse>(string? methodName, TRequest data, CancellationToken cancellationToken= default)
public virtual Task<TResponse?> DeleteAsync<TRequest, TResponse>(string? methodName, TRequest data, CancellationToken cancellationToken= default)
{
var request = CreateRequest(HttpMethod.Delete, methodName, data);
return SendAsync<TResponse>(request, cancellationToken);
Expand Down
35 changes: 35 additions & 0 deletions src/Caller/MASA.Utils.Caller.Core/DefaultRequestMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
namespace MASA.Utils.Caller.Core;

public class DefaultRequestMessage : IRequestMessage
{
private readonly CallerOptions _callerOptions;

public DefaultRequestMessage(CallerOptions callerOptions)
{
_callerOptions = callerOptions;
}

public async Task<TResponse?> ProcessResponseAsync<TResponse>(HttpResponseMessage response, CancellationToken cancellationToken = default)
{
if (response.IsSuccessStatusCode)
{
switch (response.StatusCode)
{
case HttpStatusCode.Accepted:
case HttpStatusCode.NoContent:
return default;
case (HttpStatusCode)MasaHttpStatusCode.UserFriendlyException:
throw new UserFriendlyException(await response.Content.ReadAsStringAsync(cancellationToken));
default:
if (typeof(TResponse).GetInterfaces().Any(type => type == typeof(IConvertible)))
{
var content = await response.Content.ReadAsStringAsync(cancellationToken);
return (TResponse)Convert.ChangeType(content, typeof(TResponse));
}
return await response.Content.ReadFromJsonAsync<TResponse>(_callerOptions.JsonSerializerOptions, cancellationToken)
?? throw new ArgumentException("Response cannot be empty");
}
}
throw new Exception(await response.Content.ReadAsStringAsync(cancellationToken));
}
}
20 changes: 9 additions & 11 deletions src/Caller/MASA.Utils.Caller.Core/ICallerProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@ namespace MASA.Utils.Caller.Core;

public interface ICallerProvider
{
Task<TResponse> SendAsync<TResponse>(HttpRequestMessage request, CancellationToken cancellationToken = default);
Task<TResponse?> SendAsync<TResponse>(HttpRequestMessage request, CancellationToken cancellationToken = default);

Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken = default);

Task<HttpResponseMessage> SendAsync(HttpMethod method, string? methodName, HttpContent? content,
CancellationToken cancellationToken = default);
Task<HttpResponseMessage> SendAsync(HttpMethod method, string? methodName, HttpContent? content, CancellationToken cancellationToken = default);

Task<HttpResponseMessage> SendAsync<TRequest>(HttpMethod method, string? methodName, TRequest data, CancellationToken cancellationToken = default);

Task<TResponse> SendAsync<TRequest, TResponse>(HttpMethod method, string? methodName, TRequest data,
CancellationToken cancellationToken = default);
Task<TResponse?> SendAsync<TRequest, TResponse>(HttpMethod method, string? methodName, TRequest data, CancellationToken cancellationToken = default);

Task SendGrpcAsync(string methodName, CancellationToken cancellationToken = default);

Expand All @@ -36,31 +34,31 @@ Task<TResponse> SendGrpcAsync<TRequest, TResponse>(string methodName, TRequest r

Task<HttpResponseMessage> GetAsync(string? methodName, Dictionary<string, string> data, CancellationToken cancellationToken = default);

Task<TResponse> GetAsync<TResponse>(string? methodName, CancellationToken cancellationToken = default);
Task<TResponse?> GetAsync<TResponse>(string? methodName, CancellationToken cancellationToken = default);

Task<TResponse> GetAsync<TResponse>(string? methodName, Dictionary<string, string> data, CancellationToken cancellationToken = default);
Task<TResponse?> GetAsync<TResponse>(string? methodName, Dictionary<string, string> data, CancellationToken cancellationToken = default);

Task<HttpResponseMessage> PostAsync(string? methodName, HttpContent? content, CancellationToken cancellationToken = default);

Task<HttpResponseMessage> PostAsync<TRequest>(string? methodName, TRequest data, CancellationToken cancellationToken = default);

Task<TResponse> PostAsync<TRequest, TResponse>(string? methodName, TRequest data, CancellationToken cancellationToken = default);
Task<TResponse?> PostAsync<TRequest, TResponse>(string? methodName, TRequest data, CancellationToken cancellationToken = default);

Task<HttpResponseMessage> PatchAsync(string? methodName, HttpContent? content, CancellationToken cancellationToken = default);

Task<HttpResponseMessage> PatchAsync<TRequest>(string? methodName, TRequest data, CancellationToken cancellationToken = default);

Task<TResponse> PatchAsync<TRequest, TResponse>(string? methodName, TRequest data, CancellationToken cancellationToken = default);
Task<TResponse?> PatchAsync<TRequest, TResponse>(string? methodName, TRequest data, CancellationToken cancellationToken = default);

Task<HttpResponseMessage> PutAsync(string? methodName, HttpContent? content, CancellationToken cancellationToken = default);

Task<HttpResponseMessage> PutAsync<TRequest>(string? methodName, TRequest data, CancellationToken cancellationToken = default);

Task<TResponse> PutAsync<TRequest, TResponse>(string? methodName, TRequest data, CancellationToken cancellationToken = default);
Task<TResponse?> PutAsync<TRequest, TResponse>(string? methodName, TRequest data, CancellationToken cancellationToken = default);

Task<HttpResponseMessage> DeleteAsync(string? methodName, HttpContent? content, CancellationToken cancellationToken = default);

Task<HttpResponseMessage> DeleteAsync<TRequest>(string? methodName, TRequest data, CancellationToken cancellationToken = default);

Task<TResponse> DeleteAsync<TRequest, TResponse>(string? methodName, TRequest data, CancellationToken cancellationToken = default);
Task<TResponse?> DeleteAsync<TRequest, TResponse>(string? methodName, TRequest data, CancellationToken cancellationToken = default);
}
6 changes: 6 additions & 0 deletions src/Caller/MASA.Utils.Caller.Core/IRequestMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace MASA.Utils.Caller.Core;

public interface IRequestMessage
{
Task<TResponse?> ProcessResponseAsync<TResponse>(HttpResponseMessage response, CancellationToken cancellationToken = default);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\MASA.Utils.Exceptions\MASA.Utils.Exceptions.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public static IServiceCollection AddCaller(this IServiceCollection services, Act

services.TryOrUpdateCallerOptions(callerOption);
services.TryAddSingleton<ICallerFactory, DefaultCallerFactory>();
services.TryAddSingleton<IRequestMessage, DefaultRequestMessage>();
services.TryAddTransient(serviceProvider => serviceProvider.GetRequiredService<ICallerFactory>().CreateClient());
return services;
}
Expand Down
3 changes: 3 additions & 0 deletions src/Caller/MASA.Utils.Caller.Core/_Imports.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@
global using Microsoft.Extensions.DependencyInjection.Extensions;
global using System.Reflection;
global using System.Text.Json;
global using System.Net;
global using System.Net.Http.Json;
global using MASA.Utils.Exceptions;

Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ public static CallerOptions UseDapr(this CallerOptions callerOptions, Func<MasaD

callerOptions.Services.AddDaprClient(builder.Configure);
callerOptions.AddCaller(builder.Name, builder.IsDefault, (serviceProvider) =>
{
var daprClient = serviceProvider.GetRequiredService<Dapr.Client.DaprClient>();
return new DaprCallerProvider(builder.AppId, daprClient);
});
{
var daprClient = serviceProvider.GetRequiredService<Dapr.Client.DaprClient>();
var requestMessage = serviceProvider.GetRequiredService<IRequestMessage>();
return new DaprCallerProvider(builder.AppId, requestMessage, daprClient);
});
return callerOptions;
}

Expand Down
11 changes: 8 additions & 3 deletions src/Caller/MASA.Utils.Caller.DaprClient/DaprCallerProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,21 @@ namespace MASA.Utils.Caller.DaprClient;
public class DaprCallerProvider : AbstractCallerProvider
{
private readonly string AppId;
private readonly IRequestMessage _requestMessage;
private readonly Dapr.Client.DaprClient _daprClient;

public DaprCallerProvider(string appId, Dapr.Client.DaprClient daprClient)
public DaprCallerProvider(string appId, IRequestMessage requestMessage, Dapr.Client.DaprClient daprClient)
{
AppId = appId;
_requestMessage = requestMessage;
_daprClient = daprClient;
}

public override Task<TResponse> SendAsync<TResponse>(HttpRequestMessage request, CancellationToken cancellationToken = default)
=> _daprClient.InvokeMethodAsync<TResponse>(request, cancellationToken);
public override async Task<TResponse?> SendAsync<TResponse>(HttpRequestMessage request, CancellationToken cancellationToken = default) where TResponse : default
{
var response = await _daprClient.InvokeMethodWithResponseAsync(request, cancellationToken);
return await _requestMessage.ProcessResponseAsync<TResponse>(response, cancellationToken);
}

public override HttpRequestMessage CreateRequest(HttpMethod method, string? methodName)
=> _daprClient.CreateInvokeMethodRequest(method, AppId, methodName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ public static IHttpClientBuilder UseHttpClient(this CallerOptions callerOptions,
callerOptions.AddCaller(builder.Name, builder.IsDefault, (serviceProvider) =>
{
var httpClient = serviceProvider.GetRequiredService<IHttpClientFactory>().CreateClient(builder.Name);
return new HttpClientCallerProvider(httpClient, builder.BaseAPI, builder.JsonSerializerOptions ?? callerOptions.JsonSerializerOptions);
var requestMessage = serviceProvider.GetRequiredService<IRequestMessage>();
return new HttpClientCallerProvider(
httpClient,
requestMessage,
builder.BaseAPI);
});
return httpClientBuilder;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,20 @@ namespace MASA.Utils.Caller.HttpClient;
public class HttpClientCallerProvider : AbstractCallerProvider
{
private readonly System.Net.Http.HttpClient _httpClient;
private readonly IRequestMessage _requestMessage;
private string _baseAPI;
private JsonSerializerOptions? _jsonSerializerOptions;

public HttpClientCallerProvider(System.Net.Http.HttpClient httpClient, string baseAPI, JsonSerializerOptions? jsonSerializerOptions)
public HttpClientCallerProvider(System.Net.Http.HttpClient httpClient,IRequestMessage requestMessage, string baseAPI)
{
_httpClient = httpClient;
_requestMessage = requestMessage;
_baseAPI = baseAPI;
_jsonSerializerOptions = jsonSerializerOptions;
}

public override async Task<TResponse> SendAsync<TResponse>(HttpRequestMessage request, CancellationToken cancellationToken = default)
public override async Task<TResponse?> SendAsync<TResponse>(HttpRequestMessage request, CancellationToken cancellationToken = default) where TResponse : default
{
HttpResponseMessage response = await _httpClient.SendAsync(request, cancellationToken);

if (typeof(TResponse).GetInterfaces().Any(type => type == typeof(IConvertible)))
{
var content = await response.Content.ReadAsStringAsync(cancellationToken);
return (TResponse)Convert.ChangeType(content, typeof(TResponse));
}
return await response.Content.ReadFromJsonAsync<TResponse>(this._jsonSerializerOptions, cancellationToken)
?? throw new ArgumentException("Response cannot be empty");
return await _requestMessage.ProcessResponseAsync<TResponse>(response, cancellationToken);
}

public override HttpRequestMessage CreateRequest(HttpMethod method, string? methodName) => new(method, GetRequestUri(methodName));
Expand All @@ -45,7 +38,6 @@ public override Task SendGrpcAsync(string methodName, CancellationToken cancella

public override Task<TResponse> SendGrpcAsync<TResponse>(string methodName, CancellationToken cancellationToken = default)
{

throw new NotImplementedException();
}

Expand Down
Loading

0 comments on commit 4fdfd4f

Please sign in to comment.