-1

I have an event pubblished in a bus(rabbit) and two application that are subscribed to this Event.

public class CreationEvent 
{
    public int CreationEventID {get; set; }
    ... other properties
}

Application A and Application B are subscribed to this event, and listen from a rabbit queue. Application A save the properties of this event in its database.

Application B save the properties of this event in its database. In addition create another event related to the CreationEventId with other properties and send it to a rabbit queue

public class ExtendCreationEvent
{
    public int ExtendCreationEvent {get; set; }
    public int CreationEventID {get; set; }
    ... other properties
}

Application A is subscribed to this Event and listen from a rabbit queue, read and save the properties in its database related to CreationEventID.

This is the problem. I don't know if the Application B is too fast and pubblish the event ExtendCreationEvent before ApplicationA save CreationEventID from the first event. So application A could try to elaborate event ExtendCreationEvent before the elaboration of CreationEvent .

How can I solve this problem and guarantee the elaboration order in Application A?

3
  • It is not clear to me how this relates to .NET events. Perhaps it doesn't. It sounds like you are calling directly into application code with this and this is the problem. Try posting to a queue instead and let the receiving application deal with the message when it is ready to do so. Commented Sep 14, 2021 at 20:57
  • Hi Martin. I've rephrased the question, I hope it's more clear. The applications doesn't call directly each other. They communicate only with events on a rabbit queue. Commented Sep 14, 2021 at 21:08
  • user3401335 If there is such a strong dependency (B needing results of A), why not have A do the extended stuff in sequence? Or, have A post an event to B when it's ready. Commented Sep 15, 2021 at 5:46

2 Answers 2

4

You can rarely guarantee the execution order of anything concurrent; therefore, the obvious solution although not necessarily satisfying is to sequence the operations. Some suggestions to do that:

Chain the event:

Application A is the only subscribed to the Creation Event. Application B waits A to emit a Created Event to it, that A will when its processing is fully complete.

Submit to the original queue, single worker:

Application A and B listen to events. A gets Creation event. B completes its processing and publish to the same queue the ExtendCreationEvent. Since A is currently processing Creation event it doesn't process ExtendCreationEvent before finishing CreationEvent.

Push back:

A and B listen to events. A get ExtendCreationEvent, check for existence of the CreationEvent in database. If not, push back the event in the queue / retry after a timer

3

Let me quickly rephrase your question to make sure I am understanding correctly.

You have two applications, App_A and App_B. They both subscribe to the same message, CreationEvent.

When App_B gets the CreationEvent message is does some stuff with the message and then publishes a new ExtendedCreationEvent message.

App_A subscribed to both the CreationEvent and ExtendedCreationEvent messages. But you do not want App_A to process a ExtendedCreationEvent message until the associated CreationEvent message is processed.

Let me know if I've misunderstood any of that.


Here are two options for you.

  1. have App_B fail to process a ExtendedCreationEvent unless it sees the associated CreationEvent in the database. If a ExtendedCreationEvent is received but no matching CreationEvent can be found in the database you should requeue the message for processing later.

  2. Place all CreationEvents and ExtendedCreationEvents on the same RabbitMq queue. Because RabbitMq queues are FIFO (first in first out, or "ordered") by default the ExtendedCreationEvent will never be able to "jump ahead" of the CreationEvent.

Each of the above options has caviats.

Option 1 will only work if every ExtendedCreationEvent has a matching CreationEvent.

Option 1 will either require you to configure the retry handling of your message bus to ensure that messages can be retried. Or will require you to write a re-publish message function for your code.

Option 2 depends heavily on the behavior of your message bus. It might not work for a non RabbitMq bus or a non-default configuration of your RabbitMq queue which does not guarantee FIFO.

Option 2 will also not work if you need to be able to retry failed messages. As this causes a reordering of messages.

Option 2 requires your message deserializer to be able to read both CreationEvent and ExtendedCreationEvent. Polymorphism at deserialization time can be tricky if the messages do not follow a common pattern.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.