MassTransit - Getting response from request-response ok but message added and deleted from skipped queue?

1.7k views Asked by At

I couldn't see anything to say this is normal behaviour, so excuse me if I am blind lol. I have seen something a bit odd when using MassTransit with request-response.

So I have multiple consumers on a service that listens for different requests to do simple tasks, like grab data from a database.

To test each consumer, I created a console app that executes a request for each consumer and checks the response.

What I am noticing is that the first request-response works fine, but when the code runs the next checks the response is received but the message is then moved to the skipped queue and deleted.

Here is the masstransit log for the 2nd request.

Send

[2021-05-14 10:27:11.812 DBG] (MassTransit.)-SEND rabbitmq://192.168.0.25/Ksrs.Requests:ConceptByConceptNoRequest d9360000-cf5b-480f-418f-08d916ba7421 Ksrs.Requests.ConceptByConceptNoRequest

Receive

[2021-05-14 10:28:00.203 DBG] (MassTransit.ReceiveTransport.)-RECEIVE rabbitmq://192.168.0.25/DESKTOP99KLG9M_Tests_bus_5r5yyygxmpry6jgtbdctpqurrb?temporary=true d9360000-cf5b-480f-2626-08d916ba7429 Ksrs.Response.ConceptResponse MassTransit.MessageHandler<Ksrs.Response.ConceptResponse>(00:00:00.0004546)

Skip?

[2021-05-14 10:28:41.361 DBG] (MassTransit.ReceiveTransport.)-SKIP rabbitmq://192.168.0.25/DESKTOP99KLG9M_Tests_bus_5r5yyygxmpry6jgtbdctpqurrb?temporary=true d9360000-cf5b-480f-ce25-08d916ba75f3

Don't understand the skip when I still get the response, the response is as expected and the code can move on.

This is the client request and response code, which is pretty much the same for all my checks. The only difference being the request-response types.

static async Task<bool> GetByConceptNo(AutofacServiceProvider autoFac, short ksrsId, short conceptNo, ILogger logger)
    {
        var client = autoFac.GetService<IRequestClient<ConceptByConceptNoRequest>>();

        if (client is null) return false;

        Response<ConceptResponse> response;

        try
        {
            response = await client.GetResponse<ConceptResponse>(new ConceptByConceptNoRequest() {KsrsId = ksrsId, ConceptNo = conceptNo});

            logger.LogInformation("Received {Concept}.",response.Message.Concept);
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            return false;
        }
        return response.Message.Concept is not null;
    }

Just some notes:

Using Autofac as container.

Using Serilog for logging.

Using RabbitMQ (3.8.16) as message broker.

UPDATE: So found something interesting. I added the following logging line to each consumer so I know is being run.

Logger.LogInformation("Request for [what ever consumer running goes here]");

Now lets say I have Consumer1, Consumer2 and Consumer3. I am seeing this in the log.

Request for Consumer 1
SEND blah blah
RECIEVE blah blah
Request for Consumer 1
Request for Consumer 2
SEND blah blah
RECIEVE blah blah
Request for Consumer 1
Request for Consumer 3
SEND blah blah
RECIEVE blah blah
SEND blah blah
RECIEVE blah blah

So it seems Consumer 1 keeps executing, but I don't understand why if the message type is different for each consumer and the client is not calling for it.

1

There are 1 answers

0
Chris Patterson On BEST ANSWER

MassTransit supports polymorphic message routing. So in the case above, if the message type consumed by Consumer 1 is implemented by the request produced for Consumer 2 or Consumer 3, Consumer 1 will receive a copy of that message – to which it will also respond.

When publishing requests (which is the default if a specific destination address it not specified), it's important to make sure that there is only one consumer for that message type configured.

Polymorphic messaging is great for events, since it is easy to siphon off the interesting event properties with a single consumer and multiple event types. But it is best avoided with commands/requests, based upon what you've seen above. Or at least in the case above, when publishing requests/commands, having a consumer that consumes a super type of the message shouldn't respond, but perhaps only track/log/audit the command/request.