Transparent batching, caching etc

77 views
Skip to first unread message

Robert Munteanu

unread,
May 3, 2011, 5:16:13 PM5/3/11
to gwt-di...@googlegroups.com
Hi all,

While the 1.2.0 release was shaping up we've been discussing the next major feature for gwt-dispatch: transparent integration or client-side batching and caching. The complete discussion can be found at pillingworthz's gwt-dispath clone , and we have reached the stage where we could really use feedback from a larger group of people.

The goal of these changed would be to allow gwt-dispatch to transparently handle caching , batching and possibly other scenarios. At an API level, we arrived at these two options:

1. Message-based implementation
We will have a pair of methods on the DispatchAsync similar to sendMessage(Message m), where the message could be a StartBatchingMessage for instance. 
The top-level dispatch will propagate these messages to the implementations which will in turn react ( or not )

2. Controller-based implementation

The root idea is pass in some sort of control object into the implementation via the constructor. class BatchDispatchAsyncController { private final BatchDispatchAsync batchDispatchAsync; BatchDispatchAsyncController(BatchDispatchAsync batchDispatchAsync) { this.batchDispatchAsync = batchDispatchAsync; } void startBatch() { batchDispatchAsync.startBatch(); } void stopBatch(); batchDispatchAsync.stopBatch(); } } BatchDispatchAsync batchDispatcher = new BatchDispatchAsync(new SecureDispatchAsync()); DispatchAsync dispatcher = new ProgressReportDispatchAsync(batchDispatcher); BatchDispatchAsyncController batchController = new BatchDispatchAsyncController(batchDispatcher); Now inject both the dispatcher and the batchController and start stop batching using batchController.startBatch(); batchController.stopBatch();
This can be more complicated, but the more I think about it, the more I believe it is the best option.

Thoughts?

Robert

David Chandler

unread,
May 3, 2011, 6:01:55 PM5/3/11
to gwt-di...@googlegroups.com
My DispatchQueue is essentially #2 and has worked well for me. You're welcome to (improve) the code:

http://turbomanage.wordpress.com/2010/07/16/dispatchqueue/

With option 1, I think tracking state would be a pain and the client code would be hard to follow.

/dmc

Robert Munteanu

unread,
May 4, 2011, 4:58:28 AM5/4/11
to gwt-di...@googlegroups.com
Thanks for the pointer, David. I will take a look at that implementation.

Robert

--
Sent from my (old) computer

pillingworth

unread,
May 12, 2011, 6:01:35 AM5/12/11
to gwt-di...@googlegroups.com
The DispatchQueue is the same sort of thing as the BatchingDispatchAsync. I think this further confirms that it would be good if the framework had a standard way of adding this additional functionality to the DispatchAsync. This way we might get some new and interesting implementations that can be bolted together easily.

So, my thoughts...

Ideally what you want to do it inject/pass around a DispatchAsync interface to all of your code. The actual implementation that is used is decided by the application. A common pattern is to daisy chain the implementations together each adding their own functionality before calling the next in the chain (Decorator pattern?). The tricky bit is is when the code calling DispatchAsync needs to use some specific feature of an implementation of DispatchAsync in the chain that is not accessible from the DispatchAsync interface.

In the case of the batching the client might want to control the starting/stopping of the batching, for the queue implementation it might want to flush the queue, for a cache it may want to clear the cache. If the client wants to control this then arguably it must know that this feature is available. The simple "solution" of using instanceof won't work because the the implementation first in the chain may not be the one that implements the interface.

Some options
1) Add side channel sendMessage() (described in other thread) - changes the interface
2) When building the chain of DispatchAsync you build up some sort of control interface that exposes the various extra bits of functionality and pass this around along with the DispatchAsync (described in other thread). The requires no interface changes but is not elegant - requires a load of code.
3) Use an Eclipse style Adapter class instead of instanceof - ask if the DispatchAsync can be adapted to BatchingDispatchAsync. The adaptor walks the chain, finds the BatchingDispatch and returns this - this needs methods to navigate the chain.

