We have a business requirement that forced us to do a live refresh of stocks in Solr every after a user orders. What I did was created a new action in our orderProcess.xml that will put a lock, run our cronjob that will do the indexing, wait until the cronjob finishes then release the lock after. This caused an issue wherein our order confirmation emails were not sending because the lock got stuck and multiple business processes were affected because the lock was not yet ready. We were able to resolve this by temporarily introducing a new dynamic process definition without the new action and setting it in store level.
Now, my question is, what could we do to improve our process? Could I still use the new action class and just change my logic or overhaul the whole update indexing process? Hopefully, you can help me determine what I’m doing wrong.
orderProcess.xml
<action id="sendOrderPlacedNotification" bean="sendOrderPlacedNotificationAction">
<transition name="OK" to="decrementStockOrderPlaced"/>
<transition name="NOK" to="success"/>
</action>
<action id="decrementStockOrderPlaced" bean="decrementStockOrderPlacedAction">
<transition name="OK" to="refreshSolr"/>
<transition name="NOK" to="success"/>
</action>
<action id="refreshSolr" bean="refreshSolrAction">
<transition name="OK" to="success"/>
<transition name="NOK" to="success"/>
</action>
<!-- Need to addin other actions replicate order etc -->
<end id='error' state='ERROR'>All went wrong.</end>
<end id='success' state='SUCCEEDED'>Order process finished.</end>
RefreshSolrAction.java
@Override
public Transition executeAction(OrderProcessModel orderProcessModel) throws Exception {
if (Objects.nonNull(orderProcessModel.getOrder())) {
final OrderModel order = orderProcessModel.getOrder();
BaseStoreModel storeModel = order.getStore();
ReentrantLock lock = getStoreLock(storeModel.getUid());
lock.lock(); // Acquire the store-specific lock
try {
Optional<SolrIndexerCronJobModel> updateCronJob = //Find cronjob based on cronjob code
// Perform the indexing operation within a lock to ensure sequential execution
if (updateCronJob.isPresent()) {
cronJobService.performCronJob(updateCronJob.get());
waitForCronJobCompletion(updateCronJob.get());
}
} finally {
lock.unlock(); // Release the lock
}
}
return Transition.OK;
}
private void waitForCronJobCompletion(SolrIndexerCronJobModel cronJob) throws InterruptedException {
while (!cronJobService.isFinished(cronJob)) {
Thread.sleep(10000); // Sleep for 10 seconds before checking again
}
}
private ReentrantLock getStoreLock(String storeUid) {
return storeLocks.computeIfAbsent(storeUid, k -> new ReentrantLock());
}