on 10-03-2014 11:15 AM
Hi all,
We have implemented full AJAX cart updating system, in spite of this is a good approach in terms of performance we have realized to main issues:
When updating a cart concurrently we deals with errors of type "item 8842464264236 no longer valid (was removed): object no longer valid". Do NOTE different request from same user does not necesarily arrives in the same order neither takes the same time to been executed (obvious). In this scenario cart does not work as it should.
Our current solution is to serialize (in terms of implementation "synchronize" access) affected requests.
In spite of synchronizing access (no concurrent updates to the same user cart) the cart state for the request n+1 is not necessarily the same that at the end of the request n (I mean, sometimes cart entries are not up to date)
Find attached our current solution but I would like to discuss if this seems to be normal or any further advise
/**
* Synchronizes access to a affected methods and optionally refresh the cart before proceed.
*
* @param pjp
* the join point.
* @param refreshCart
* whether to refresh the cart before proceed.
* @return the original invocation result.
* @throws Throwable
* in case of failure.
*/
private Object doSynchronize(final ProceedingJoinPoint pjp, final boolean refreshCart) throws Throwable
{
final Object result;
// Synchronization mutex is based on HTTP Session and standard Spring MVC behaviour
// In other context may make sense employing the cart ID
final HttpSession httpSession = WebSessionFunctions.getCurrentHttpSession();
if (httpSession != null)
{
final Object mutex = WebUtils.getSessionMutex(httpSession);
synchronized (mutex)
{
LOG.debug("Synchronizing transaction (\"" + pjp.getSignature().getName() + "\")with mutex: \"" + mutex + "\"");
// [1] - Refresh cart if needed (cart exist and is not up to date)
if (refreshCart && getCartService().hasSessionCart())
{
final CartModel cartModel = getCartService().getSessionCart();
if (!getModelService().isUpToDate(cartModel))
{
LOG.info("Refreshing cart \"" + cartModel.getCode() + "\" at \"" + pjp.getSignature().getName() + "\"");
getModelService().refresh(cartModel);
}
}
// [2] - Proceed
result = pjp.proceed(pjp.getArgs());
}
}
else
{
LOG.warn("Unable to identify a mutex for current transaction. No JALO session found");
result = pjp.proceed(pjp.getArgs());
}
return result;
}
[Spring AOP Java File][1] [1]: /storage/temp/1271-cartsynchronizationaspect.java.txt
[Spring Application Context XML File][2] [2]: /storage/temp/1272-spring-sync-config.xml.txt
Yes, this is a common problem. This error usually happens, when a thread tries to read promotionresults that have been modified by another thread.
Your idea is good, but I am not sure about your solution, though. What good will refreshing do, and if you suspect the model not being fresh, calling modelService.isUpToDate() will not give correct result anyway.
What you would need to do is synchronize the whole cart calculation with your session lock to avoid the "no longer valid".
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks indeed Christoph!!
In my case I'm synchronizing more heavily, at controller level (therefore including calculation). I suspect the problem is not only at promotions level but also with cart entries, that is the reason why the region to be sync is greater.
If you agree I will give it a try and later will reduce the portion of code to be synced until getting optimal results.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Am I the unique with problems updating the cart?
Please, any feedback?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
5 | |
1 | |
1 | |
1 | |
1 | |
1 | |
1 | |
1 | |
1 | |
1 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.