e.g.

    BatchingDispatchAsync bda = getAdaptable(BatchingDispatchAsync.class, dispatchAsync);
    if (bda != null) {
       bda.startBatch();
       ...
       bda.stopBatch();
    }

    @SuppressWarnings("unchecked")
    public static <T> T getAdaptable(Object object, Class<T> clazz) {

        if (object == null) {
            return null;
        }
        if (object instanceof Adaptable) {
            T t = (T) ((Adaptable) object).getAdapter(clazz);
            if (t != null) {
                return t;
            }
        }
        if (clazz.equals(object.getClass())) {
            return (T) object;
        }
        if (object instanceof ChainedDispatchAsync) {
            return getAdaptable((ChainedDispatchAsync)object).getNext(), clazz);
        }
       
        return null;
    }

Personally I like the third approach - then I love the Adaptor stuff. I know not everybody does.




pillingworth

unread,
May 16, 2011, 8:15:04 AM5/16/11
to gwt-di...@googlegroups.com
I have updated the code in the pillingworthz@pillingworthz-batching-dispatch clone to take a slightly different approach based on my last comment.

You join your dispatchers together using the pattern

DispatchAsync dispatchAsync = new BatchingDispatchAsync(new CachingDispatchAsync(new XYZDispatchAsync(new SecureDispatchAsync())));

or build them using GIN.

This is injected/passed around the application as normal and would be used as is.

If you need to get access to a particular implementation then use

CachingDispatchAsync cda = ChainedDispatchAsync.getImpl(dispatchAsync, CachingDispatchAsync.class));
if (cda != null) {
 ...
}

You'll get a value returned if there is an instance of this in the chain. There are issues in that it doesn't handle interfaces, only classes (because GWT does not implement Class.isAssignableFrom()).

It may be a way forward - it may not.


Robert Munteanu

unread,
May 20, 2011, 4:37:18 AM5/20/11
to gwt-di...@googlegroups.com
As long as the DispatchAsync is not changed and the API allows us to
extract high-level participant, I'm happy with it. I've started
discussing the changeset at
http://code.google.com/r/pillingworthz-batching-dispatch/source/detail?r=f05750eacb5d02c1212ef90fd119233f02f39499
.

Robert

--

Brian Lough

unread,
Sep 17, 2011, 9:51:56 PM9/17/11
to gwt-di...@googlegroups.com
I've read through the discussions and get the gist, but I'm not sure of the "why?".  Understand, I'm not criticizing the ideas.  My assumption is there's a hole in my understanding of web-apps.
  • there are many options and levels for caching of server side data
  • JDBC and ORM solutions can handle huge volumes of data
  • application servers, alone or clustered, with or without being fronted by Apache, can handle enormous request volumes
  • one could argue the above applies to the size of the data transfer packets between client and server as well
  • AJAX and the higher degree of sophistication in the client frameworks facilitates splitting out client-side reference data loads
  • there's various ways of leveraging client-side data storage/caching
It seems like this is trying to address a request volume issue.  It's not "(n) requests x (n) clients" hammering the server: that's a server-side issue.  It seems like it has to be "(n) requests x (a bunch) within 1 client".  Seems like that's an application design issue, client-side storage thing, or a "throw up a spinner and let 'em wait" thing.  Am I way off target on this?

Having said the above, I would lobby for two approaches: Event driven and/or Filters.  It seems the former could be implemented and integrated with existing code with "minimal" change to existing code.  Provide an optional default BatchingSubscriber and it's an easy configuration item for us "users".  The latter, well, I'm in love with http://mina.apache.org/'s Filters. As with an Event driven solution, a default BatchingFilter could be supplied.  

Personally, I prefer the Filter approach as I can see where it would provide us "users" with the bigger benefit.  But, either way, I can think of a bunch of different reasons to tap into a "dispatch" filter chain/event bus, all of which I could unit test.


Robert Munteanu

