Friday, August 1, 2014

Handling Long Conversations in Web Application

Long conversations in web applications are characterized by the multi step action that a user has to do to accomplish the task. For example shopping cart or booking a reservation are characteristic examples of such long conversations. Such long conversations create intermediate data which cannot be committed to the database till the user confirms her action. For example a user who is doing a reservation of a flight might go through the steps but may change his mind mid way and abort the whole things. Web works on Http protocol which is a stateless protocol and this makes the job harder as we cannot save the intermediate data in some in memory objects or structures. Modern day servers do help us in this regard because they bring the notion of session, which is basically attached to each unique user conversing with the system.
To handle the issue of maintaining the transient user actions, there are couple of strategies that can be employed. Let's go through each of the strategies and understand what each has to offer and what are the shortcomings.

Maintaining data in session

This is the most common and easy strategy to employ. The intermediate data is kept in the session and persisted only when the user confirms it. The downside is that with time when more and more variables are pushed into the session it starts becoming a maintainable headache comes. Another problems that often come is that the same attribute name might get used in two different parts of system and becomes quite difficult to debug. One good strategy that can be employed is to make a class which contains the state of the session and exposes api to save and retrieves from session. And forbid everyone to access session directly.
class SessionContextDataHolder{
//Put all the variables are. Rather than making a Map here
//let all the variables to be outlined separately. This will
//let other to see what variables are stored
public Variable v1; public Variable v2;
Now attach the object of SessionContextDataHolder to individual session. This way all the session saving will happen through one central object.
The other robust way to handle this is to use some frameworks which have flow handling capabilities. For example in Java there is Spring web flow which can handle this by taking care of all the details. It also stores the data in the session but in a more transparent way. It handles double submit also nicely. The downside of systems like web flow is that they work nicely till we have a clean and canned way of doing things. Till the flows are linear these frameworks are a good choice. But the moment the system starts becoming non linear these systems become difficult to handle. Just to clarify, a linear system has a fixed and well defined way of working. You cannot jump around. The non linear system allow to jump to any part of the application from any place.
Another important thing to take care of in this case is the bloating of session. This might reduce the scalability in terms of memory footprint requirement.
Sending the Data to Front End

Another way to handle this is to serialize the data and send it to the client and make the client to send back as part of its request. This is a scalable way at the expense of bandwidth. Also some data may not be amenable for serialization as it might have deep nested structures. Also the data travelling on wire is not secure so might be prone to hacking. For security the data can be encrypted but then it brings another level of complexity. Also encryption and decryption of data itself would take some cpu cycles.
Saving the intermediate data to database

In this all the intermediate data is saved to the database. This keeps the session clean. If the process/conversation is aborted than the data is cleaned either by a cron job on database side or by some scheduler from application layer. Be careful with this approach if you have to deal with multiple state of data and need to go from one state to another. As all data is saved into the database it is difficult to identify the other state. Also it is complex to implement and needs some amount of cleaning up.
Running Long Transactions

Long transactions can be run where the intermediate data is not committed to the database. However this approach might lead to long database connection locking and may also lead to data synchronization issues. Frameworks like hibernate support long conversations. However be careful about the session cache which keeps on growing and may become maintenance headache on its own.
So which one to choose? A million dollar question :-)

No comments:

Post a Comment