W3C home > Mailing lists > Public > public-webapps@w3.org > October to December 2009

Re: [WebSimpleDB] Introduce a pause/resume pattern for coordinated access to multiple stores

From: Nikunj R. Mehta <nikunj.mehta@oracle.com>
Date: Tue, 22 Dec 2009 19:32:03 -0800
Cc: "public-webapps@w3.org" <public-webapps@w3.org>
Message-Id: <40DDD224-E369-4CA0-86B8-0B07C0845B9B@oracle.com>
To: Pablo Castro <Pablo.Castro@microsoft.com>

On Dec 22, 2009, at 5:39 PM, Pablo Castro wrote:

> Whenever we take a callback that's to be called for each item in a  
> set (e.g. with a .forEach(callback) pattern), we need a way to  
> indicate the system whether it's ok to move to the next row and  
> invoke the next callback or not. Otherwise, in scenarios where the  
> callback itself performs an operation that doesn't finish  
> immediately (such as another database async call) the system will  
> keep queuing up top-level callbacks, which in turn may queue up more  
> callbacks as part of its implementation, and execution will be in  
> "some order" that's very hard to predict at best.
>
> This comes up in several contexts. Applications will often need to  
> scan more than one object store in coordination. Query processors  
> will also need this when implementing physical operators for joins  
> and such. A different context would be a system that needs to submit  
> an HTTP request per row, where you may want to use an XmlHttpRequest  
> and unwind after calling open. While the HTTP request is in flight  
> you don't want to move to the next
>
> In most cases one of the key aspects is that we need separate  
> components to work cooperatively as they pull rows from one or  
> multiple scans, and there needs to be a way of controlling the  
> advance of cursors through the rows.
>
> We would like to introduce "pause" and "resume" functions for scans  
> to support this. Since there is no obvious place to put this right  
> now, we could introduce an "iterator" object that can be used to  
> control things related to the current state of the iteration as of  
> when the callback happens, or maybe this is the cursor itself.
>
> The resulting code would look like this (the example uses the single- 
> async-level pattern we're playing around, but these two are actually  
> independent things):
>
> async_db.forEachObjectInStore("people", function(person, iteration) {
>  iteration.pause(); // we won't be done with 'person' until later...
>  var request = async_db.getFromStore("people", person.managerId);
>  request.onsuccess = function() {
>    var manager = request.result;
>    // Do something with both 'person' and 'manager', and now we're  
> ready to process the next person.
>    iteration.resume();
>  };
> });
>
> The nice thing about adding these as methods on the side is that  
> it's completely out of sight in simple scenarios where you may be  
> just scanning to build some HTML for example. Only if you're doing  
> multiple coordinated, async tasks you need to know about these  
> functions.
>
> Regards,
> -pablo
>

The proposed WD can do what you want. You would write the following  
code for async processing, even though the solution is not the easiest  
to follow:

async_db.request.onsuccess = function() {
   var people = async_db.request.result;
   people.request.onsuccess = function() {
     var cursor = people.request.result;
     var eachPerson = function() {
       var person = cursor.value;
       cursor.request.onsuccess = eachPerson;
       people.request.onsuccess = function() {
         var manager = people.request.result;
         // do something with both person and manager
         cursor.continue();
       }
       cursor.request.onerror = function () {
         // do what you will when all the people have been processed
       }
       people.get(person.managerId);
     }
     eachPerson();
   }
   people.openCursor();
}
async_db.openObjectStore("people");

It is difficult to follow the logic above, so I will also give a  
synchronous example:

var people = async_db.openObjectStore('people');
var cursor = people.openCursor();
if (cursor)
do {
   var person = cursor.value;
   var manager = people.get(person.managerId);
   // do something with person and manager
} while (cursor.continue());
// we are done with all the people

As I said earlier, there is something to be said about the  
comprehensibility of the asynchronous code above, but let's look at  
the expressive power separately from ease of programming.

Nikunj
http://o-micron.blogspot.com
Received on Wednesday, 23 December 2009 04:06:46 GMT

This archive was generated by hypermail 2.3.1 : Tuesday, 26 March 2013 18:49:35 GMT