Async call to third party slows down a request

53 Views Asked by At

I have a command in .NET that creates some entities and returns a result. During the command, it sends an email with the information about the entity. It uses a service I get using DI and the call is async. I see when testing that sending this email can make the request take twice as long. The code is something like this.

public Guid CreateInvoice(string email, string name, ...)
{
    var transaction = await _context.Databse.BeginTransactionAsync();

    try {
       await _context.Invoice.AddAsync(new Invoice(email, name));
       // Some other CRUD operations here
    
       await _emailService.SendEmail(email, name); // This here adds the latency

       // Some other CRUD
       transaction.Commit();
       return newInvoice.Id;
    } 
    catch(Exception e)
    {
      transaction.Rollback();
    }
}

I have tried removing the await from the call of the email method. This obviously makes the code faster, but then I don't know if the method was send, which means that I cannot rollback the transaction if there is a problem. I want to rollback all of the CRUD if the method is not sent.

What is the best approach here? Should I add some retry policy for the sending so I don't have to worry about rolling back. Should I add some method in the email service that notifies the user that there was an error if the method fails? I can maybe split them and then call the email sending in the background so it is on its own. I am open to any ideas on how to tackle it. Thanks in advance.

1

There are 1 best solutions below

1
quyentho On BEST ANSWER

Does your business logic require the email to be sent within the transaction before the object gets saved to the database? I can't think of any reason for that to be a requirement. So, simply send the email after you commit the transaction. Then, you know for sure that your transaction has succeeded without worrying about a rollback.

Most email sending functionality doesn't need to be synchronous. This means you don't have to wait for the email to be sent successfully before continuing. Instead, delegate the email sending function to a background job. Then, implement a mechanism to update the status when the email has been sent.