Section 15.4. Server-Side Client Queues

15.4. Server-Side Client Queues

The concept of queuing up clients comes in handy when building applications that authenticate users through a call to a database or whenever your server-side code needs to perform an asynchronous operation, the results of which affect the clients connected to the application.

Consider a multi-instance application, for example. When building a complex FlashCom application, it's common to use different application instances to partition users into different "rooms." Each of these rooms will have some information that differentiates it from other rooms, such as a room name or a room password.

These room properties are usually kept in a database, which maps application instance names to the room-specific properties and features. The database could simply be a shared object in a separate "manager" application instance (look at the lobby/rooms application in Chapter 9 for an example) or in a database system connected to FlashCom through server-side Flash Remoting.

Either way, retrieving these properties from the database requires an asynchronous operation, such as a server-to-server call or a Flash Remoting call.

Now imagine that clients need to have this information in order to function properly (for example, the room UI needs to display the room name at the top of the users' screens).

The most logical thing to do is to put the code that retrieves these properties in the onAppStart( ) handler of your application, like this:

 application.onAppStart = function (  ) {   // Perform the Remoting or server-to-server call here   nc = new NetConnection(  );   nc.connect("rtmp://someserver/someapp");   nc.onStatus = function (p_info) {     if (p_info.code == "NetConnection.Connect.Success") {       application.roomInfoHandler = new GetRoomInfoHandler( );       this.call("getRoomInfo", application.roomInfoHandler);     }   }; }; 

The problem is that onAppStart( ) is not run until the first client connects, and it is run just before the onConnect( ) handler for that client. So this is what's going to happen:

  1. Client connects to a room instance that's not yet running.

  2. application.onAppStart( ) runs, and the server-to-server (or Remoting) connection is started.

  3. application.onConnect( ) runs, and room properties are still unknown.

  4. Some time elapses.

  5. Room properties arrive .

So, what can we do in the onConnect( ) handler? We have two options:

  • If the room properties are not vital , we can simply accept the client connection (through application.acceptConnection( ) ) and notify the client of the room properties when they arrive, through a server-to-client call. The client might be able to use a subset of the application functionality while the room properties are unknown.

  • If the room properties are very important for the client (for example, if it's the password that users need to provide in order to enter a room), we need to put the client "on hold" until the room properties are returned asynchronously.

Now imagine that 100 people connect right around the same timeas is possible for a large lecture or if, for example, your application has some automatic reconnecting code and a server briefly goes downall while the initial asynchronous call to get the room properties is still pending.

In this case, you need a client queue, which can be implemented as simply as this (you can place GetRoomInfoHandler( ) at the top of main.asc as shown here or in its own file):

 // getRoomInfo result handler. function GetRoomInfoHandler (  ) {   this.queue = new Array(  );    // Create queue } GetRoomInfoHandler.prototype.onResult = function (p_val) {   // Save results.   application.roomName = p_val.name;   application.roomPwd = p_val.pwd;   // Set flag.   application.roomIsReady = true;   // Flush queue.   for (var i = 0; i < this.queue.length; i++) {     application.acceptClientWithRoomReady(this.queue[i]);   }   // Clean up queue.   this.queue = new Array( ); }; GetRoomInfoHandler.prototype.addToQueue = function (p_client) {   this.queue.push(p_client); }; //- application.onAppStart = function ( ) {   // Perform the Remoting or server-to-server call here.   nc = new NetConnection( );   nc.connect("rtmp://someserver/someapp");   nc.onStatus = function (p_info) {     if (p_info.code == "NetConnection.Connect.Success") {       application.roomIsReady = false;       application.roomInfoHandler = new GetRoomInfoHandler( );       this.call("getRoomInfo", application.roomInfoHandler);     }   }; }; application.onConnect = function (p_client) {   if (application.roomIsReady)     application.acceptClientWithRoomReady(p_client);   else     application.roomInfoHandler.addToQueue(p_client); }; application.acceptClientWithRoomReady = function (p_client) {   application.acceptConnection(p_client);   p_client.call("setRoomInfo", null, {name:this.roomName}); }; 

The code is pretty self-explanatory: we create a result handler for our server-to-server call, with an added addToQueue( ) method, which adds a client to the pending queue. We also use a global application.roomIsReady flag, which is used in onConnect( ) to decide whether to add a client to the queue or accept it right away. Also, we move the application.acceptConnection( ) call to an acceptClientWithRoomReady( ) method, which notifies the newly accepted client of the room properties right after accepting it (note that, for added security, we don't pass the room password to the client).

As we have seen, a queue can be nothing more than a simple array attached to the result handler of the asynchronous call.

This concludes the "tips-and-tricks" section of this chapter. The next section covers a frequently requested feature that is complicated to implement, so you may want to go get some coffee now!



Programming Flash Communication Server
Programming Flash Communication Server
ISBN: 0596005040
EAN: 2147483647
Year: 2003
Pages: 203

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net