Wednesday, November 18, 2015

Batch RPCs for GWT


We had developed GWT beginning from 2009. Framework was becoming more popular.
Up to a point it was like a dream framework. It was like developing
windows application on browser. It is really capable of whatever you want to.
If you have knowledge in Swing ,it is similar and productivity is unbelievable.

But when project grows, to 200+ pages it became more and more slow.
There were lots of optimizations. We did nearly all of them.
But it was not possible to come up with lightweight product.

I will write small posts with useful ideas about GWT.


Think you have a page which includes independent 10,20 components.
When page is loaded all of them are making their own RPC. This adds big delays
on page loads.

Idea is,do not call RPC wait for 500 milliseconds batch them and call them together.

protected ArrayList<YRPCRequest> reqQueue = new ArrayList<YRPCRequest>( ) ;

    protected ArrayList<AsyncCallback<YRPCResponse>> cbQueue = new ArrayList<AsyncCallback<YRPCResponse>>( ) ;

protected YRPCTimer timer = new YRPCTimer( 500 )
    {
        @Override
        public void run( )
        {
            fireRegisteredRPCs( ) ;
        }
    } ;
 
 
 protected void registerCallImpl( YRPCRequest req, AsyncCallback<YRPCResponse> callback, boolean isCached )
    {
        final long time = System.currentTimeMillis( ) ;
        

       
        this.reqQueue.add( null ) ;
        

        this.cbQueue.add( callback ) ;

        
    }

 
 @RemoteServiceRelativePath( "YRPCServiceGateway" )
public interface IYRPCServiceGateway extends RemoteService 
{
    public static class Util
    {
        public static IYRPCServiceGatewayAsync getInstance( )
        {
            return GWT.create( IYRPCServiceGateway.class ) ;
        }
    }

    public ArrayList<YRPCResponse> serviceMultiplexer( ArrayList<YRPCRequest> reqList ) ;
}


@Override
    public void onSuccess( ArrayList<YRPCResponse> resList )
    {
        lastResponse = resList ;
        try
        {
            long totalServerTime = -1 ;
            for( int ii = 0; ii < this.cbQueue.size( ); ++ii )
            {
                final int i = ii ;

                final YRPCResponse res = i < resList.size( ) ? resList.get( i ) : null ;

    
    
    Scheduler.get( ).scheduleDeferred( new Scheduler.ScheduledCommand( )
                    {
                        private AsyncCallback<YRPCResponse> callback = GwtRpcGateway.this.cbQueue.get( i ) ;

                        @Override
                        public void execute( )
                        {
                            this.callback.onSuccess( res ) ;
                        }
                    } ) ;
            }


            this.reqQueue.clear( ) ;
            this.reqQueue = null ;
            this.cbQueue.clear( ) ;
            this.cbQueue = null ;
        }
        catch( final RuntimeException e )
        {
            e.printStackTrace( ) ;
            throw e ;
        }
        finally
        {
            if( this.isBlocked )
            {
                // YComponentUtils.enableBodyComponent( true ) ;
            }
        }

    }