Futurescale, Inc. PureMVC Home

The PureMVC Framework Code at the Speed of Thought


Over 10 years of community discussion and knowledge are maintained here as a read-only archive.

New discussions should be taken up in issues on the appropriate projects at https://github.com/PureMVC

Pages: [1]
Print
Author Topic: Multiple proxies to connect to AMFPHP  (Read 7567 times)
nicolas
Newbie
*
Posts: 1


View Profile Email
« on: April 23, 2011, 08:41:45 »

I am building a PureMVC application that makes use of AMFPHP to retrieve (a lot of) data.
There are now 40+ different services (AMFPHP functions) that may be called during the application runtime. Some of them simultaneously.

First I started implementing ONE proxy to manage all the calls to the services, sharing only one NetConnection. I soon realized that making a second call when the result of the previous one was not arrived would likely stop the first call. (For example, upon login I simultaneously call a service "checkMails" and a service "getNews").
So, I added an Array to this proxy which contained all opened NetConnections to AMFPHP. (And removing from array when the result arrives).

I am now rewriting this part,
I wrote a class "AMF_Proxy" that extends "Proxy", and several classes extending "AMF_Proxy" (one for each AMFPHP service). So that I now have multiple proxies created dynamically, one for each call to an AMFPHP service. When the service returns a result or fails, the proxy is supposed to remove itself.

LoginCommand.as
:
/*
Simple Command - PureMVC
 */
package com.project.controller
{
import org.puremvc.as3.interfaces.INotification;
import org.puremvc.as3.patterns.command.SimpleCommand;
import org.puremvc.as3.patterns.observer.Notification;
   
import com.project.ApplicationNotifications;
import com.project.ApplicationParameters;
import com.project.model.*;
import com.project.model.amf.*;

/**
* Login
*/
public class LoginCommand extends SimpleCommand
{
override public function execute(note:INotification):void
{
var notificationData:Object = note.getBody() as Object;
facade.registerProxy( new AMF_LoginProxy(notificationData) );
}
}
}

AMF_Proxy.as
:
package com.project.model.amf
{
import flash.events.*;
import flash.net.*;
import flash.system.Security;
 
import org.puremvc.as3.interfaces.IProxy;
import org.puremvc.as3.patterns.proxy.Proxy;
import org.puremvc.as3.interfaces.IMediator;
import org.puremvc.as3.interfaces.INotification;
import org.puremvc.as3.patterns.mediator.Mediator;

import com.project.utils.MyUtils;
import com.project.model.*;
import com.project.model.vo.*;
import com.project.ApplicationNotifications;
import com.project.ApplicationParameters;

public class AMF_Proxy extends Proxy implements IProxy
{
// Cannonical name of the Proxy
                public static const NAME:String = "AMF_Proxy";

public var connection:NetConnection;
private var responder:Responder;

public function AMF_Proxy(calldata:Object = null)
{
// To register multiple times
super(MyUtils.getUniqueProxyName() + NAME);

// Initializing
connection = new NetConnection();

connection.addEventListener(IOErrorEvent.IO_ERROR, IOerrorConnection);
connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, errorConnection);
connection.addEventListener(AsyncErrorEvent.ASYNC_ERROR, errorConnection);
//connection.addEventListener(NetStatusEvent.NET_STATUS, status );

// Initiate connection on creation
this.connect();

this.serviceCall(calldata);
}

private function connect():Boolean
{
try
{
connection.connect((facade.retrieveProxy (DataProxy.NAME) as DataProxy).gatewayURL);
}
catch (error:Error)
{
trace("Error accessing Gateway");
}
return true;
}

public function serviceCall(calldata:Object = null):void
{

}

public function onServiceResult(result:Object):void
{

}

private function disconnect():void
{
connection.close();
}

//PHP Fault
public function onFault(fault:Object):void
{
for (var i in fault)
{
trace("onFault: " + fault[i]);
}
this.destroy();
}

private function IOerrorConnection(e:IOErrorEvent):void
{
trace("IO_ERROR: " + e);
this.destroy();
}

private function errorConnection(pEvt:Event):void
{
trace("errorConnection: " + pEvt);
this.destroy();
}

public function destroy():void
{
this.disconnect();
facade.removeProxy(this.getProxyName());
}

// Method to remove everything
override public function onRemove():void
{
// Remove All Listeners
connection.removeEventListener(IOErrorEvent.IO_ERROR, IOerrorConnection);
connection.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, errorConnection);
connection.removeEventListener(AsyncErrorEvent.ASYNC_ERROR, errorConnection);

try
{
connection.close();
connection = null;
}catch (e:Error)
{
trace("** Error");
}
}
}
}

AMF_LoginProxy.as
:
package com.project.model.amf
{
import flash.events.*;
import flash.net.*;
import flash.system.Security;
 
import org.puremvc.as3.interfaces.IProxy;
import org.puremvc.as3.patterns.proxy.Proxy;
import org.puremvc.as3.interfaces.IMediator;
import org.puremvc.as3.interfaces.INotification;
import org.puremvc.as3.patterns.mediator.Mediator;

import com.project.utils.MyUtils;
import com.project.model.*;
import com.project.model.vo.*;
import com.project.ApplicationNotifications;

/**
* Login
*/
public class AMF_LoginProxy extends AMF_Proxy
{
public function AMF_LoginProxy(calldata:Object)
{
super(calldata);
}

override public function serviceCall(calldata:Object = null):void
{
var serviceResponder:Responder = new Responder(onServiceResult, onFault);
try
{
connection.call("User.logIn", serviceResponder, String(calldata.nickname), String(calldata.password));
}
catch (error:Error)
{
trace("Error calling serviceCall. " + error.getStackTrace());
}
}

override public function onServiceResult(result:Object):void
{
if (result.res == "OK")
{
sendNotification(ApplicationNotifications.LOGIN_OK, result);
}else {
sendNotification(ApplicationNotifications.LOGIN_KO, result);
}

this.destroy();
}
}
}

My main concerns are:
* I would like to make sure that every AMFPHP call is handled properly (ie. always gives some result)
* I worry that it won't create too many simultaneous connections that would overload the server

Am I doing wrong?

Thank you.
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #1 on: April 25, 2011, 07:18:00 »

Usually a Proxy is a long-lived actor that hangs around. It not only fetches the data and sends a note to the rest of the app for immediate consumption, but also acts as a holder for that data in case it is needed at some time after the result note has been sent out.

If you instantiate a Proxy every time you make a call you bear a lot of object creation overhead. If you make 5 calls to service X you have to go through creation and destruction of the proxy and its service component each time, which is avoidable by leaving the Proxy registered.

Of course you are using a separate connection for every Proxy, so that's a bit much. You might want to create a ConnectionPoolProxy that would create some NetConnections up front and keep them around. Your AMFProxies would fetch one, use it and return it to the pool when done. This way you could go ahead and instantiate the Proxies and just fetch them and act on them as normal.

-=Cliff>
Logged
Pages: [1]
Print