In ODC i have 3 apps each I am using as DB service. Apps are exposing crud actions witht the help of Service actiojns.
Now sevice actions calls from different apps as one transaction. So either all call shoud be successful or all should roll back.
How to manage transactions in this context or How to manage distributed transactions in ODC?
Hi Mangesh
These things are hard to offer help because there isn't a single solution and often it really depends on understanding the full domain you are working on. That being said, let me offer some tips.
Domain and Bounded Contexts
Review your app composition - this may sound like "meh", but seriously, a DDD approach fits very nicely with ODCs architecture - so review your apps compositions.
Do you really need them to be bounded in isolation in different apps? Do you need an extra app/context maybe? The concept of "DRY", and reusability is not the exact same here and you want things that belong to the same context(the same language) to be under the same app, even if you have to repeat it in a different app with the same functionality (although in a different context/domain language)
https://success.outsystems.com/documentation/outsystems_developer_cloud/app_architecture/building_a_well_architected_app/
Orchestration vs Choreography
For your scenario, implement one of:
Compensation strategies
Outsystems provides a nice video on some patterns to apply, you will need to apply them:
https://learn.outsystems.com/training/journeys/architecture-patterns-581/distributed-transactions-patterns/odc/629
Essentially, you need to have in mind a full compensation strategy when architecting your scenarios within your domain and contexts, and apply auto-retries, rollbacks, model compensations...
I purposely left out the communication pattern - service/event - because its the least of the problems here. But let me also tip on the following:
Atomicity does NOT play well with these architectures. Expecting for a full orchestrated/choreographed rollback on a single transaction will drive anyone nuts. This is where eventual consistency is helpful - model for your services to EVENTUALLY render the model consistent again, even if your model will lag behind in some cases for a few minutes/hours.
With this in mind, shifting to events will go a long away, where either your orchestrator emits an event for a compensation or, in a choreography, each A,B,C listens to each other for compensation.
Finally, I don't have any .oml to give you, because this is way too abstract of a problem to do that - properly composing your apps in a DDD approach, foreseeing these and a whole lot of other challenges is the way to go - https://success.outsystems.com/documentation/outsystems_developer_cloud/app_architecture/building_a_well_architected_app/
Thanks @Nuno Damaso
Comprehensve inputs. I am going through it.
I agree there is no solution to it but Your post help me to conclude that
1 - When we have to consume service actions from different applications Need to write roll back logic
2 - Some scenarios we need to implement Retry
3 - Some scenarios need to manage status of the record cancel/delete etc
4 - Some scenarios need to hard delete.
So it is very abstract and depends on business reuirement
Hi @Mangesh Phanse ,
i don't have any experience yet with building large systems in ODC, but let me try anyway to give a more general answer :
Application architectures can be imagined (simplyfied) somewhere on a spectrum between a single big monolith and hundreds of small microservices.
On one end of that spectrum you have transactions, which is an extremely convenient tool for ensuring integrity accross all the data, coming at the cost of the monolith being dense and tightly coupled and hard to maintain a single part without touching much more than you'd like.
On the other end of that spectrum, any meaningfull bit of logic will likely span somewhere between a couple and a dozen of separate microservices that can only do their own thing and can't consider any of the other bits because they are completely decoupled.
This makes all bits agile and changeable without having to consider the world around them, but it comes at a high cost of added complexity, because you will have to put in mechanisms in each microservice to somehow undo what has been done, repairing any change if an event in some other microservice means data integrity is compromised.
And you'll have to make some sort of orchestration logic to keep track of the total picture (which is done by the transaction on monolith side) and tells the microservices to execute repair logic if needed.
Being somewhere in the middle of that spectrum with your application architecture, in O11 you can choose between server actions and service actions, choosing how tightly or loosely coupled things are, so you can choose the level at which you want to have transactionality, without having to push everything in the same module.
With O11 I can use different levels of coupling, where some modules that belong together (same domain) are tightly coupled through server actions, without having to cram all the code in a single module, and the loose coupling/decoupling is put at a higher level, to span code over different domains, using service actions or api's (and in ODC events).
If in ODC you only have service actions available between apps, this will force you to move on the spectrum either more in the direction of monolith, or more in the direction of microservices, the one making your apps large and harder to maintain, the other, making your architecture complex and expensive and harder to develop / test / troubleshoot / ...
Here are some links that are not related to ODC, but talk about the kind of thing you will have to do to replace transactions :
A medium article about O11 service actions
A non-OutSystems article about possible patterns to use
Dorine
Hi @Dorine Boudry
Thanks for sharing information on why . Is there any scenario implemented in the os11 to maintain service action as one transaction or on faliure how to roll back. Please share me oml. Same I can implement in the outsystems
Thanks
Mangesh
No,
by design, it is not one transaction.
Moving towards loose = you have to implement one of the strategies for dealing with distributed transactions, see the links, those are the type of patterns you will have to implement, simply rolling back is not available
Moving towards tight = you have to move more data in a single application to give you the convenience of using a single transaction
The short answer is you need to explicitly handle rollback scenarios when they fail, as service actions run in a different transaction.
Hi @Siya
If you can provide sample OML on how to handle server actions it will be great help