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; } } } }