I want to create a saga which is started by message "Event1" but which will ignore receipt of "duplicate" start messages with the same applicative id (which may result from two or more users hitting a UI button within a short period of time). The documentation seems to suggest that this approach would work:
Saga declares IAmStartedByMessages<Event1>
Saga configures itself with ConfigureMapping<Event1>(s => s.SomeID, m => m.SomeID);
Handle(Event1 evt) sets a boolean flag when it processes the first message, and falls out of the handler if the flag has already been set.
Will this work? Will I have a race condition if the subscribers are multithreaded? If so, how can I achieve the desired behavior?
Thanks!
The race condition happens when two Event1 messages are processed concurrently. The way to prevent two saga instances from being created is by setting a unique constraint on the SomeID column.
Related
Whenever I receive a message from a Queue, I want to be able to know somehow what is the sequence number of the message. This sequence number should be equal to the number of messages that were sent to the queue from the moment it was created plus 1. So the first message sent to the queue would have sequenceNumber = 1, second message would have sequenceNumber = 2 etc. So basically it should work similarly to database id sequence, that is inceremented every time we insert a new row.
Does RabbitMQ has some kind of mechanism to support that?
Of course, I could use database for that, but I need to avoid DB usage if that's possible.
Any help would be really appreciated,
Thanks
In my Anylogic model I have a hub which can store 5 containers. So it has a capacity parameter with value 5. I also have given it a variable with the numberOfContainers stored at the hub at that moment. When I run the model I see that the variable works (it changes over time to the number of containers that is stored at that moment).
Now I want another agent in my model to make a decision based on whether the capacity of the hub is reached at that moment (within its statechart). I tried to create a branche with the following condition:
main.hub.numberOfContainers > main.hub.capacity
but it doesn't work, the statechart acts like the capacity is never reached, even if the number of containers is much higher than the capacity. Does anybody know how to make this work?
Typically, condition branches are tricky because the condition may not be evaluated at the time you want it to be. Here is an example.
At time n there are 3 containers in the hub
At time n+1 there are 10 containers in the hub
At time n+2 there are 2 containers in the hub
The model may have missed evaluating the condition at time (n+1) which is why your transition would not be triggered.
To address this issue, I have 3 possible suggestions:
Do not use a condition transition. Instead, use a message. For example, if you are storing the containers in a queue, then, on the "On Enter" and "On Exit" fields of the queue, add the condition:
if(queue.size >= main.hub.numberOfContainers)
<send msg to the statechart>
Use a cyclic event to check if the condition is met every second or millisecond or whatever time period makes sense to you. When the condition is met, send a message to trigger the transition. But the problem with this method is that it might slow down your model with poor performance.
Use the onChange() function. This function is used to signal to your model that a change happened and the condition trigger needs to be evaluated. So, you need to make sure to place onChange() whenever a change that might cause the condition to become true happens. In the example provided under option 1 above, that would be in the fields of the queue "On Enter" and "On Exit".
Is there an option on Active MQ level to preserve the order of execution of messages in case of an exception? . In other words, assume that we have inside message ID=1 info about an object called student having for example ID=Student_1000 and this message failed and entered in DLQ for a certain reason but we have in the principal queue message ID= 2 and message ID = 3 having the same ID of this student (ID=Student_1000) . We should not allow those messages from getting processed because they are containing info about same ID of object as inside message ID = 1; ideally, they should be redirected directly to DLQ to preserve the order of execution because if we allow this processing, we will loose the order of execution in case we are performing an update.
Please note that I'm using message groups of Active MQ.
How to do that on Active MQ level?
Many thanks,
Rosy
Well, not really. But since the DLQ is by default shared, you would not have ordered messages there unless you configure individual DLQs.
Trying to rely on strict, 100% message order on queues to keep business logic simple is a bad idea, from my experience. That is, unless you have a single broker, a single producer and a single consumer and no DLQ handling (infinite redeliviers on RedeliveryPolicy).
What you should do is to read the entire group in a single transaction. Roll it back or commit it as a group. It will require you to set the prefetch size accordingly. DLQ handling and reading is actually a client concern and not a broker level thing.
I have to run multiple jobs upon a request from the user. However only one is important among those.
So i have a MainWorker in whose perform method I call different other workers like Worker1, Worker2.
Worker1 and Worker2 can be delayed, I need to give priority to MainWorker.
so here is how my perform method looks now
class MainWorker
def perform( user_id )
User.find( user_id ).main_task
Worker1.perform_async( user_id )
Worker2.perform_async( user_id )
end
end
I might have more sub workers coming up later. I want to know if this is a good practice or there is a much better way to do this. I however give custom queue names and priority to those based on the worker.
There are some 3rd party add-ons for Sidekiq. See here: https://github.com/mperham/sidekiq/wiki/Related-Projects
One that might be helpful for you is: SidekiqSuperworker.
I have a system that seems to be working fine, but when a certain process writes a message, I get 10 messages appear in the queue. They are all almost duplicates, but the last section of the message id is incremented.
Example:
c6743810-65e6-4bcd-b575-08174f9cae73:1:1:1
c6743810-65e6-4bcd-b575-08174f9cae73:1:1:2
c6743810-65e6-4bcd-b575-08174f9cae73:1:1:3
c6743810-65e6-4bcd-b575-08174f9cae73:1:1:4
.
.
.
What does this mean? From what I can tell, the process is only writing one message.
Nevermind, I found it... The process WAS writing multiple messages, but using the same producer and transaction. ActiveMQ seems to use this as a session ID or something of that sort. Feel free to expand on this topic if you deem it necessary.
The message id is generated to be globally unique - and consists of a combination of a your host, a unique MessageProducer Id and an incrementing sequence for each message