0

I have a table in a page that shows summary data.
These data come from a summary database table. I need to refresh this table shown in the page if the underlying table gets updated.
The way that I know is to reload the page every X seconds.
But what I am interested in is to update the table whenever the table is actually updated.
What is the standard solution for this? The only approach I was able to think was to add some extra column to the table to have the row ids that have been updated and somehow "poll" on this column every X seconds. I think it could work but it seems horrible solution and I was wondering what would be the standard approach to this (I assume common) problem.

Update:
Just to add more content. My question is not so generic. I have only 1 specific part of the code that updates the table and the update is under my complete control. It is not like a table that gets updated by multiple sources

Dan Froberg
  • 168
  • 8
Jim
  • 18,826
  • 34
  • 135
  • 254
  • Why close?Can I improve the question somehow? – Jim Feb 19 '14 at 19:31
  • You'll need some sort of server-side framework for this. In .Net, I would create a SignalR app (which leverages web sockets for real time communication) and then setup a dependency on my database table that would raise an event when its contents had changed. – Mister Epic Feb 19 '14 at 19:33
  • 1
    This question is very broad and there are many possible solutions. With your 2.3K rep points people here generally figure that you should know not to post questions without showing some effort... – MonkeyZeus Feb 19 '14 at 19:34
  • Overall the easy-way-out would be to create a `setInterval()` and implement a continuous AJAX call every 5 seconds maybe. – MonkeyZeus Feb 19 '14 at 19:35
  • @ChrisHardie:Does the update help? – Jim Feb 19 '14 at 19:35
  • Not really, still no code from you... – MonkeyZeus Feb 19 '14 at 19:36
  • @MonkeyZeus:Yes but in the AJAX call what do I retrieve? – Jim Feb 19 '14 at 19:36
  • @MonkeyZeus:What code do you need?This is a design question at this step.I am trying to setup my table so that the AJAX can be efficient – Jim Feb 19 '14 at 19:37
  • You shouldn't be using AJAX if you can help it. Web Sockets are the way to go. But there are indeed many different ways to go about executing this. I gave a $.50 explanation with .Net tech, but I have no idea what your environment is. – Mister Epic Feb 19 '14 at 19:38
  • @ChrisHardie:No AJAX?I thought that was the standard way.So you are talking about comet? – Jim Feb 19 '14 at 19:39
  • @Jim, please have a look here for a fuller explanation: http://www.html5rocks.com/en/tutorials/websockets/basics/ – Mister Epic Feb 19 '14 at 19:42

4 Answers4

2

Communication System

You have multiple ways to create a sort of dynamic page that auto updates (i.e. like Facebook).

  1. Basic. The most basic method is, like you said, polling the server every X seconds (having a JavaScript infinite $.ajax({}); loop that is called each X seconds) to see if there are new things on the server. This is a valid solution, and it has been used in the past.

  2. Push. A second way of doing this and is quite used also, is long polling or push. If you are using an asynchronous framework on the backend (i.e. Node.js, Tornado, Twisted etc.) you can very easily use this solution since it has almost no performance cost. With other back end frameworks like PHP or Django, this is not a good way of doing it since you create a process per each request that stays open until something is updated or the time out for the Http connection is being reached (people put most of the time, from what I saw, a 30s timer on the long polling).

  3. Sockets. This is the newest and most unsupported way of doing this. Not all browsers have yet access to WebSockets. As before an asynchronous framework is better for this approach.

If you are having a CGI base back en framework (this implies WCGI, FastCGI, etc) like Django , PHP, Flask, etc. then you are better taking the first approach, which is the most basic one. Taking any other is very resource costly for your servers. If you have an async back end, then either the 2nd or 3rd approach are ok. I must say that the web sockets approach is a bit harder to get into, program correctly and support the framework.

Database System

