Skip to content

Commit

Permalink
Merge pull request #42 from NerosoftDev/refactoring/service-bus
Browse files Browse the repository at this point in the history
Refactoring/service bus
  • Loading branch information
Codespilot authored Dec 5, 2023
2 parents 3100cdf + fc9a6a7 commit 06dde5b
Show file tree
Hide file tree
Showing 21 changed files with 541 additions and 216 deletions.
4 changes: 0 additions & 4 deletions Source/Euonia.Application/Euonia.Application.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@
<Nullable>disable</Nullable>
</PropertyGroup>

<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authorization" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
Expand Down
210 changes: 125 additions & 85 deletions Source/Euonia.Application/Seedwork/IRequestContextAccessor.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Security.Claims;
using System.Net;
using System.Security.Claims;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Primitives;

namespace Nerosoft.Euonia.Application;
Expand All @@ -8,35 +10,65 @@ namespace Nerosoft.Euonia.Application;
/// </summary>
public interface IRequestContextAccessor
{
/// <summary>
/// Gets the authenticated user information for the current request.
/// </summary>
ClaimsPrincipal User { get; }

/// <summary>
/// Gets the items for the current request.
/// </summary>
IDictionary<object, object> Items { get; }

/// <summary>
/// Gets the request trace identifier.
/// </summary>
string TraceIdentifier { get; }

/// <summary>
/// Gets the injected service provider for the current request.
/// </summary>
IServiceProvider RequestServices { get; }

/// <summary>
/// Gets the request cancellation token.
/// </summary>
CancellationToken RequestAborted { get; }

/// <summary>
/// Gets the request headers.
/// </summary>
IDictionary<string, StringValues> RequestHeaders { get; }
/// <summary>
/// Gets a unique identifier to represent the connection.
/// </summary>
string ConnectionId { get; }

/// <summary>
/// Gets the IP address of the remote target. Can be null.
/// </summary>
IPAddress RemoteIpAddress { get; }

/// <summary>
/// Gets the port of the remote target.
/// </summary>
int RemotePort { get; }

/// <summary>
///
/// </summary>
bool IsWebSocketRequest { get; }

/// <summary>
/// Gets the authenticated user information for the current request.
/// </summary>
ClaimsPrincipal User { get; }

/// <summary>
/// Gets the items for the current request.
/// </summary>
IDictionary<object, object> Items { get; }

/// <summary>
/// Gets the request trace identifier.
/// </summary>
string TraceIdentifier { get; }

/// <summary>
/// Gets the injected service provider for the current request.
/// </summary>
IServiceProvider RequestServices { get; }

/// <summary>
/// Gets the request cancellation token.
/// </summary>
CancellationToken RequestAborted { get; }

/// <summary>
/// Gets the request headers.
/// </summary>
IDictionary<string, StringValues> RequestHeaders { get; }

/// <summary>
/// Gets the Authorization HTTP header.
/// </summary>
StringValues Authorization => RequestHeaders?.TryGetValue(nameof(Authorization)) ?? default;

/// <summary>
/// Gets or sets the Request-Id HTTP header.
/// </summary>
StringValues RequestId => RequestHeaders?.TryGetValue("Request-Id") ?? default;
}

/// <summary>
Expand Down Expand Up @@ -69,64 +101,72 @@ public interface IRequestContextAccessor
/// </summary>
public delegate IDictionary<string, StringValues> GetRequestHeadersDelegate();

/// <summary>
/// Define delegation to get connection information of current request.
/// </summary>
/// <returns></returns>
public delegate Tuple<string, IPAddress, int, bool> GetConnectionInfoDelegate();

