Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency between message queuing messages

Here is my scenario:

  • I have two servers with a multi-threaded message queuing consumer on each (two consumers total).
  • I have many message types (CreateParent, CreateChild, etc.)
  • I am stuck with bad legacy code (creating a child will partially creates a parent. I know it is bad...But I cannot change that.)
  • Message ordering cannot be assume (message queuing principle!)
  • RabbitMQ is my message queuing broker.

My problem:

  • When two threads are running simultaneous (one executing a CreateParent, the other executing a CreateChild), they generate conflicts because the two threads try to create the Parent in the database (remember the legacy code!)

My initial solution:

  • Inside the consumer, I created an "entity locking" concept. So when the thread processes a CreateChild message for example, it locks the Child and the Parent (legacy code!!) so the CreateParent message processing can wait. I used basic .net Monitor and list of Ids to implement this concept. It works well.

My initial solution limitation:

  • My "entity locking" concept works well on a single consumer in a single process on a single server. But it will not works across multiple servers running multiple consumers.
  • I am thinking of using a shared database to "store" my entity locking concept, so each processes (and threads) could access the database to verify which entities are locked.

My question (finally!):

All this is becoming very complex and it increases the bugs risk and code maintenance problems. I really don`t like it! Does anyone already faced this kind of problem? Are they acceptable workarounds for it? Does anyone have an idea for a clean solution for my scenario?

Thanks!

like image 347
Normand Bedard Avatar asked Nov 13 '22 09:11

Normand Bedard


1 Answers

Finally, simple solutions are always the better ones!

Instead of using all the complexity of my "entity locking" concept, I finally turn down to pre-validate all the required data and entities states before executing the request.

More precisely, instead of letting CreateChild process crashes by itself when it encounter already existing data created by the CreateParent, I fully validate that everything is okay in the databases BEFORE executing the CreateChild message.

The drawback of this solution is that the implementation of the CreateChild must be aware of what of the specific data the CreateParent will produces and verify it`s presence before starting the execution. But seriously, this is far better than locking all the stuff in cross-system!

like image 168
Normand Bedard Avatar answered Dec 14 '22 03:12

Normand Bedard