Phil Wallach

I follow where my mind leads …

Phil Wallach header image 2

OpenLaszlo: replacing a “persistent connection” with an idle loop

July 2nd, 2007 · No Comments

The OpenLaszlo documentation states that the persistent connection functionality should not be deployed for production purposes, except for low-volume non-critical applications.

This may be in part due to the model of holding an open connection between a server and a client over the Internet. Such solutions typically do not scale well (requiring back end servers to handle many thousands of open connections) and have difficulty recovering from broken connections.

I implemented a persistent connection to push data from the server out to clients. I found that messages over ~2K caused the client loader to die, so no further messages, asynchronous or not, could be received. I also found that race coniditions arose between client operations and the server data push, disrupting user experience and causing errors.

In the end I removed the persistent connection functionality and replaced it with a polling loop. A polling loop is simple, reliable, and flexible.

Polling

The core of the polling loop executes as an idle event handler. The handler:

  1. Checks if the loader is doing any work. If the loader is working then we consider the system busy, so to avoid race conditions and access/update collisions the handler gracefully exits.
  2. Checks to see if (in my case) 2 seconds has passed since the last update. To track the last update time I use the “update” attribute.
  3. If both these conditions are OK, then we place a request for the next batch of updates and refresh our update timer.


<attribute name="update" type="number" value="0" />
<handler name="onidle" reference="LzIdle">
    if (LzLoadQueue.openConx > 0) return;
    
    var now = (new Date()).getTime();
    var then = this.getAttribute('update');
    if ((now - then) > 2000)
    {
        var d = canvas.datasets.???;
        var p = new LzParam();
        p.addValue(???, ???, true);
        d.setQueryString(p);
        d.doRequest();
        this.setAttribute('update', now);
    }
</handler>

The response

Processing the response is no different from processing any other response, except in my case I disable updates for the duration of processing by setting the update counter to a very large value, before refreshing the update timer at the end of processing to “schedule” the next update.

<datapointer xpath="values:/*">
    <handler name="ondata">
            canvas.setAttribute('update', Infinity);
            ... process here ...
            var now = (new Date()).getTime();
            canvas.setAttribute('update', now);
    </handler>
</datapointer>

Management

To refresh the timer and defer the next update (as above):

var now = (new Date()).getTime();
canvas.setAttribute('update', now);

To force an update as soon as possible:

canvas.setAttribute('update', 0)

To prevent updates altogether (until update is re-set):

canvas.setAttribute('update', Infinity);

Resources

For a persistent connection tutorial, have a look at http://jackhung.tripod.com/lpsagent/quoteAgent/main.html.

Tags: OpenLaszlo

0 responses so far ↓

  • There are no comments yet...Kick things off by filling out the form below.

Leave a Comment