/// <summary>
/// An implementation of <see cref="IRequestContextAccessor"/> using delegate methods.
/// </summary>
public class DelegateRequestContextAccessor : IRequestContextAccessor
{
private readonly GetRequestUserDelegate _getUser;
private readonly GetRequestItemsDelegate _getItems;
private readonly GetRequestTraceIdentifierDelegate _getTraceIdentifier;
private readonly GetRequestServicesDelegate _getServices;
private readonly GetRequestAbortedDelegate _getAborted;
private readonly GetRequestHeadersDelegate _getHeaders;

/// <summary>
/// Initializes a new instance of the <see cref="DelegateRequestContextAccessor"/> class.
/// </summary>
public DelegateRequestContextAccessor()
{
}

/// <inheritdoc />
public DelegateRequestContextAccessor(GetRequestUserDelegate getUser, GetRequestItemsDelegate getItems, GetRequestTraceIdentifierDelegate getTraceIdentifier, GetRequestServicesDelegate getServices, GetRequestAbortedDelegate getAborted, GetRequestHeadersDelegate getHeaders)
: this()
{
_getUser = getUser;
_getItems = getItems;
_getTraceIdentifier = getTraceIdentifier;
_getServices = getServices;
_getAborted = getAborted;
_getHeaders = getHeaders;
}

/// <summary>
/// Gets the authenticated user information for the current request.
/// </summary>
public ClaimsPrincipal User => _getUser?.Invoke();

/// <summary>
/// Gets the items for the current request.
/// </summary>
public IDictionary<object, object> Items => _getItems?.Invoke();

/// <summary>
/// Gets the request trace identifier.
/// </summary>
public string TraceIdentifier => _getTraceIdentifier?.Invoke();

/// <summary>
/// Gets the injected service provider for the current request.
/// </summary>
public IServiceProvider RequestServices => _getServices?.Invoke();

/// <summary>
/// Gets the request cancellation token.
/// </summary>
public CancellationToken RequestAborted => _getAborted?.Invoke() ?? default;

/// <summary>
/// Gets the request headers.
/// </summary>
public IDictionary<string, StringValues> RequestHeaders => _getHeaders?.Invoke();

private readonly IServiceProvider _provider;

/// <summary>
/// Initializes a new instance of the <see cref="DelegateRequestContextAccessor"/> class.
/// </summary>
public DelegateRequestContextAccessor(IServiceProvider provider)
{
_provider = provider;
var (connectionId, remoteIpAddress, remotePort, isWebSocketRequest) = provider.GetService<GetConnectionInfoDelegate>()?.Invoke() ?? default;
ConnectionId = connectionId;
RemoteIpAddress = remoteIpAddress;
RemotePort = remotePort;
IsWebSocketRequest = isWebSocketRequest;
}

/// <inheritdoc/>
public string ConnectionId { get; }

/// <inheritdoc/>
public IPAddress RemoteIpAddress { get; }

/// <inheritdoc/>
public int RemotePort { get; }

/// <inheritdoc/>
public bool IsWebSocketRequest { get; }

/// <summary>
/// Gets the authenticated user information for the current request.
/// </summary>
public ClaimsPrincipal User => _provider.GetService<GetRequestUserDelegate>()?.Invoke();

/// <summary>
/// Gets the items for the current request.
/// </summary>
public IDictionary<object, object> Items => _provider.GetService<GetRequestItemsDelegate>()?.Invoke();

/// <summary>
/// Gets the request trace identifier.
/// </summary>
public string TraceIdentifier => _provider.GetService<GetRequestTraceIdentifierDelegate>()?.Invoke();

/// <summary>
/// Gets the injected service provider for the current request.
/// </summary>
public IServiceProvider RequestServices => _provider.GetService<GetRequestServicesDelegate>()?.Invoke();

/// <summary>
/// Gets the request cancellation token.
/// </summary>
public CancellationToken RequestAborted => _provider.GetService<GetRequestAbortedDelegate>()?.Invoke() ?? default;

/// <summary>
/// Gets the request headers.
/// </summary>
public IDictionary<string, StringValues> RequestHeaders => _provider.GetService<GetRequestHeadersDelegate>()?.Invoke();
}
5 changes: 5 additions & 0 deletions Source/Euonia.Application/Services/BaseApplicationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,9 @@ public abstract class BaseApplicationService : IApplicationService
/// Gets the current request user principal.
/// </summary>
protected virtual UserPrincipal User => LazyServiceProvider.GetService<UserPrincipal>();