After you chose what you want to use as a communication system, your database design need to reflect the new query types you need to do.
Let's say the user wants to see all the new changes since he loaded the page.

  • A simple way of doing it would be to have a date on each row, which is the time of the last change. Query for all rows that changed since last query time.

  • A more complex way of doing it is to implement a full notification system. For each change or new row, a new notification about it will be added. You can do a relation between a user and notifications to know if he has already seen it, and have a job scheduled each 24h to delete old relations. But very soon this all becomes bloated. I prefer using a NoSQL database (JSON one like CouchDB) for the notification system. You can easily change the structure of the documents and create specific views for all notifications. It is more lenient to work with than a relational database. If you want to know if your data has changed after user loaded the page, all you have to do is query the type of notification (what data/table you are observing for changes) and get the ones with a creation date newer than the last queried time and also non-viewed. Since your table always reflects the last state, on page load you query the table and afterwards you only query for changes or here called notifications.

My Personal Take

If you are having a CGI backend, for a complete notifications system you will require a specific back end structure added on top of yours for either long polling or sockets. Don't forget your client needs to also have logic on how to react to the new server handlers. For quick results, if your job specifies this, you are better suited with just a script in your page that reloads the page each 1 minute or so.

If you are already using an asynchronous framework, you can easily add the notifications functionality but will require hard work on the database, especially if the notifications are in a relational one. If you decide to add a new database specifically for this, it requires also a lot of app logic on your back end plus the training for it.

Hope I helped, cheers!

