In the Sales domain, I have 3 entities - Lead, Contact and Opportunity. A lead is injected into the system from many sources and nurtured. If it is a prospect then it is converted into a contact and opportunity(potential future sale). A contact represents the physical person in the CRM.
An api convertLead which converts a lead by
- creating a contact
- creating an opportunity
- marking the lead as converted
In my model, lead, contact and opportunity are different aggregates.
Hence I need to perform a business transaction across 3 aggregates. The problem is I need my api to be sync - that is the response is received in the api, as this api will be exposed to 3rd party, hence I cannot make this business transaction eventually consistent. All Sales CRMs provide sync apis. How do I provide such an api? I am using Domain Driven Design to model my system and Lagom framework for implementing it.
- Do a polling on server side to provide a sync response and keep the transaction eventually consistent
- I do the coordination /flow in the service layer itself, taking a temporary lock on lead aggregate, and performing the business transaction. In case of failure(due to application down etc), the api could not complete execution and the lock will become invalid as it was temporary(lock valid for some seconds). This transient state is to handle parallel transactions(eg. deleteLead). Within the transaction, if due to application failure the api does not complete then the transaction will remain incomplete. In this use case the incomplete transaction is OK business wise. The user will just have to resend the command
- In some use cases, like pick a lead(i.e assign the lead to self), the transaction involves 2 aggregates - lead and userResource aggregate. I have 2 microservices, one managing lead and one managing resource assignment( like the number of leads a user can work on in a territory, finding the best rep for a lead, etc). Here I need the complete transaction to execute or nothing. In this case if I use the above method, I will need to make the system eventually consistent also (apart from flow logic in api) by implementing a saga which finds resource assignment aggregates in blocked state and frees them.
Solution 2 and 3 don't seem a very natural/recommended way. Also there is an overhead with modeling too many transient states. Please recommend what pattern people use to guarantee consistency with sync apis.