Reputation: 824
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
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