using MediatR;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Repositories;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands
{
///
/// 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.
///
/// Type of the command handler that performs the operation if request is not duplicated
/// Return value of the inner command handler
public class IdentifierCommandHandler : IAsyncRequestHandler, R>
where T : IAsyncRequest
{
private readonly IMediator _mediator;
private readonly IRequestManager _requestManager;
public IdentifierCommandHandler(IMediator mediator, IRequestManager requestManager)
{
_mediator = mediator;
_requestManager = requestManager;
}
///
/// Creates the result value to return if a previous request was found
///
///
protected virtual R CreateResultForDuplicateRequest()
{
return default(R);
}
///
/// 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.
///
/// IdentifiedCommand which contains both original command & request ID
/// Return value of inner command or default value if request same ID was found
public async Task Handle(IdentifiedCommand message)
{
var alreadyExists = await _requestManager.ExistAsync(message.Id);
if (alreadyExists)
{
return CreateResultForDuplicateRequest();
}
else
{
await _requestManager.CreateRequestForCommandAsync(message.Id);
var result = await _mediator.SendAsync(message.Command);
return result;
}
}
}
}