/// <summary>
/// Gets the current request context accessor.
/// </summary>
protected virtual IRequestContextAccessor HttpRequestAccessor => LazyServiceProvider.GetService<IRequestContextAccessor>();
}
6 changes: 3 additions & 3 deletions Source/Euonia.Bus.Abstract/Contracts/IBusConfigurator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public interface IBusConfigurator
/// </summary>
/// <typeparam name="TFactory"></typeparam>
/// <returns></returns>
IBusConfigurator SerFactory<TFactory>()
IBusConfigurator SetFactory<TFactory>()
where TFactory : class, IBusFactory;

/// <summary>
Expand All @@ -26,7 +26,7 @@ IBusConfigurator SerFactory<TFactory>()
/// <param name="factory"></param>
/// <typeparam name="TFactory"></typeparam>
/// <returns></returns>
IBusConfigurator SerFactory<TFactory>(TFactory factory)
IBusConfigurator SetFactory<TFactory>(TFactory factory)
where TFactory : class, IBusFactory;

/// <summary>
Expand All @@ -35,7 +35,7 @@ IBusConfigurator SerFactory<TFactory>(TFactory factory)
/// <param name="factory"></param>
/// <typeparam name="TFactory"></typeparam>
/// <returns></returns>
IBusConfigurator SerFactory<TFactory>(Func<IServiceProvider, TFactory> factory)
IBusConfigurator SetFactory<TFactory>(Func<IServiceProvider, TFactory> factory)
where TFactory : class, IBusFactory;

/// <summary>
Expand Down
4 changes: 2 additions & 2 deletions Source/Euonia.Bus.Abstract/RoutedMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ protected RoutedMessage()
/// Gets or sets the conversation identifier.
/// </summary>
[DataMember]
public virtual string ConversationId { get; }
public virtual string ConversationId { get; set; } = Guid.NewGuid().ToString();

/// <summary>
/// Gets or sets the request trace identifier.
/// </summary>
[DataMember]
public virtual string RequestTraceId { get; }
public virtual string RequestTraceId { get; set; }

/// <summary>
/// Gets or sets the channel that the message send to.
Expand Down
23 changes: 3 additions & 20 deletions Source/Euonia.Bus.InMemory/BusConfiguratorExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Nerosoft.Euonia.Bus.InMemory;

namespace Nerosoft.Euonia.Bus;
Expand All @@ -15,29 +14,13 @@ public static class BusConfiguratorExtensions
/// </summary>
/// <param name="configurator"></param>
/// <param name="configuration"></param>
/// <exception cref="InvalidOperationException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public static void UseInMemory(this IBusConfigurator configurator, Action<InMemoryBusOptions> configuration)
{
configurator.Service.Configure(configuration);
configurator.Service.TryAddSingleton(provider =>
{
var options = provider.GetService<IOptions<InMemoryBusOptions>>()?.Value;
if (options == null)
{
throw new InvalidOperationException("The in-memory message dispatcher options is not configured.");
}
IMessenger messenger = options.MessengerReference switch
{
MessengerReferenceType.StrongReference => StrongReferenceMessenger.Default,
MessengerReferenceType.WeakReference => WeakReferenceMessenger.Default,
_ => throw new ArgumentOutOfRangeException(nameof(options.MessengerReference), options.MessengerReference, null)
};
return messenger;
});
configurator.Service.TryAddTransient<InMemoryQueueConsumer>();
configurator.Service.TryAddTransient<InMemoryTopicSubscriber>();
configurator.Service.TryAddSingleton<InMemoryDispatcher>();
configurator.Service.AddTransient<IRecipientRegistrar, InMemoryRecipientRegistrar>();
configurator.SerFactory<InMemoryBusFactory>();
configurator.SetFactory<InMemoryBusFactory>();
}
}
5 changes: 0 additions & 5 deletions Source/Euonia.Bus.InMemory/InMemoryBusOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,4 @@ public class InMemoryBusOptions
/// <c>true</c> if the subscriber should create for each message channel; otherwise, <c>false</c>. default is <c>false</c>.
/// </value>
public bool MultipleSubscriberInstance { get; set; }

/// <summary>
/// Gets or sets the messenger reference type.
/// </summary>
public MessengerReferenceType MessengerReference { get; set; } = MessengerReferenceType.StrongReference;
}
Loading

0 comments on commit 06dde5b

Please sign in to comment.