I send a command from my service impl to the persistent entity
If the command contains certain state, depending on that state I call various external services that return Future(Foo) (not a lagom microservice)
Based on the result of the external call, I need to persist some events/update read model via ReadSideProcessor.
Question:
According to various internet sources, I’m not supposed to perform asynchronous web service calls from my persistent entity. The entity should only work on local data that is provided to it by a command.
What should be the ideal place to put my web service calls then?
@gabox01 it is true that asynchronous call should not be used. Main indication for that is that command handlers do not support Future based responses (intentionally).
Regarding where external service call could be performed these are the options:
in service call implementation, prior to command sending. External service response would “enrich” the command with required metadata. If you require entity info prior to performing external service call you can always query readside or query entity itself.
readside processor (saga pattern)
Your step #2
a) in command handler, when indicated that external service info is required event is persisted (DoingExternalInfoQueryEvent) and entity behavior changes (for example “query external info in progress”).
b) Readside processor would handle this event by calling external service and response would trigger new command SetExternalInfo (handled only in ”query external info in progress”).
c) Command would trigger persisting of a new event that would continue the flow.
Behavior change is not mandatory but ensures clean saga flow.
Solution #2 is more complicated and is used in cases when high level of consistency is required (querying entity metadata from readside or entity is not enough).
If high level of consistancy is not needed then go with #1 (in most cases is this).
Regarding option 2, it is a little bit confusing in Lagom, since I thought read side processor is about updating the read model. What I’m missing here is a generic “event listener”, that for example slick-event-sourcing has:
Most likely I will go with option 1 then, but I really wanted to perform my external calls in response to actual events, and not based on a command’s state.
Actually option 1 is not going to work, because then it could happen that I i call an external service, that changes something, and the appropriate event is not persisted for some reason. So my external calls must be transactionally consistent with the events. Guess I have no other choice than the read side processor route.
@gabox01
It is true that readside processor was designed for updating readside (indicated by required response [BoundStatements] for event handlers).
But on the other hand it can also be used as a generic event processor (doing actions and when done just return empty list of BoundStatements).
Saga, as an alternative to two-phase commit transaction, is something that is not straight forward to implement in Lagom but can be done in the way I described.
I believe Lagom saga feature will be available in the future, offering streight forward implementation.
And what f I want to emit new events from the read side processor? (in response to an event)
Is the only way to do that is to have a reference on the service interface, and issue a new command? (bit messy in my opinion)
@gabox01 event can only be created entity and trigger is command. So you need to send command to entity that will create a new event(s).
You do not need reference to service interface but access to PersistantEntityRegistry that is used to send commands to entity