zeroframework/Services/DeviceCenter/ZeroFramework.DeviceCenter.Application/Infrastructure/IdentifiedCommandHandler.cs
2023-12-05 17:22:48 +08:00

38 lines
1.7 KiB
C#

using MediatR;
using ZeroFramework.DeviceCenter.Infrastructure.Idempotency;
namespace ZeroFramework.DeviceCenter.Application.Infrastructure
{
/// <summary>
/// Provides a base implementation for handling duplicate request and ensuring idempotent updates, in the cases where
/// a requestid sent by client is used to detect duplicate requests.
/// </summary>
public class IdentifiedCommandHandler<TRequest, TResponse>(IMediator mediator, IRequestManager requestManager) : IRequestHandler<IdentifiedCommand<TRequest, TResponse>, TResponse> where TRequest : IRequest<TResponse>
{
private readonly IMediator _mediator = mediator;
private readonly IRequestManager _requestManager = requestManager;
/// <summary>
/// Creates the result value to return if a previous request was found
/// </summary>
protected virtual TResponse? CreateResultForDuplicateRequest() => default;
/// <summary>
/// This method handles the command. It just ensures that no other request exists with the same ID, and if this is the case
/// just enqueues the original inner command.
/// </summary>
public async Task<TResponse> Handle(IdentifiedCommand<TRequest, TResponse> command, CancellationToken cancellationToken)
{
if (await _requestManager.ExistAsync(command.Id))
{
return CreateResultForDuplicateRequest() ?? throw new NotImplementedException();
}
await _requestManager.CreateRequestForCommandAsync<TRequest>(command.Id);
// Send the embeded business command to mediator so it runs its related CommandHandler
return await _mediator.Send(command.Command, cancellationToken);
}
}
}