unread,
Sep 21, 2011, 5:09:55 AM9/21/11
to gwt-di...@googlegroups.com
On Sun, Sep 18, 2011 at 4:51 AM, Brian Lough <bkl...@gmail.com> wrote:
I've read through the discussions and get the gist, but I'm not sure of the "why?".  Understand, I'm not criticizing the ideas.  My assumption is there's a hole in my understanding of web-apps.
  • there are many options and levels for caching of server side data
  • JDBC and ORM solutions can handle huge volumes of data
  • application servers, alone or clustered, with or without being fronted by Apache, can handle enormous request volumes
  • one could argue the above applies to the size of the data transfer packets between client and server as well
  • AJAX and the higher degree of sophistication in the client frameworks facilitates splitting out client-side reference data loads
  • there's various ways of leveraging client-side data storage/caching
It seems like this is trying to address a request volume issue.  It's not "(n) requests x (n) clients" hammering the server: that's a server-side issue.  It seems like it has to be "(n) requests x (a bunch) within 1 client".  Seems like that's an application design issue, client-side storage thing, or a "throw up a spinner and let 'em wait" thing.  Am I way off target on this?

You're spot on. The issue is in client responsiveness mostly. Imagine a form which contains multiple drop-downs which need to be populated with reference data from the server. We create individual actions for each drop-down as we want the actions to be reusable between forms.

If we send requests one by one, we make the end-user pay the cost of waiting for the network call to return for each drop-down population request. Instead, by batching we only pay that cost once.

Having said the above, I would lobby for two approaches: Event driven and/or Filters.  It seems the former could be implemented and integrated with existing code with "minimal" change to existing code.  Provide an optional default BatchingSubscriber and it's an easy configuration item for us "users".  The latter, well, I'm in love with http://mina.apache.org/'s Filters. As with an Event driven solution, a default BatchingFilter could be supplied.  

Personally, I prefer the Filter approach as I can see where it would provide us "users" with the bigger benefit.  But, either way, I can think of a bunch of different reasons to tap into a "dispatch" filter chain/event bus, all of which I could unit test.

How would this API look?  Not necessarily its implementation, but basic usage would be useful.

Brian Lough

unread,
Sep 21, 2011, 11:32:45 AM9/21/11
to gwt-di...@googlegroups.com
Thanks, Robert.  Nice to know my quick dip into .NET didn't eat into my frontal lobe too badly. ;-)


The above is short, clear, and concise: probably better than I can do providing an API.  GWT client-side implementation elements wouldn't present too many challenges, I wouldn't think.  I haven't looked at the gwt-dispatch internals yet, so I can't comment on the Filter attachment point.


I'm not an HTML5 heavy, but the above suggests the move is towards leveraging client-side storage/caching.  As a developer, I would target target that to avoid reliance on a framework and keep fine control would be in my hands.  However, having something like Filtering hooks in gwt-dispatch would immediately draw my attention as it would be an intuitive point at which to tie in dealing with my local storage/cache.  Non-HTML5 coders could work their own magic there, providing themselves an isolated migration point to HTML5, or utilize the default BatchingFilter while they wait.

Robert Munteanu

unread,
Sep 23, 2011, 9:32:43 AM9/23/11
to gwt-di...@googlegroups.com
On Wed, Sep 21, 2011 at 6:32 PM, Brian Lough <bkl...@gmail.com> wrote:
> Thanks, Robert.  Nice to know my quick dip into .NET didn't eat into my
> frontal lobe too badly. ;-)
> http://mina.apache.org/chapter-5-filters.html
> The above is short, clear, and concise: probably better than I can do
> providing an API.  GWT client-side implementation elements wouldn't present
> too many challenges, I wouldn't think.  I haven't looked at the gwt-dispatch
> internals yet, so I can't comment on the Filter attachment point.
> http://gearsblog.blogspot.com/2011/03/stopping-gears.html
> I'm not an HTML5 heavy, but the above suggests the move is towards
> leveraging client-side storage/caching.  As a developer, I would target
> target that to avoid reliance on a framework and keep fine control would be
> in my hands.  However, having something like Filtering hooks in gwt-dispatch
> would immediately draw my attention as it would be an intuitive point at
> which to tie in dealing with my local storage/cache.  Non-HTML5 coders could
> work their own magic there, providing themselves an isolated migration point
> to HTML5, or utilize the default BatchingFilter while they wait.

Brian, thanks for the references.

When I'll be back to working with GWT I'll be sure to take a look at
the Mina filter mechanism.

Robert

Reply all
Reply to author
Forward
0 new messages