Closed dazinator closed 3 months ago
I just coded up this example: https://github.com/rebus-org/Rebus/blob/master/Rebus.Tests/Examples/SagaSendsMessagesToItself.cs
It demonstrates how an in-mem saga can send a bunch of messages to itself, which will not actually be sent until the saga data is saved. Moreover, it shows that all subsequent messages get dispatched with optimistic concurrency.
Could you maybe take a look at the example to see where your code differs?
Thank you, I will investigate
One thing at a glance before I get into running the two examples, I use "bus.Send" not "bus.SendLocal" not sure if that makes any difference. The messages sent are routed to another bus's handler, which uses bus.Send() to route messages back to be handled by this saga.
await bus.SendLocal(...);
just means that the the bus will
await bus.Send(...);
with itself as the destination. If you were to explicitly configure the equivalent, it would be something like
services.AddRebus(
configure => configure
.Transport(t => t.Use(..., "my-queue"))
.Routing(r => r.TypeBased().Map<SomeMessage>("my-queue"))
);
// (...)
await bus.Send(new SomeMessage());
Hi @dazinator , did you figure out how your code differed from my example?
Hi @dazinator , did you figure out how your code differed from my example?
I haven't got back into the issue again just yet sorry, but this does seem like a difference.. your example uses SendLocal to route back to the same bus. My test has two buses, and my sage sends a message which is routed to the other bus (different input queue name) which handles it and sends a message back to my saga bus input queue. Both buses are sharing an in memory network created at the start of the test.
Yeah ok, but as mentioned in the previous comment, it doesn't affect how the message is sent, only where it is sent to.
All other things being equal, await bus.SendLocal(..)
should not take as long as await bus.Send(..)
followed by await bus.Reply(...)
in the other end, so to try to reproduce your issue, await bus.SendLocal(..)
would seem like an sharper bet.
I am running a test in memory. It consists of a "manager" app bus, and an "agent" app bus.
The manager app has a saga. When it is initiated, in that same method it also dispatches some messages in a loop - we are talking to 2 or 3.
Thes agent receives this, does some small work, and sends back a
ChangeStepStateCommandMessage
which is correlated to the same saga instance for handling.The issue I see is that, the agent, dispatches several
ChangeStepStateCommandMessage
messages destined for this saga instance, however only one of them gets handled, the rest seem to be dropped complaining about "could not find existing saga data for message"My test is:
InMemoryNetwork
InMemoryTransport
for both busesreturn routing.Sagas(s => { s.StoreInMemory(); s.EnforceExclusiveAccess(); });
I know that messages can be delivered out of order, so I have idempotency checks, and a scheme to discard obsolete messages. However I was not expecting for messages to be discarded without being given the chance to process them in this circumstance.
My gut feeling is that something like this could be happening:
IAmInitiatedBy
method, it is awaiting Bus.Send() to send some messages and perhaps these are dispatched, handled by the agent, which generates messages destined back to the saga instance, before the saga fully completes its SaveChanges() operations? If the saga doesn't persist its record until sometime after it'sIAmInitiatedBy
finishes (I am actually not sure about that) then could this explain why I see the "Could not find existing saga data for message" - because those happen to be the messages picked for the sagaa, before the saga has even persisted?