using MediatR;
using ZeroFramework.DeviceCenter.Infrastructure.Idempotency;
namespace ZeroFramework.DeviceCenter.Application.Infrastructure
{
///
/// 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.
///
public class IdentifiedCommandHandler(IMediator mediator, IRequestManager requestManager) : IRequestHandler, TResponse> where TRequest : IRequest
{
private readonly IMediator _mediator = mediator;
private readonly IRequestManager _requestManager = requestManager;
///
/// Creates the result value to return if a previous request was found
///
protected virtual TResponse? CreateResultForDuplicateRequest() => default;
///
/// 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.
///
public async Task Handle(IdentifiedCommand command, CancellationToken cancellationToken)
{
if (await _requestManager.ExistAsync(command.Id))
{
return CreateResultForDuplicateRequest() ?? throw new NotImplementedException();
}
await _requestManager.CreateRequestForCommandAsync(command.Id);
// Send the embeded business command to mediator so it runs its related CommandHandler
return await _mediator.Send(command.Command, cancellationToken);
}
}
}