views:

60

answers:

1

In general, how do you guys handle user update/data freshness interaction with the user (UI issue) in web-apps?

For example:

  • Multi-users web-app (like project management)
  • Login to a "virtual" space
  • People can update project names, etc
  • How to handle a situation such that:
    • user-A and user-B load a project with title "Project StackOverflow"
    • user-B updates the title to "Project StackExchange"
    • user-A updates the title after user-B update operation to "Project Basecamp"

The question I'm asking is from the user perspective (UI) and not about transactional operation.

What do most people do in this situation?

  • What would you do after user-B updates the title in user-A screen/view?
  • What happened when user-A tries to update the title after user-B finished his/her update operation?
    • do you inform user-A that the title has changed and he/she has to reload the page?
    • do you go ahead and change the title and let user-B has old data?
  • Do you do some sort of application-level "locking" mechanism? (if someone is updating, nobody else can?)
  • Or fix the application workflow? (who has the access to be able to change things, etc).

What would be the simplest solution, but at the same time not annoy the user with more dialog/warning messages.

I've encountered this particular problem frequently in a GWT app specifically where domain models are being passed around and refreshing the whole app/client-side isn't the optimal solution in my mind (since it means the whole "loading"/initialization phase must be executed again in this specific environment).

Maybe the answer is to stay away from GWT? :)

Love to hear options, solutions, and advises from you guys.

Thanks

A: 

The general answer to issues of data staleness in a client is either polling, or server push (Comet), depending on how important it is to have up-to-date information.

With polling, your client sends a request for fresh information every N minutes and shows the updated data in the UI (preferably not reloading the whole UI, just parts that have updated).

With server-pushing, your client has a persistent open connection to the server, reconnecting as soon as the connection times out, and whenever the server has new data to tell the client, it does so immediately. This has the advantage of less staleness in the client, but more overhead in total because of all of these persistent connections being made.

Locking is difficult, because it requires a lot of coordination among all parties. The server has to tell the second client to ask for a model that it is locked, then tell it again when it's unlocked, and the client has to know whether it still wants to make a change at all (what if user-A made the same change user-B wanted to make?). In general keeping all clients as up-to-date as is reasonable is the best answer.

To work with your example, after user-A updates a model, the server publishes to anyone who cares that the model has been changed, and user-B's client updates accordingly. Same when user-B updates the model, user-A can tell right away (or after their client polls again).

The rocket-gwt project includes support for Comet, and I've heard good things about it, though I've never tried it myself.

A similar option, though not immediately usable, is HTML5 WebSockets, which removes the need for a persistent connection to the server by opening a specialized direct "channel" between the server and the client. Unfortunately, WebSockets are currently only supported on a small subset of browsers. Hopefully as adoption grows this will be a better option. That being said, if you want to use WebSockets in GWT, I have written some code to do it (shameless self-promotion)

Jason Hall
Hi Jason,Thank you for the detailed answer (unfortunately I can't +1 you yet according to the reputation rule). I was hoping to avoid either solution (polling or comet) because that would add an extra layer/complexity to the web-app itself. Client-side polling would require a Xms number that plays well with most users. But if some users would perform the update operation faster than the polling time limit, additional handling would be required (telling them that someone else have already updated the info).
edwin.nathaniel
You definitely don't want to be polling more than once per second, or even once per minute. So then the problem becomes one of knowing when two write operations conflict, giving one user in that case an error message, and showing them the current state of the data so that they can decide if they still want to make a change. This will probably be more of a question for your server-side architecture, particularly your database layer. Is your server talking to a separate database server, and what kind of database is it?
Jason Hall
The database is a typical RDBMS (let's say MySQL). One of the projects I used to work on had to use version for every persisted object. One of the advantages of using version is to detect this particular issue. But it feels like an added complexity.
edwin.nathaniel