AlexandruB
  • 678
  • 3
  • 15
  • Concerning the (1) basic approach.I understand this but my OP was about this specific approach how to detect exactly what has been updated.Are you recommending to reload the whole table every X seconds? – Jim Feb 19 '14 at 19:51
  • You have to create a handler on the server side for that. Unless your client side can query your database (I imagine you store your information there), you need to create a handler which will query for you and return what has changed. Of course if you want to support a "has changed" system, you need to make your database design with that intention. For example have a date on your row which is the last time you modified it and then have a date on your query to know the last time you queried for changes. – AlexandruB Feb 19 '14 at 19:53
  • `Of course if you want to support a "has changed" system` That is exactly what I am interested in.I could e.g. keep an extra column that would have value only in the first row of the table having e.g. the ids that were most recently updated but this seems horrible solution and I am looking for alternatives – Jim Feb 19 '14 at 20:22
  • It is a "horrible" non-scaling solution but it is the quickest to be done. An alternative and the one I am using is a complete notification system. When something new comes in, it adds to the notification tables (that's what you query). A simple design could be [this](http://stackoverflow.com/questions/1887602/facebook-like-notifications-tracking-db-design/1892311#1892311). I have previously seen one really good on the stack overflow but could not find the link for it. For notifications I always use a noSQL db (CouchDB for me), it is less bloated by relations and more easy to work around. – AlexandruB Feb 19 '14 at 20:33
  • So in the notification table for each row added/updated the new table stores each id/per user? – Jim Feb 19 '14 at 21:54
  • Don't forget your data tables have the latest version of data. Your notifications serve 2 purposes. One is there so the client (here browser) requests a handler that queries only a limited amount of data (not as big as the original table) so he can be up to date with the latest version. On a page load you load from the database, on the page script you query for the notifications. The second type of notifications which have a user relation, are the ones you want the user to see, for example a new message that is addressed to him. Until he sees it, it will not be able to be deleted. – AlexandruB Feb 19 '14 at 23:18
  • But still, if I query for limiting amount of data I would need to process the displayed table and filter out the rows to update/delete and add potentially new rows.This seems to me too much trouble with no clear gain.Isn't a table refresh the same? – Jim Feb 20 '14 at 22:37
  • Depends on the type of DB you use. InnoDB is only row locked so since you always append new data you can query all but the "latest" (or better, now writing to the db) notifications. While changing the original table often, makes it so your reads are queued after the writing so it is slower. You do have some gains just by doing this. I would still use the simplest case, because if you don't have much activity on your DB it is a better gain/effort ratio. – AlexandruB Feb 23 '14 at 17:42
1

There are a lot of different approaches to solving a problem like this. The best and most efficient solutions will involve some help from your server to know when/what has changed. Here are some ideas:

  1. Use a websocket connection to your server so your server can notify when the back-end data has changed and the client can then request fresh data.

  2. Deliver some sort of "last transaction id" with the original page and then use an ajax call on a polling interval to ask the server if the data has changed since this last transaction id. If so, request the new data. If not, nothing to do. This keeps you from getting the data over and over when nothing has actually changed.

  3. Alternatives to a websocket are long polling of http push which can also be used (particular in clients that don't support websockets) to allow the server to notify the client when there is new data.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • +1.I like (2).But how a "last transaction id" would be defined?Is it something "stored" in the database level? – Jim Feb 19 '14 at 19:49
  • @Jim - yes a last transaction id would have to be something your database or server implemented/supported. – jfriend00 Feb 19 '14 at 19:51
  • This is the part that I don't get.I am using MySQL.Would that be an actual transaction id?In my code I am just doing `UPDATE TABLE SET...`. Or is it some "application" construct of some kind?Would it be possible to elaborate a bit on this please? – Jim Feb 19 '14 at 19:54
0

This is the premise of WebSockets (http://socket.io for a shim). You'll need (as already mentioned) a server (such as Node.JS) to support the WebSocket functionality -- most modern web browsers support this API on the client-side.

Web Sockets API (http://www.w3.org/TR/2012/CR-websockets-20120920/) allows the browser to continuously communicate data to a server (and vice-versa).

If a database record is updated, you can set a trigger to communicate this data back to the client. Look at comment board systems (exactly like the one we're using here on StackOverflow) for examples -- since there's an enormous amount of information already available on the web, I don't believe it necessary to go into great detail here.

Further reading and tools:

As mentioned by others, you may do polling through setInterval (preferred) or setTimeout methods using AJAX. Don't forget to create a variable to store the ID of the set[Fn] in case you (or the user) wish(es) to cancel it:

var pollID = window.setInterval(function poller(){ getAjaxData(); }, 2000);
if (noUpdate) window.clearInterval(pollID);
Joe Johnson
  • 1,814
  • 16
  • 20
  • What is the `pollID`? – Jim Feb 19 '14 at 19:57
  • pollID is a somewhat random number generated by the user-agent (browser) when invoking setInterval or setTimeout. It is an integer typically in the range of 1 to 100000 or so if my memory serves. The actual number is NOT important... it is simply a reference so that you can stop a setInterval or setTimeout from executing. – Joe Johnson Feb 19 '14 at 20:05
0

Polling is the easiest way. It will look like this:

(function poll() {
  $.ajax('/myTableData', {
    success: function(data) {
        updateTable(data);
    },
    complete: function() {
       setTimeout(poll, 8000); //every eight seconds
    }
  });
})();

And then you'll add the endpoint /myTableData to your server.

Google Docs, which supports real-time collaboration, polls at the time of this writing. However, it is more sophisticated in that the poll are "long": they last as long as it takes until new data arrives, or certain amount of time passes (e.g. 40 seconds), whichever comes first. That reduces the amount of polling.

Alternatively, you could look into websockets which are supported in modern browsers (IE 10+).

Paul Draper
  • 78,542
  • 46
  • 206
  • 285
  • The problem with this method (which does work!) is that you needlessly poll for changes at a random interval (N seconds). It may be difficult to extrapolate how often the data changes and the typical time the user stays on the page... especially as needs change. – Joe Johnson Feb 19 '14 at 19:48
  • Thanks for this code sample.But what is exactly `updateTable`?Does it update the *whole* table?Only the part that has been updated?But then we go to my original question, how can I know **which** rows need update? – Jim Feb 19 '14 at 19:52