emirkljucanin
emirkljucanin

Reputation: 824

Publishing one generic fail event and attaching data to it or publish multiple specific fail event

So we have a scenario where we are creating credit cards. We have CreateCardConsumer that internally implements a strategy that decides which credit card provider API will be used (currently, we have two, let's call them, Provider1 and Provider2).

In case that credit card creation fails, we have the FailedToCreateCard event that gets published in CreateCardConsumer:

public class CreateCardConsumer : IConsumer<CreateCard>
{
   public async Task Consume(ConsumeContext<CreateVirtualCard> context)
   {
      try
      {
        // Decide which provider to use
      }
      catch (Provider1Exception e)
      {
      }
      catch (Provider2Exception e)
      {
      }
      catch (Exception e)
      {
        await context.Publish<FailedToCreateCard>(new(context.Message.CardId));
      }
   }
}

The issue with this is that when card creation fails, we must inform multiple systems that creation failed (and there, we use the FailedToCreateCard event). We also need to send a notification to our support with error details (which are a different data structure for both providers).

It feels fishy to extend FailedToCreateCard event with the error data for both providers and listen in the consumer that sends an email to the support (in the future there can be more than 2 providers), but it also feels fishy that we do something like

catch (Provider1Exception e)
{
  await context.Publish<FailedToCreateProvider1Card>(new(context.Message.CardId, e));
  await context.Publish<FailedToCreateCard>(new(context.Message.CardId));
}
catch (Provider2Exception e)
{
  await context.Publish<FailedToCreateProvider2Card>(new(context.Message.CardId, e));
  await context.Publish<FailedToCreateCard>(new(context.Message.CardId));
}

And the third solution that comes to mind is that we publish FailedToCreateProvider1Card and FailedToCreateProvider2Card from within the service that makes an API call and publish FailedToCreateCard in the consumer.

Does any one of these solution makes sense or there is a fourth one that is a common practice in this scenario?

Upvotes: 1

Views: 55

Answers (1)

Chris Patterson
Chris Patterson

Reputation: 33542

If you're using a broker like RabbitMQ, MassTransit supports polymorphic messaging. You can read more in the documentation, but by having two interfaces implemented by a single class (which would be published), you can produce a single event that would be routed via either message type.

Upvotes: 1

Related Questions