parallel remote requests in Tapestry

classic Classic list List threaded Threaded
20 messages Options
Reply | Threaded
Open this post in threaded view
|

parallel remote requests in Tapestry

Тимур Бухараев
Hi,

My pages consist page class and several components inside.

Page and its components needs some information from remote services. I get
this information with blocking calls in setupRender(). For example, if i
need user's profile data, i get it like this:

setupRender() {
 profileData = loadProfileDate(); // blocking call, waiting for the response
}

And now i can use profileData in render to show some information.

The problem is page and components need many remote data, so there are many
serial requests to remote services. It harms latency, because overall
latency is sum of serial requests delays.

I have idea to improve latency, sending requests in parallel. I want make
non blocking function sendRequest, which returns me token. All components
call non blocking sendRequest for remote data, then i'll wait in blocking
call waitResponses(), which wait for all responses.Then component get their
data from token.

Some code for illustration:

MyComponent {
    @Inject
    private RemoteService remoteService;

    private Token<Response> token;
}

void prepareData() {
    token = remoteService.sendRequest(); // non blocking call
}

void setupRender() {
    Response response = token.getData(); // first call is blocking, wait
for all responses, other calls just return data;
}

Why i did not just realize my idea and write this post?

Because i need two separate phases: first for send request, and second for
prepare rendering. All componets should send in first phase, and after get
data in second.

Tapestry have setupRender and beginRender, but they have another order. It
call setupRender and beginRender for first component, and then - for
second. But i need phase 1 calls for all components, then phase 2 call for
all components.

And now my question is: is there any way in Tapestry to create this phases?
Thank you for your attention, sorry for my English.
Reply | Threaded
Open this post in threaded view
|

Re: parallel remote requests in Tapestry

Chris Poulsen
If your prepareData() is non-blocking, why not just call it right before
you do the token.getData() ? (both in setupRender() )

On Tue, Apr 14, 2015 at 1:03 PM, Тимур Бухараев <[hidden email]> wrote:

> Hi,
>
> My pages consist page class and several components inside.
>
> Page and its components needs some information from remote services. I get
> this information with blocking calls in setupRender(). For example, if i
> need user's profile data, i get it like this:
>
> setupRender() {
>  profileData = loadProfileDate(); // blocking call, waiting for the
> response
> }
>
> And now i can use profileData in render to show some information.
>
> The problem is page and components need many remote data, so there are many
> serial requests to remote services. It harms latency, because overall
> latency is sum of serial requests delays.
>
> I have idea to improve latency, sending requests in parallel. I want make
> non blocking function sendRequest, which returns me token. All components
> call non blocking sendRequest for remote data, then i'll wait in blocking
> call waitResponses(), which wait for all responses.Then component get their
> data from token.
>
> Some code for illustration:
>
> MyComponent {
>     @Inject
>     private RemoteService remoteService;
>
>     private Token<Response> token;
> }
>
> void prepareData() {
>     token = remoteService.sendRequest(); // non blocking call
> }
>
> void setupRender() {
>     Response response = token.getData(); // first call is blocking, wait
> for all responses, other calls just return data;
> }
>
> Why i did not just realize my idea and write this post?
>
> Because i need two separate phases: first for send request, and second for
> prepare rendering. All componets should send in first phase, and after get
> data in second.
>
> Tapestry have setupRender and beginRender, but they have another order. It
> call setupRender and beginRender for first component, and then - for
> second. But i need phase 1 calls for all components, then phase 2 call for
> all components.
>
> And now my question is: is there any way in Tapestry to create this phases?
> Thank you for your attention, sorry for my English.
>
Reply | Threaded
Open this post in threaded view
|

Re: parallel remote requests in Tapestry

Chris Poulsen
Or maybe you can use progressive display?
http://jumpstart.doublenegative.com.au/jumpstart7/examples/ajax/progressivedisplayvariations

On Tue, Apr 14, 2015 at 1:36 PM, Chris Poulsen <[hidden email]>
wrote:

> If your prepareData() is non-blocking, why not just call it right before
> you do the token.getData() ? (both in setupRender() )
>
> On Tue, Apr 14, 2015 at 1:03 PM, Тимур Бухараев <[hidden email]>
> wrote:
>
>> Hi,
>>
>> My pages consist page class and several components inside.
>>
>> Page and its components needs some information from remote services. I get
>> this information with blocking calls in setupRender(). For example, if i
>> need user's profile data, i get it like this:
>>
>> setupRender() {
>>  profileData = loadProfileDate(); // blocking call, waiting for the
>> response
>> }
>>
>> And now i can use profileData in render to show some information.
>>
>> The problem is page and components need many remote data, so there are
>> many
>> serial requests to remote services. It harms latency, because overall
>> latency is sum of serial requests delays.
>>
>> I have idea to improve latency, sending requests in parallel. I want make
>> non blocking function sendRequest, which returns me token. All components
>> call non blocking sendRequest for remote data, then i'll wait in blocking
>> call waitResponses(), which wait for all responses.Then component get
>> their
>> data from token.
>>
>> Some code for illustration:
>>
>> MyComponent {
>>     @Inject
>>     private RemoteService remoteService;
>>
>>     private Token<Response> token;
>> }
>>
>> void prepareData() {
>>     token = remoteService.sendRequest(); // non blocking call
>> }
>>
>> void setupRender() {
>>     Response response = token.getData(); // first call is blocking, wait
>> for all responses, other calls just return data;
>> }
>>
>> Why i did not just realize my idea and write this post?
>>
>> Because i need two separate phases: first for send request, and second for
>> prepare rendering. All componets should send in first phase, and after get
>> data in second.
>>
>> Tapestry have setupRender and beginRender, but they have another order. It
>> call setupRender and beginRender for first component, and then - for
>> second. But i need phase 1 calls for all components, then phase 2 call for
>> all components.
>>
>> And now my question is: is there any way in Tapestry to create this
>> phases?
>> Thank you for your attention, sorry for my English.
>>
>
>
Reply | Threaded
Open this post in threaded view
|

Re: parallel remote requests in Tapestry

Тимур Бухараев
I can't call both in setupRender, because i need one blocking wait to
receive all requests in parallel.

Steps:
1. prepareData(), all components send their request for data, remember all
requests.
2. setupRender(), all components gets data from tokens. getData() could be
like this:
   Response getData() {
       while ( !allRequestsAreRecieved() ) {
           Thread.sleep( 10 );
       }
       return data;
   }

Now, we if we need 3 data: data1, data2, data3, we dont wait on blocking
calls 3 times one after one. We do one blocking call. So overall delay
would be max( delay1. delay2, delay3), not delay1 + delay2 + delay3

On Tue, Apr 14, 2015 at 2:39 PM, Chris Poulsen <[hidden email]>
wrote:

> Or maybe you can use progressive display?
>
> http://jumpstart.doublenegative.com.au/jumpstart7/examples/ajax/progressivedisplayvariations
>
> On Tue, Apr 14, 2015 at 1:36 PM, Chris Poulsen <[hidden email]>
> wrote:
>
> > If your prepareData() is non-blocking, why not just call it right before
> > you do the token.getData() ? (both in setupRender() )
> >
> > On Tue, Apr 14, 2015 at 1:03 PM, Тимур Бухараев <[hidden email]>
> > wrote:
> >
> >> Hi,
> >>
> >> My pages consist page class and several components inside.
> >>
> >> Page and its components needs some information from remote services. I
> get
> >> this information with blocking calls in setupRender(). For example, if i
> >> need user's profile data, i get it like this:
> >>
> >> setupRender() {
> >>  profileData = loadProfileDate(); // blocking call, waiting for the
> >> response
> >> }
> >>
> >> And now i can use profileData in render to show some information.
> >>
> >> The problem is page and components need many remote data, so there are
> >> many
> >> serial requests to remote services. It harms latency, because overall
> >> latency is sum of serial requests delays.
> >>
> >> I have idea to improve latency, sending requests in parallel. I want
> make
> >> non blocking function sendRequest, which returns me token. All
> components
> >> call non blocking sendRequest for remote data, then i'll wait in
> blocking
> >> call waitResponses(), which wait for all responses.Then component get
> >> their
> >> data from token.
> >>
> >> Some code for illustration:
> >>
> >> MyComponent {
> >>     @Inject
> >>     private RemoteService remoteService;
> >>
> >>     private Token<Response> token;
> >> }
> >>
> >> void prepareData() {
> >>     token = remoteService.sendRequest(); // non blocking call
> >> }
> >>
> >> void setupRender() {
> >>     Response response = token.getData(); // first call is blocking, wait
> >> for all responses, other calls just return data;
> >> }
> >>
> >> Why i did not just realize my idea and write this post?
> >>
> >> Because i need two separate phases: first for send request, and second
> for
> >> prepare rendering. All componets should send in first phase, and after
> get
> >> data in second.
> >>
> >> Tapestry have setupRender and beginRender, but they have another order.
> It
> >> call setupRender and beginRender for first component, and then - for
> >> second. But i need phase 1 calls for all components, then phase 2 call
> for
> >> all components.
> >>
> >> And now my question is: is there any way in Tapestry to create this
> >> phases?
> >> Thank you for your attention, sorry for my English.
> >>
> >
> >
>
Reply | Threaded
Open this post in threaded view
|

Re: parallel remote requests in Tapestry

Dmitry Gusev
Hi,

could you create a Future in your setupRender and use actual results w/
Future.get() during the rendering?

As Chris said I'd also recommend you looking at the ProgressiveDisplay
component.



On Tue, Apr 14, 2015 at 2:56 PM, Тимур Бухараев <[hidden email]> wrote:

> I can't call both in setupRender, because i need one blocking wait to
> receive all requests in parallel.
>
> Steps:
> 1. prepareData(), all components send their request for data, remember all
> requests.
> 2. setupRender(), all components gets data from tokens. getData() could be
> like this:
>    Response getData() {
>        while ( !allRequestsAreRecieved() ) {
>            Thread.sleep( 10 );
>        }
>        return data;
>    }
>
> Now, we if we need 3 data: data1, data2, data3, we dont wait on blocking
> calls 3 times one after one. We do one blocking call. So overall delay
> would be max( delay1. delay2, delay3), not delay1 + delay2 + delay3
>
> On Tue, Apr 14, 2015 at 2:39 PM, Chris Poulsen <[hidden email]>
> wrote:
>
> > Or maybe you can use progressive display?
> >
> >
> http://jumpstart.doublenegative.com.au/jumpstart7/examples/ajax/progressivedisplayvariations
> >
> > On Tue, Apr 14, 2015 at 1:36 PM, Chris Poulsen <[hidden email]>
> > wrote:
> >
> > > If your prepareData() is non-blocking, why not just call it right
> before
> > > you do the token.getData() ? (both in setupRender() )
> > >
> > > On Tue, Apr 14, 2015 at 1:03 PM, Тимур Бухараев <[hidden email]>
> > > wrote:
> > >
> > >> Hi,
> > >>
> > >> My pages consist page class and several components inside.
> > >>
> > >> Page and its components needs some information from remote services. I
> > get
> > >> this information with blocking calls in setupRender(). For example,
> if i
> > >> need user's profile data, i get it like this:
> > >>
> > >> setupRender() {
> > >>  profileData = loadProfileDate(); // blocking call, waiting for the
> > >> response
> > >> }
> > >>
> > >> And now i can use profileData in render to show some information.
> > >>
> > >> The problem is page and components need many remote data, so there are
> > >> many
> > >> serial requests to remote services. It harms latency, because overall
> > >> latency is sum of serial requests delays.
> > >>
> > >> I have idea to improve latency, sending requests in parallel. I want
> > make
> > >> non blocking function sendRequest, which returns me token. All
> > components
> > >> call non blocking sendRequest for remote data, then i'll wait in
> > blocking
> > >> call waitResponses(), which wait for all responses.Then component get
> > >> their
> > >> data from token.
> > >>
> > >> Some code for illustration:
> > >>
> > >> MyComponent {
> > >>     @Inject
> > >>     private RemoteService remoteService;
> > >>
> > >>     private Token<Response> token;
> > >> }
> > >>
> > >> void prepareData() {
> > >>     token = remoteService.sendRequest(); // non blocking call
> > >> }
> > >>
> > >> void setupRender() {
> > >>     Response response = token.getData(); // first call is blocking,
> wait
> > >> for all responses, other calls just return data;
> > >> }
> > >>
> > >> Why i did not just realize my idea and write this post?
> > >>
> > >> Because i need two separate phases: first for send request, and second
> > for
> > >> prepare rendering. All componets should send in first phase, and after
> > get
> > >> data in second.
> > >>
> > >> Tapestry have setupRender and beginRender, but they have another
> order.
> > It
> > >> call setupRender and beginRender for first component, and then - for
> > >> second. But i need phase 1 calls for all components, then phase 2 call
> > for
> > >> all components.
> > >>
> > >> And now my question is: is there any way in Tapestry to create this
> > >> phases?
> > >> Thank you for your attention, sorry for my English.
> > >>
> > >
> > >
> >
>



--
Dmitry Gusev

AnjLab Team
http://anjlab.com
Reply | Threaded
Open this post in threaded view
|

Re: parallel remote requests in Tapestry

Тимур Бухараев
Hello,

Future would not helps, because components renders one after one.
For example page contains component1 and component2.

The render sequence is next:

component1.setupRender();
other component1 rendering
component1.setupRender();
other component2 rendering

So if i create Future in setupRender and get result, i get delay1 in
rendering component1, and delay2 in rendering component2. Overall delay
would be delay1+delay2.
If page is complex and contains many independent components which call many
remote services, overall delay could be very much.


Thank you and Chris for ProgressiveDisplay recommending, i'll look it.

On Tue, Apr 14, 2015 at 3:00 PM, Dmitry Gusev <[hidden email]>
wrote:

> Hi,
>
> could you create a Future in your setupRender and use actual results w/
> Future.get() during the rendering?
>
> As Chris said I'd also recommend you looking at the ProgressiveDisplay
> component.
>
>
>
> On Tue, Apr 14, 2015 at 2:56 PM, Тимур Бухараев <[hidden email]>
> wrote:
>
> > I can't call both in setupRender, because i need one blocking wait to
> > receive all requests in parallel.
> >
> > Steps:
> > 1. prepareData(), all components send their request for data, remember
> all
> > requests.
> > 2. setupRender(), all components gets data from tokens. getData() could
> be
> > like this:
> >    Response getData() {
> >        while ( !allRequestsAreRecieved() ) {
> >            Thread.sleep( 10 );
> >        }
> >        return data;
> >    }
> >
> > Now, we if we need 3 data: data1, data2, data3, we dont wait on blocking
> > calls 3 times one after one. We do one blocking call. So overall delay
> > would be max( delay1. delay2, delay3), not delay1 + delay2 + delay3
> >
> > On Tue, Apr 14, 2015 at 2:39 PM, Chris Poulsen <[hidden email]>
> > wrote:
> >
> > > Or maybe you can use progressive display?
> > >
> > >
> >
> http://jumpstart.doublenegative.com.au/jumpstart7/examples/ajax/progressivedisplayvariations
> > >
> > > On Tue, Apr 14, 2015 at 1:36 PM, Chris Poulsen <[hidden email]
> >
> > > wrote:
> > >
> > > > If your prepareData() is non-blocking, why not just call it right
> > before
> > > > you do the token.getData() ? (both in setupRender() )
> > > >
> > > > On Tue, Apr 14, 2015 at 1:03 PM, Тимур Бухараев <[hidden email]
> >
> > > > wrote:
> > > >
> > > >> Hi,
> > > >>
> > > >> My pages consist page class and several components inside.
> > > >>
> > > >> Page and its components needs some information from remote
> services. I
> > > get
> > > >> this information with blocking calls in setupRender(). For example,
> > if i
> > > >> need user's profile data, i get it like this:
> > > >>
> > > >> setupRender() {
> > > >>  profileData = loadProfileDate(); // blocking call, waiting for the
> > > >> response
> > > >> }
> > > >>
> > > >> And now i can use profileData in render to show some information.
> > > >>
> > > >> The problem is page and components need many remote data, so there
> are
> > > >> many
> > > >> serial requests to remote services. It harms latency, because
> overall
> > > >> latency is sum of serial requests delays.
> > > >>
> > > >> I have idea to improve latency, sending requests in parallel. I want
> > > make
> > > >> non blocking function sendRequest, which returns me token. All
> > > components
> > > >> call non blocking sendRequest for remote data, then i'll wait in
> > > blocking
> > > >> call waitResponses(), which wait for all responses.Then component
> get
> > > >> their
> > > >> data from token.
> > > >>
> > > >> Some code for illustration:
> > > >>
> > > >> MyComponent {
> > > >>     @Inject
> > > >>     private RemoteService remoteService;
> > > >>
> > > >>     private Token<Response> token;
> > > >> }
> > > >>
> > > >> void prepareData() {
> > > >>     token = remoteService.sendRequest(); // non blocking call
> > > >> }
> > > >>
> > > >> void setupRender() {
> > > >>     Response response = token.getData(); // first call is blocking,
> > wait
> > > >> for all responses, other calls just return data;
> > > >> }
> > > >>
> > > >> Why i did not just realize my idea and write this post?
> > > >>
> > > >> Because i need two separate phases: first for send request, and
> second
> > > for
> > > >> prepare rendering. All componets should send in first phase, and
> after
> > > get
> > > >> data in second.
> > > >>
> > > >> Tapestry have setupRender and beginRender, but they have another
> > order.
> > > It
> > > >> call setupRender and beginRender for first component, and then - for
> > > >> second. But i need phase 1 calls for all components, then phase 2
> call
> > > for
> > > >> all components.
> > > >>
> > > >> And now my question is: is there any way in Tapestry to create this
> > > >> phases?
> > > >> Thank you for your attention, sorry for my English.
> > > >>
> > > >
> > > >
> > >
> >
>
>
>
> --
> Dmitry Gusev
>
> AnjLab Team
> http://anjlab.com
>
Reply | Threaded
Open this post in threaded view
|

Re: parallel remote requests in Tapestry

Тимур Бухараев
sorry, some mistake in sequence

it should be:
component1.setupRender();
other component1 rendering
component2.setupRender();
other component2 rendering

On Tue, Apr 14, 2015 at 3:17 PM, Тимур Бухараев <[hidden email]> wrote:

> Hello,
>
> Future would not helps, because components renders one after one.
> For example page contains component1 and component2.
>
> The render sequence is next:
>
> component1.setupRender();
> other component1 rendering
> component1.setupRender();
> other component2 rendering
>
> So if i create Future in setupRender and get result, i get delay1 in
> rendering component1, and delay2 in rendering component2. Overall delay
> would be delay1+delay2.
> If page is complex and contains many independent components which call
> many remote services, overall delay could be very much.
>
>
> Thank you and Chris for ProgressiveDisplay recommending, i'll look it.
>
> On Tue, Apr 14, 2015 at 3:00 PM, Dmitry Gusev <[hidden email]>
> wrote:
>
>> Hi,
>>
>> could you create a Future in your setupRender and use actual results w/
>> Future.get() during the rendering?
>>
>> As Chris said I'd also recommend you looking at the ProgressiveDisplay
>> component.
>>
>>
>>
>> On Tue, Apr 14, 2015 at 2:56 PM, Тимур Бухараев <[hidden email]>
>> wrote:
>>
>> > I can't call both in setupRender, because i need one blocking wait to
>> > receive all requests in parallel.
>> >
>> > Steps:
>> > 1. prepareData(), all components send their request for data, remember
>> all
>> > requests.
>> > 2. setupRender(), all components gets data from tokens. getData() could
>> be
>> > like this:
>> >    Response getData() {
>> >        while ( !allRequestsAreRecieved() ) {
>> >            Thread.sleep( 10 );
>> >        }
>> >        return data;
>> >    }
>> >
>> > Now, we if we need 3 data: data1, data2, data3, we dont wait on blocking
>> > calls 3 times one after one. We do one blocking call. So overall delay
>> > would be max( delay1. delay2, delay3), not delay1 + delay2 + delay3
>> >
>> > On Tue, Apr 14, 2015 at 2:39 PM, Chris Poulsen <[hidden email]>
>> > wrote:
>> >
>> > > Or maybe you can use progressive display?
>> > >
>> > >
>> >
>> http://jumpstart.doublenegative.com.au/jumpstart7/examples/ajax/progressivedisplayvariations
>> > >
>> > > On Tue, Apr 14, 2015 at 1:36 PM, Chris Poulsen <
>> [hidden email]>
>> > > wrote:
>> > >
>> > > > If your prepareData() is non-blocking, why not just call it right
>> > before
>> > > > you do the token.getData() ? (both in setupRender() )
>> > > >
>> > > > On Tue, Apr 14, 2015 at 1:03 PM, Тимур Бухараев <
>> [hidden email]>
>> > > > wrote:
>> > > >
>> > > >> Hi,
>> > > >>
>> > > >> My pages consist page class and several components inside.
>> > > >>
>> > > >> Page and its components needs some information from remote
>> services. I
>> > > get
>> > > >> this information with blocking calls in setupRender(). For example,
>> > if i
>> > > >> need user's profile data, i get it like this:
>> > > >>
>> > > >> setupRender() {
>> > > >>  profileData = loadProfileDate(); // blocking call, waiting for the
>> > > >> response
>> > > >> }
>> > > >>
>> > > >> And now i can use profileData in render to show some information.
>> > > >>
>> > > >> The problem is page and components need many remote data, so there
>> are
>> > > >> many
>> > > >> serial requests to remote services. It harms latency, because
>> overall
>> > > >> latency is sum of serial requests delays.
>> > > >>
>> > > >> I have idea to improve latency, sending requests in parallel. I
>> want
>> > > make
>> > > >> non blocking function sendRequest, which returns me token. All
>> > > components
>> > > >> call non blocking sendRequest for remote data, then i'll wait in
>> > > blocking
>> > > >> call waitResponses(), which wait for all responses.Then component
>> get
>> > > >> their
>> > > >> data from token.
>> > > >>
>> > > >> Some code for illustration:
>> > > >>
>> > > >> MyComponent {
>> > > >>     @Inject
>> > > >>     private RemoteService remoteService;
>> > > >>
>> > > >>     private Token<Response> token;
>> > > >> }
>> > > >>
>> > > >> void prepareData() {
>> > > >>     token = remoteService.sendRequest(); // non blocking call
>> > > >> }
>> > > >>
>> > > >> void setupRender() {
>> > > >>     Response response = token.getData(); // first call is blocking,
>> > wait
>> > > >> for all responses, other calls just return data;
>> > > >> }
>> > > >>
>> > > >> Why i did not just realize my idea and write this post?
>> > > >>
>> > > >> Because i need two separate phases: first for send request, and
>> second
>> > > for
>> > > >> prepare rendering. All componets should send in first phase, and
>> after
>> > > get
>> > > >> data in second.
>> > > >>
>> > > >> Tapestry have setupRender and beginRender, but they have another
>> > order.
>> > > It
>> > > >> call setupRender and beginRender for first component, and then -
>> for
>> > > >> second. But i need phase 1 calls for all components, then phase 2
>> call
>> > > for
>> > > >> all components.
>> > > >>
>> > > >> And now my question is: is there any way in Tapestry to create this
>> > > >> phases?
>> > > >> Thank you for your attention, sorry for my English.
>> > > >>
>> > > >
>> > > >
>> > >
>> >
>>
>>
>>
>> --
>> Dmitry Gusev
>>
>> AnjLab Team
>> http://anjlab.com
>>
>
>
Reply | Threaded
Open this post in threaded view
|

Re: parallel remote requests in Tapestry

Thiago H de Paula Figueiredo
On Tue, 14 Apr 2015 09:22:36 -0300, Тимур Бухараев <[hidden email]>  
wrote:

> sorry, some mistake in sequence
>
> it should be:
> component1.setupRender();
> other component1 rendering
> component2.setupRender();
> other component2 rendering

If you think Future is not the way to go (and that's what I'd use and I  
think it covers your problem from in the description you gave) and neither  
ProgressiveDisplay is (which is a good other solution), why don't you move  
the data fetch logic for all components in a single place (preferably a  
service, maybe the page) so you can properly parallelize it and the  
components themselves just receive the data instead of fetching it?

>
> On Tue, Apr 14, 2015 at 3:17 PM, Тимур Бухараев <[hidden email]>  
> wrote:
>
>> Hello,
>>
>> Future would not helps, because components renders one after one.
>> For example page contains component1 and component2.
>>
>> The render sequence is next:
>>
>> component1.setupRender();
>> other component1 rendering
>> component1.setupRender();
>> other component2 rendering
>>
>> So if i create Future in setupRender and get result, i get delay1 in
>> rendering component1, and delay2 in rendering component2. Overall delay
>> would be delay1+delay2.
>> If page is complex and contains many independent components which call
>> many remote services, overall delay could be very much.
>>
>>
>> Thank you and Chris for ProgressiveDisplay recommending, i'll look it.
>>
>> On Tue, Apr 14, 2015 at 3:00 PM, Dmitry Gusev <[hidden email]>
>> wrote:
>>
>>> Hi,
>>>
>>> could you create a Future in your setupRender and use actual results w/
>>> Future.get() during the rendering?
>>>
>>> As Chris said I'd also recommend you looking at the ProgressiveDisplay
>>> component.
>>>
>>>
>>>
>>> On Tue, Apr 14, 2015 at 2:56 PM, Тимур Бухараев <[hidden email]>
>>> wrote:
>>>
>>> > I can't call both in setupRender, because i need one blocking wait to
>>> > receive all requests in parallel.
>>> >
>>> > Steps:
>>> > 1. prepareData(), all components send their request for data,  
>>> remember
>>> all
>>> > requests.
>>> > 2. setupRender(), all components gets data from tokens. getData()  
>>> could
>>> be
>>> > like this:
>>> >    Response getData() {
>>> >        while ( !allRequestsAreRecieved() ) {
>>> >            Thread.sleep( 10 );
>>> >        }
>>> >        return data;
>>> >    }
>>> >
>>> > Now, we if we need 3 data: data1, data2, data3, we dont wait on  
>>> blocking
>>> > calls 3 times one after one. We do one blocking call. So overall  
>>> delay
>>> > would be max( delay1. delay2, delay3), not delay1 + delay2 + delay3
>>> >
>>> > On Tue, Apr 14, 2015 at 2:39 PM, Chris Poulsen  
>>> <[hidden email]>
>>> > wrote:
>>> >
>>> > > Or maybe you can use progressive display?
>>> > >
>>> > >
>>> >
>>> http://jumpstart.doublenegative.com.au/jumpstart7/examples/ajax/progressivedisplayvariations
>>> > >
>>> > > On Tue, Apr 14, 2015 at 1:36 PM, Chris Poulsen <
>>> [hidden email]>
>>> > > wrote:
>>> > >
>>> > > > If your prepareData() is non-blocking, why not just call it right
>>> > before
>>> > > > you do the token.getData() ? (both in setupRender() )
>>> > > >
>>> > > > On Tue, Apr 14, 2015 at 1:03 PM, Тимур Бухараев <
>>> [hidden email]>
>>> > > > wrote:
>>> > > >
>>> > > >> Hi,
>>> > > >>
>>> > > >> My pages consist page class and several components inside.
>>> > > >>
>>> > > >> Page and its components needs some information from remote
>>> services. I
>>> > > get
>>> > > >> this information with blocking calls in setupRender(). For  
>>> example,
>>> > if i
>>> > > >> need user's profile data, i get it like this:
>>> > > >>
>>> > > >> setupRender() {
>>> > > >>  profileData = loadProfileDate(); // blocking call, waiting for  
>>> the
>>> > > >> response
>>> > > >> }
>>> > > >>
>>> > > >> And now i can use profileData in render to show some  
>>> information.
>>> > > >>
>>> > > >> The problem is page and components need many remote data, so  
>>> there
>>> are
>>> > > >> many
>>> > > >> serial requests to remote services. It harms latency, because
>>> overall
>>> > > >> latency is sum of serial requests delays.
>>> > > >>
>>> > > >> I have idea to improve latency, sending requests in parallel. I
>>> want
>>> > > make
>>> > > >> non blocking function sendRequest, which returns me token. All
>>> > > components
>>> > > >> call non blocking sendRequest for remote data, then i'll wait in
>>> > > blocking
>>> > > >> call waitResponses(), which wait for all responses.Then  
>>> component
>>> get
>>> > > >> their
>>> > > >> data from token.
>>> > > >>
>>> > > >> Some code for illustration:
>>> > > >>
>>> > > >> MyComponent {
>>> > > >>     @Inject
>>> > > >>     private RemoteService remoteService;
>>> > > >>
>>> > > >>     private Token<Response> token;
>>> > > >> }
>>> > > >>
>>> > > >> void prepareData() {
>>> > > >>     token = remoteService.sendRequest(); // non blocking call
>>> > > >> }
>>> > > >>
>>> > > >> void setupRender() {
>>> > > >>     Response response = token.getData(); // first call is  
>>> blocking,
>>> > wait
>>> > > >> for all responses, other calls just return data;
>>> > > >> }
>>> > > >>
>>> > > >> Why i did not just realize my idea and write this post?
>>> > > >>
>>> > > >> Because i need two separate phases: first for send request, and
>>> second
>>> > > for
>>> > > >> prepare rendering. All componets should send in first phase, and
>>> after
>>> > > get
>>> > > >> data in second.
>>> > > >>
>>> > > >> Tapestry have setupRender and beginRender, but they have another
>>> > order.
>>> > > It
>>> > > >> call setupRender and beginRender for first component, and then -
>>> for
>>> > > >> second. But i need phase 1 calls for all components, then phase  
>>> 2
>>> call
>>> > > for
>>> > > >> all components.
>>> > > >>
>>> > > >> And now my question is: is there any way in Tapestry to create  
>>> this
>>> > > >> phases?
>>> > > >> Thank you for your attention, sorry for my English.
>>> > > >>
>>> > > >
>>> > > >
>>> > >
>>> >
>>>
>>>
>>>
>>> --
>>> Dmitry Gusev
>>>
>>> AnjLab Team
>>> http://anjlab.com
>>>
>>
>>


--
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: parallel remote requests in Tapestry

Тимур Бухараев
I don't know how to solve my problem with Future. If you know, explain
please.

ProgressiveDisplay is a solution, but has some disadvantages.

Now about moving data fetch logic.

The problem is components are independent. Page class doesn't know about
Component classes, component classes don't know about page and other
components. They just embedded in a single tml document. So designer could
move component to other place, and it still works. Each component fetches
his own remote data independently. I can cache this data in service, if
some components need same data, so the second component get cached data.
But component is the only place who knows, what data it needs. For example,
component displaying user profile. It needs user profile data, and it
fetches it. So component is the only thing who knows it need profile data.
But i can embed it in any tml in any place.

On Tue, Apr 14, 2015 at 4:27 PM, Thiago H de Paula Figueiredo <
[hidden email]> wrote:

> On Tue, 14 Apr 2015 09:22:36 -0300, Тимур Бухараев <[hidden email]>
> wrote:
>
>  sorry, some mistake in sequence
>>
>> it should be:
>> component1.setupRender();
>> other component1 rendering
>> component2.setupRender();
>> other component2 rendering
>>
>
> If you think Future is not the way to go (and that's what I'd use and I
> think it covers your problem from in the description you gave) and neither
> ProgressiveDisplay is (which is a good other solution), why don't you move
> the data fetch logic for all components in a single place (preferably a
> service, maybe the page) so you can properly parallelize it and the
> components themselves just receive the data instead of fetching it?
>
>
>
>> On Tue, Apr 14, 2015 at 3:17 PM, Тимур Бухараев <[hidden email]>
>> wrote:
>>
>>  Hello,
>>>
>>> Future would not helps, because components renders one after one.
>>> For example page contains component1 and component2.
>>>
>>> The render sequence is next:
>>>
>>> component1.setupRender();
>>> other component1 rendering
>>> component1.setupRender();
>>> other component2 rendering
>>>
>>> So if i create Future in setupRender and get result, i get delay1 in
>>> rendering component1, and delay2 in rendering component2. Overall delay
>>> would be delay1+delay2.
>>> If page is complex and contains many independent components which call
>>> many remote services, overall delay could be very much.
>>>
>>>
>>> Thank you and Chris for ProgressiveDisplay recommending, i'll look it.
>>>
>>> On Tue, Apr 14, 2015 at 3:00 PM, Dmitry Gusev <[hidden email]>
>>> wrote:
>>>
>>>  Hi,
>>>>
>>>> could you create a Future in your setupRender and use actual results w/
>>>> Future.get() during the rendering?
>>>>
>>>> As Chris said I'd also recommend you looking at the ProgressiveDisplay
>>>> component.
>>>>
>>>>
>>>>
>>>> On Tue, Apr 14, 2015 at 2:56 PM, Тимур Бухараев <[hidden email]>
>>>> wrote:
>>>>
>>>> > I can't call both in setupRender, because i need one blocking wait to
>>>> > receive all requests in parallel.
>>>> >
>>>> > Steps:
>>>> > 1. prepareData(), all components send their request for data, remember
>>>> all
>>>> > requests.
>>>> > 2. setupRender(), all components gets data from tokens. getData()
>>>> could
>>>> be
>>>> > like this:
>>>> >    Response getData() {
>>>> >        while ( !allRequestsAreRecieved() ) {
>>>> >            Thread.sleep( 10 );
>>>> >        }
>>>> >        return data;
>>>> >    }
>>>> >
>>>> > Now, we if we need 3 data: data1, data2, data3, we dont wait on
>>>> blocking
>>>> > calls 3 times one after one. We do one blocking call. So overall delay
>>>> > would be max( delay1. delay2, delay3), not delay1 + delay2 + delay3
>>>> >
>>>> > On Tue, Apr 14, 2015 at 2:39 PM, Chris Poulsen <
>>>> [hidden email]>
>>>> > wrote:
>>>> >
>>>> > > Or maybe you can use progressive display?
>>>> > >
>>>> > >
>>>> >
>>>> http://jumpstart.doublenegative.com.au/jumpstart7/examples/ajax/
>>>> progressivedisplayvariations
>>>> > >
>>>> > > On Tue, Apr 14, 2015 at 1:36 PM, Chris Poulsen <
>>>> [hidden email]>
>>>> > > wrote:
>>>> > >
>>>> > > > If your prepareData() is non-blocking, why not just call it right
>>>> > before
>>>> > > > you do the token.getData() ? (both in setupRender() )
>>>> > > >
>>>> > > > On Tue, Apr 14, 2015 at 1:03 PM, Тимур Бухараев <
>>>> [hidden email]>
>>>> > > > wrote:
>>>> > > >
>>>> > > >> Hi,
>>>> > > >>
>>>> > > >> My pages consist page class and several components inside.
>>>> > > >>
>>>> > > >> Page and its components needs some information from remote
>>>> services. I
>>>> > > get
>>>> > > >> this information with blocking calls in setupRender(). For
>>>> example,
>>>> > if i
>>>> > > >> need user's profile data, i get it like this:
>>>> > > >>
>>>> > > >> setupRender() {
>>>> > > >>  profileData = loadProfileDate(); // blocking call, waiting for
>>>> the
>>>> > > >> response
>>>> > > >> }
>>>> > > >>
>>>> > > >> And now i can use profileData in render to show some information.
>>>> > > >>
>>>> > > >> The problem is page and components need many remote data, so
>>>> there
>>>> are
>>>> > > >> many
>>>> > > >> serial requests to remote services. It harms latency, because
>>>> overall
>>>> > > >> latency is sum of serial requests delays.
>>>> > > >>
>>>> > > >> I have idea to improve latency, sending requests in parallel. I
>>>> want
>>>> > > make
>>>> > > >> non blocking function sendRequest, which returns me token. All
>>>> > > components
>>>> > > >> call non blocking sendRequest for remote data, then i'll wait in
>>>> > > blocking
>>>> > > >> call waitResponses(), which wait for all responses.Then component
>>>> get
>>>> > > >> their
>>>> > > >> data from token.
>>>> > > >>
>>>> > > >> Some code for illustration:
>>>> > > >>
>>>> > > >> MyComponent {
>>>> > > >>     @Inject
>>>> > > >>     private RemoteService remoteService;
>>>> > > >>
>>>> > > >>     private Token<Response> token;
>>>> > > >> }
>>>> > > >>
>>>> > > >> void prepareData() {
>>>> > > >>     token = remoteService.sendRequest(); // non blocking call
>>>> > > >> }
>>>> > > >>
>>>> > > >> void setupRender() {
>>>> > > >>     Response response = token.getData(); // first call is
>>>> blocking,
>>>> > wait
>>>> > > >> for all responses, other calls just return data;
>>>> > > >> }
>>>> > > >>
>>>> > > >> Why i did not just realize my idea and write this post?
>>>> > > >>
>>>> > > >> Because i need two separate phases: first for send request, and
>>>> second
>>>> > > for
>>>> > > >> prepare rendering. All componets should send in first phase, and
>>>> after
>>>> > > get
>>>> > > >> data in second.
>>>> > > >>
>>>> > > >> Tapestry have setupRender and beginRender, but they have another
>>>> > order.
>>>> > > It
>>>> > > >> call setupRender and beginRender for first component, and then -
>>>> for
>>>> > > >> second. But i need phase 1 calls for all components, then phase 2
>>>> call
>>>> > > for
>>>> > > >> all components.
>>>> > > >>
>>>> > > >> And now my question is: is there any way in Tapestry to create
>>>> this
>>>> > > >> phases?
>>>> > > >> Thank you for your attention, sorry for my English.
>>>> > > >>
>>>> > > >
>>>> > > >
>>>> > >
>>>> >
>>>>
>>>>
>>>>
>>>> --
>>>> Dmitry Gusev
>>>>
>>>> AnjLab Team
>>>> http://anjlab.com
>>>>
>>>>
>>>
>>>
>
> --
> Thiago H. de Paula Figueiredo
> Tapestry, Java and Hibernate consultant and developer
> http://machina.com.br
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>
Reply | Threaded
Open this post in threaded view
|

Re: parallel remote requests in Tapestry

Cezary Biernacki
Hi Тимур,
Have you tried putting your asynchronous in pageAttached() methods (also
see @PageAttached annotation) in your components?

https://tapestry.apache.org/page-life-cycle.html

However pageAttached is invoked on all pages that are somehow involved in
the request processing (e.g. they are referenced via PageLink component)
and also for requests which are not rendered, so you would need some extra
checks to prevent unintended remote service calls.

PageAttached is deprecated in Tapestry 5.3, but it seems to be back and
working in 5.4.

http://tapestry.apache.org/5.3/apidocs/org/apache/tapestry5/annotations/PageAttached.html
http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/annotations/PageAttached.html


Another option is to use Heartbeat environmental service /
@HeartbeatDeferred annotation. In this case the component during normal
rendering just prepares some static template as Tapestry DOM, and invokes
asynchronous remote call, then on deferred call update the template with
actual content.


Best regards,
Cezary


On Tue, Apr 14, 2015 at 4:08 PM, Тимур Бухараев <[hidden email]> wrote:

> I don't know how to solve my problem with Future. If you know, explain
> please.
>
> ProgressiveDisplay is a solution, but has some disadvantages.
>
> Now about moving data fetch logic.
>
> The problem is components are independent. Page class doesn't know about
> Component classes, component classes don't know about page and other
> components. They just embedded in a single tml document. So designer could
> move component to other place, and it still works. Each component fetches
> his own remote data independently. I can cache this data in service, if
> some components need same data, so the second component get cached data.
> But component is the only place who knows, what data it needs. For example,
> component displaying user profile. It needs user profile data, and it
> fetches it. So component is the only thing who knows it need profile data.
> But i can embed it in any tml in any place.
>
> On Tue, Apr 14, 2015 at 4:27 PM, Thiago H de Paula Figueiredo <
> [hidden email]> wrote:
>
> > On Tue, 14 Apr 2015 09:22:36 -0300, Тимур Бухараев <[hidden email]>
> > wrote:
> >
> >  sorry, some mistake in sequence
> >>
> >> it should be:
> >> component1.setupRender();
> >> other component1 rendering
> >> component2.setupRender();
> >> other component2 rendering
> >>
> >
> > If you think Future is not the way to go (and that's what I'd use and I
> > think it covers your problem from in the description you gave) and
> neither
> > ProgressiveDisplay is (which is a good other solution), why don't you
> move
> > the data fetch logic for all components in a single place (preferably a
> > service, maybe the page) so you can properly parallelize it and the
> > components themselves just receive the data instead of fetching it?
> >
> >
> >
> >> On Tue, Apr 14, 2015 at 3:17 PM, Тимур Бухараев <[hidden email]>
> >> wrote:
> >>
> >>  Hello,
> >>>
> >>> Future would not helps, because components renders one after one.
> >>> For example page contains component1 and component2.
> >>>
> >>> The render sequence is next:
> >>>
> >>> component1.setupRender();
> >>> other component1 rendering
> >>> component1.setupRender();
> >>> other component2 rendering
> >>>
> >>> So if i create Future in setupRender and get result, i get delay1 in
> >>> rendering component1, and delay2 in rendering component2. Overall delay
> >>> would be delay1+delay2.
> >>> If page is complex and contains many independent components which call
> >>> many remote services, overall delay could be very much.
> >>>
> >>>
> >>> Thank you and Chris for ProgressiveDisplay recommending, i'll look it.
> >>>
> >>> On Tue, Apr 14, 2015 at 3:00 PM, Dmitry Gusev <[hidden email]>
> >>> wrote:
> >>>
> >>>  Hi,
> >>>>
> >>>> could you create a Future in your setupRender and use actual results
> w/
> >>>> Future.get() during the rendering?
> >>>>
> >>>> As Chris said I'd also recommend you looking at the ProgressiveDisplay
> >>>> component.
> >>>>
> >>>>
> >>>>
> >>>> On Tue, Apr 14, 2015 at 2:56 PM, Тимур Бухараев <[hidden email]>
> >>>> wrote:
> >>>>
> >>>> > I can't call both in setupRender, because i need one blocking wait
> to
> >>>> > receive all requests in parallel.
> >>>> >
> >>>> > Steps:
> >>>> > 1. prepareData(), all components send their request for data,
> remember
> >>>> all
> >>>> > requests.
> >>>> > 2. setupRender(), all components gets data from tokens. getData()
> >>>> could
> >>>> be
> >>>> > like this:
> >>>> >    Response getData() {
> >>>> >        while ( !allRequestsAreRecieved() ) {
> >>>> >            Thread.sleep( 10 );
> >>>> >        }
> >>>> >        return data;
> >>>> >    }
> >>>> >
> >>>> > Now, we if we need 3 data: data1, data2, data3, we dont wait on
> >>>> blocking
> >>>> > calls 3 times one after one. We do one blocking call. So overall
> delay
> >>>> > would be max( delay1. delay2, delay3), not delay1 + delay2 + delay3
> >>>> >
> >>>> > On Tue, Apr 14, 2015 at 2:39 PM, Chris Poulsen <
> >>>> [hidden email]>
> >>>> > wrote:
> >>>> >
> >>>> > > Or maybe you can use progressive display?
> >>>> > >
> >>>> > >
> >>>> >
> >>>> http://jumpstart.doublenegative.com.au/jumpstart7/examples/ajax/
> >>>> progressivedisplayvariations
> >>>> > >
> >>>> > > On Tue, Apr 14, 2015 at 1:36 PM, Chris Poulsen <
> >>>> [hidden email]>
> >>>> > > wrote:
> >>>> > >
> >>>> > > > If your prepareData() is non-blocking, why not just call it
> right
> >>>> > before
> >>>> > > > you do the token.getData() ? (both in setupRender() )
> >>>> > > >
> >>>> > > > On Tue, Apr 14, 2015 at 1:03 PM, Тимур Бухараев <
> >>>> [hidden email]>
> >>>> > > > wrote:
> >>>> > > >
> >>>> > > >> Hi,
> >>>> > > >>
> >>>> > > >> My pages consist page class and several components inside.
> >>>> > > >>
> >>>> > > >> Page and its components needs some information from remote
> >>>> services. I
> >>>> > > get
> >>>> > > >> this information with blocking calls in setupRender(). For
> >>>> example,
> >>>> > if i
> >>>> > > >> need user's profile data, i get it like this:
> >>>> > > >>
> >>>> > > >> setupRender() {
> >>>> > > >>  profileData = loadProfileDate(); // blocking call, waiting for
> >>>> the
> >>>> > > >> response
> >>>> > > >> }
> >>>> > > >>
> >>>> > > >> And now i can use profileData in render to show some
> information.
> >>>> > > >>
> >>>> > > >> The problem is page and components need many remote data, so
> >>>> there
> >>>> are
> >>>> > > >> many
> >>>> > > >> serial requests to remote services. It harms latency, because
> >>>> overall
> >>>> > > >> latency is sum of serial requests delays.
> >>>> > > >>
> >>>> > > >> I have idea to improve latency, sending requests in parallel. I
> >>>> want
> >>>> > > make
> >>>> > > >> non blocking function sendRequest, which returns me token. All
> >>>> > > components
> >>>> > > >> call non blocking sendRequest for remote data, then i'll wait
> in
> >>>> > > blocking
> >>>> > > >> call waitResponses(), which wait for all responses.Then
> component
> >>>> get
> >>>> > > >> their
> >>>> > > >> data from token.
> >>>> > > >>
> >>>> > > >> Some code for illustration:
> >>>> > > >>
> >>>> > > >> MyComponent {
> >>>> > > >>     @Inject
> >>>> > > >>     private RemoteService remoteService;
> >>>> > > >>
> >>>> > > >>     private Token<Response> token;
> >>>> > > >> }
> >>>> > > >>
> >>>> > > >> void prepareData() {
> >>>> > > >>     token = remoteService.sendRequest(); // non blocking call
> >>>> > > >> }
> >>>> > > >>
> >>>> > > >> void setupRender() {
> >>>> > > >>     Response response = token.getData(); // first call is
> >>>> blocking,
> >>>> > wait
> >>>> > > >> for all responses, other calls just return data;
> >>>> > > >> }
> >>>> > > >>
> >>>> > > >> Why i did not just realize my idea and write this post?
> >>>> > > >>
> >>>> > > >> Because i need two separate phases: first for send request, and
> >>>> second
> >>>> > > for
> >>>> > > >> prepare rendering. All componets should send in first phase,
> and
> >>>> after
> >>>> > > get
> >>>> > > >> data in second.
> >>>> > > >>
> >>>> > > >> Tapestry have setupRender and beginRender, but they have
> another
> >>>> > order.
> >>>> > > It
> >>>> > > >> call setupRender and beginRender for first component, and then
> -
> >>>> for
> >>>> > > >> second. But i need phase 1 calls for all components, then
> phase 2
> >>>> call
> >>>> > > for
> >>>> > > >> all components.
> >>>> > > >>
> >>>> > > >> And now my question is: is there any way in Tapestry to create
> >>>> this
> >>>> > > >> phases?
> >>>> > > >> Thank you for your attention, sorry for my English.
> >>>> > > >>
> >>>> > > >
> >>>> > > >
> >>>> > >
> >>>> >
> >>>>
> >>>>
> >>>>
> >>>> --
> >>>> Dmitry Gusev
> >>>>
> >>>> AnjLab Team
> >>>> http://anjlab.com
> >>>>
> >>>>
> >>>
> >>>
> >
> > --
> > Thiago H. de Paula Figueiredo
> > Tapestry, Java and Hibernate consultant and developer
> > http://machina.com.br
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [hidden email]
> > For additional commands, e-mail: [hidden email]
> >
> >
>
Reply | Threaded
Open this post in threaded view
|

Re: parallel remote requests in Tapestry

Thiago H de Paula Figueiredo
In reply to this post by Тимур Бухараев
On Tue, 14 Apr 2015 11:08:11 -0300, Тимур Бухараев <[hidden email]>  
wrote:

> I don't know how to solve my problem with Future. If you know, explain
> please.

That's not a Tapestry-specific question, so I suggest you to find and read  
tutorials like this:  
http://java.dzone.com/articles/javautilconcurrentfuture.

> ProgressiveDisplay is a solution, but has some disadvantages.

Yep. But it does fit in many situations, so I think it should be an option  
you have in mind when thinking about specific components.

> Now about moving data fetch logic.
>
> The problem is components are independent. Page class doesn't know about
> Component classes, component classes don't know about page and other
> components. They just embedded in a single tml document. So designer  
> could move component to other place, and it still works. Each component  
> fetches
> his own remote data independently. I can cache this data in service, if
> some components need same data, so the second component get cached data.
> But component is the only place who knows, what data it needs. For  
> example, component displaying user profile. It needs user profile data,  
> and it
> fetches it. So component is the only thing who knows it need profile  
> data. But i can embed it in any tml in any place.

Ok! Of course, one solution doesn't cover all situations, and the service  
one doesn't cover yours.

Some time ago there was a discussion about parallel rendering of  
components in this mailing list. My conclusion of it it's that it can be  
done, but you have to be extra-extra-extra careful.  
http://apache-tapestry-mailing-list-archives.1045711.n5.nabble.com/quot-Parallel-quot-component-rendering-td5729024.html.  
It's a very interesting read, with lots of interesting opinions.

I have one different suggestion now: cache the results of these slow  
method calls so, the next time you have to make one, you already have the  
result ready. Of course, caching should be done very carefully, when when  
it's done, it does wonders for performance and request times.

--
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: parallel remote requests in Tapestry

Тимур Бухараев
In reply to this post by Cezary Biernacki
Yes, i tried PageAttached. I put logs to see call sequences. PageAttached
works fine for page class, but i see many chaotic calls per component. I
expect one call per request per component, but see there are many calls per
component. I dont know why.

Heartbeat is really interesting option. Thank you for idea. The next my
question is: how update template with actual content in deffered commands?

On Tue, Apr 14, 2015 at 9:05 PM, Cezary Biernacki <[hidden email]>
wrote:

> Hi Тимур,
> Have you tried putting your asynchronous in pageAttached() methods (also
> see @PageAttached annotation) in your components?
>
> https://tapestry.apache.org/page-life-cycle.html
>
> However pageAttached is invoked on all pages that are somehow involved in
> the request processing (e.g. they are referenced via PageLink component)
> and also for requests which are not rendered, so you would need some extra
> checks to prevent unintended remote service calls.
>
> PageAttached is deprecated in Tapestry 5.3, but it seems to be back and
> working in 5.4.
>
>
> http://tapestry.apache.org/5.3/apidocs/org/apache/tapestry5/annotations/PageAttached.html
>
> http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/annotations/PageAttached.html
>
>
> Another option is to use Heartbeat environmental service /
> @HeartbeatDeferred annotation. In this case the component during normal
> rendering just prepares some static template as Tapestry DOM, and invokes
> asynchronous remote call, then on deferred call update the template with
> actual content.
>
>
> Best regards,
> Cezary
>
>
> On Tue, Apr 14, 2015 at 4:08 PM, Тимур Бухараев <[hidden email]>
> wrote:
>
> > I don't know how to solve my problem with Future. If you know, explain
> > please.
> >
> > ProgressiveDisplay is a solution, but has some disadvantages.
> >
> > Now about moving data fetch logic.
> >
> > The problem is components are independent. Page class doesn't know about
> > Component classes, component classes don't know about page and other
> > components. They just embedded in a single tml document. So designer
> could
> > move component to other place, and it still works. Each component fetches
> > his own remote data independently. I can cache this data in service, if
> > some components need same data, so the second component get cached data.
> > But component is the only place who knows, what data it needs. For
> example,
> > component displaying user profile. It needs user profile data, and it
> > fetches it. So component is the only thing who knows it need profile
> data.
> > But i can embed it in any tml in any place.
> >
> > On Tue, Apr 14, 2015 at 4:27 PM, Thiago H de Paula Figueiredo <
> > [hidden email]> wrote:
> >
> > > On Tue, 14 Apr 2015 09:22:36 -0300, Тимур Бухараев <
> [hidden email]>
> > > wrote:
> > >
> > >  sorry, some mistake in sequence
> > >>
> > >> it should be:
> > >> component1.setupRender();
> > >> other component1 rendering
> > >> component2.setupRender();
> > >> other component2 rendering
> > >>
> > >
> > > If you think Future is not the way to go (and that's what I'd use and I
> > > think it covers your problem from in the description you gave) and
> > neither
> > > ProgressiveDisplay is (which is a good other solution), why don't you
> > move
> > > the data fetch logic for all components in a single place (preferably a
> > > service, maybe the page) so you can properly parallelize it and the
> > > components themselves just receive the data instead of fetching it?
> > >
> > >
> > >
> > >> On Tue, Apr 14, 2015 at 3:17 PM, Тимур Бухараев <[hidden email]>
> > >> wrote:
> > >>
> > >>  Hello,
> > >>>
> > >>> Future would not helps, because components renders one after one.
> > >>> For example page contains component1 and component2.
> > >>>
> > >>> The render sequence is next:
> > >>>
> > >>> component1.setupRender();
> > >>> other component1 rendering
> > >>> component1.setupRender();
> > >>> other component2 rendering
> > >>>
> > >>> So if i create Future in setupRender and get result, i get delay1 in
> > >>> rendering component1, and delay2 in rendering component2. Overall
> delay
> > >>> would be delay1+delay2.
> > >>> If page is complex and contains many independent components which
> call
> > >>> many remote services, overall delay could be very much.
> > >>>
> > >>>
> > >>> Thank you and Chris for ProgressiveDisplay recommending, i'll look
> it.
> > >>>
> > >>> On Tue, Apr 14, 2015 at 3:00 PM, Dmitry Gusev <
> [hidden email]>
> > >>> wrote:
> > >>>
> > >>>  Hi,
> > >>>>
> > >>>> could you create a Future in your setupRender and use actual results
> > w/
> > >>>> Future.get() during the rendering?
> > >>>>
> > >>>> As Chris said I'd also recommend you looking at the
> ProgressiveDisplay
> > >>>> component.
> > >>>>
> > >>>>
> > >>>>
> > >>>> On Tue, Apr 14, 2015 at 2:56 PM, Тимур Бухараев <
> [hidden email]>
> > >>>> wrote:
> > >>>>
> > >>>> > I can't call both in setupRender, because i need one blocking wait
> > to
> > >>>> > receive all requests in parallel.
> > >>>> >
> > >>>> > Steps:
> > >>>> > 1. prepareData(), all components send their request for data,
> > remember
> > >>>> all
> > >>>> > requests.
> > >>>> > 2. setupRender(), all components gets data from tokens. getData()
> > >>>> could
> > >>>> be
> > >>>> > like this:
> > >>>> >    Response getData() {
> > >>>> >        while ( !allRequestsAreRecieved() ) {
> > >>>> >            Thread.sleep( 10 );
> > >>>> >        }
> > >>>> >        return data;
> > >>>> >    }
> > >>>> >
> > >>>> > Now, we if we need 3 data: data1, data2, data3, we dont wait on
> > >>>> blocking
> > >>>> > calls 3 times one after one. We do one blocking call. So overall
> > delay
> > >>>> > would be max( delay1. delay2, delay3), not delay1 + delay2 +
> delay3
> > >>>> >
> > >>>> > On Tue, Apr 14, 2015 at 2:39 PM, Chris Poulsen <
> > >>>> [hidden email]>
> > >>>> > wrote:
> > >>>> >
> > >>>> > > Or maybe you can use progressive display?
> > >>>> > >
> > >>>> > >
> > >>>> >
> > >>>> http://jumpstart.doublenegative.com.au/jumpstart7/examples/ajax/
> > >>>> progressivedisplayvariations
> > >>>> > >
> > >>>> > > On Tue, Apr 14, 2015 at 1:36 PM, Chris Poulsen <
> > >>>> [hidden email]>
> > >>>> > > wrote:
> > >>>> > >
> > >>>> > > > If your prepareData() is non-blocking, why not just call it
> > right
> > >>>> > before
> > >>>> > > > you do the token.getData() ? (both in setupRender() )
> > >>>> > > >
> > >>>> > > > On Tue, Apr 14, 2015 at 1:03 PM, Тимур Бухараев <
> > >>>> [hidden email]>
> > >>>> > > > wrote:
> > >>>> > > >
> > >>>> > > >> Hi,
> > >>>> > > >>
> > >>>> > > >> My pages consist page class and several components inside.
> > >>>> > > >>
> > >>>> > > >> Page and its components needs some information from remote
> > >>>> services. I
> > >>>> > > get
> > >>>> > > >> this information with blocking calls in setupRender(). For
> > >>>> example,
> > >>>> > if i
> > >>>> > > >> need user's profile data, i get it like this:
> > >>>> > > >>
> > >>>> > > >> setupRender() {
> > >>>> > > >>  profileData = loadProfileDate(); // blocking call, waiting
> for
> > >>>> the
> > >>>> > > >> response
> > >>>> > > >> }
> > >>>> > > >>
> > >>>> > > >> And now i can use profileData in render to show some
> > information.
> > >>>> > > >>
> > >>>> > > >> The problem is page and components need many remote data, so
> > >>>> there
> > >>>> are
> > >>>> > > >> many
> > >>>> > > >> serial requests to remote services. It harms latency, because
> > >>>> overall
> > >>>> > > >> latency is sum of serial requests delays.
> > >>>> > > >>
> > >>>> > > >> I have idea to improve latency, sending requests in
> parallel. I
> > >>>> want
> > >>>> > > make
> > >>>> > > >> non blocking function sendRequest, which returns me token.
> All
> > >>>> > > components
> > >>>> > > >> call non blocking sendRequest for remote data, then i'll wait
> > in
> > >>>> > > blocking
> > >>>> > > >> call waitResponses(), which wait for all responses.Then
> > component
> > >>>> get
> > >>>> > > >> their
> > >>>> > > >> data from token.
> > >>>> > > >>
> > >>>> > > >> Some code for illustration:
> > >>>> > > >>
> > >>>> > > >> MyComponent {
> > >>>> > > >>     @Inject
> > >>>> > > >>     private RemoteService remoteService;
> > >>>> > > >>
> > >>>> > > >>     private Token<Response> token;
> > >>>> > > >> }
> > >>>> > > >>
> > >>>> > > >> void prepareData() {
> > >>>> > > >>     token = remoteService.sendRequest(); // non blocking call
> > >>>> > > >> }
> > >>>> > > >>
> > >>>> > > >> void setupRender() {
> > >>>> > > >>     Response response = token.getData(); // first call is
> > >>>> blocking,
> > >>>> > wait
> > >>>> > > >> for all responses, other calls just return data;
> > >>>> > > >> }
> > >>>> > > >>
> > >>>> > > >> Why i did not just realize my idea and write this post?
> > >>>> > > >>
> > >>>> > > >> Because i need two separate phases: first for send request,
> and
> > >>>> second
> > >>>> > > for
> > >>>> > > >> prepare rendering. All componets should send in first phase,
> > and
> > >>>> after
> > >>>> > > get
> > >>>> > > >> data in second.
> > >>>> > > >>
> > >>>> > > >> Tapestry have setupRender and beginRender, but they have
> > another
> > >>>> > order.
> > >>>> > > It
> > >>>> > > >> call setupRender and beginRender for first component, and
> then
> > -
> > >>>> for
> > >>>> > > >> second. But i need phase 1 calls for all components, then
> > phase 2
> > >>>> call
> > >>>> > > for
> > >>>> > > >> all components.
> > >>>> > > >>
> > >>>> > > >> And now my question is: is there any way in Tapestry to
> create
> > >>>> this
> > >>>> > > >> phases?
> > >>>> > > >> Thank you for your attention, sorry for my English.
> > >>>> > > >>
> > >>>> > > >
> > >>>> > > >
> > >>>> > >
> > >>>> >
> > >>>>
> > >>>>
> > >>>>
> > >>>> --
> > >>>> Dmitry Gusev
> > >>>>
> > >>>> AnjLab Team
> > >>>> http://anjlab.com
> > >>>>
> > >>>>
> > >>>
> > >>>
> > >
> > > --
> > > Thiago H. de Paula Figueiredo
> > > Tapestry, Java and Hibernate consultant and developer
> > > http://machina.com.br
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: [hidden email]
> > > For additional commands, e-mail: [hidden email]
> > >
> > >
> >
>
Reply | Threaded
Open this post in threaded view
|

Re: parallel remote requests in Tapestry

Тимур Бухараев
In reply to this post by Thiago H de Paula Figueiredo
I know about mechanics of Future and other java.utils.concurrent.
I don't know how it helps to solve my question.

Future.get() is just a kind of blocking call.
If i have two independent components, i should call Future.get() two times
in their setupRender. So i get two consecutive delays. Overall delay would
be summ of separate delays for each component.

The question is really about Tapestry rendering pipeline. I need iterate
over all components in page before they start render, to send remote
requests.

On Tue, Apr 14, 2015 at 9:57 PM, Thiago H de Paula Figueiredo <
[hidden email]> wrote:

> On Tue, 14 Apr 2015 11:08:11 -0300, Тимур Бухараев <[hidden email]>
> wrote:
>
>  I don't know how to solve my problem with Future. If you know, explain
>> please.
>>
>
> That's not a Tapestry-specific question, so I suggest you to find and read
> tutorials like this: http://java.dzone.com/articles/
> javautilconcurrentfuture.
>
>  ProgressiveDisplay is a solution, but has some disadvantages.
>>
>
> Yep. But it does fit in many situations, so I think it should be an option
> you have in mind when thinking about specific components.
>
>  Now about moving data fetch logic.
>>
>> The problem is components are independent. Page class doesn't know about
>> Component classes, component classes don't know about page and other
>> components. They just embedded in a single tml document. So designer
>> could move component to other place, and it still works. Each component
>> fetches
>> his own remote data independently. I can cache this data in service, if
>> some components need same data, so the second component get cached data.
>> But component is the only place who knows, what data it needs. For
>> example, component displaying user profile. It needs user profile data, and
>> it
>> fetches it. So component is the only thing who knows it need profile
>> data. But i can embed it in any tml in any place.
>>
>
> Ok! Of course, one solution doesn't cover all situations, and the service
> one doesn't cover yours.
>
> Some time ago there was a discussion about parallel rendering of
> components in this mailing list. My conclusion of it it's that it can be
> done, but you have to be extra-extra-extra careful.
> http://apache-tapestry-mailing-list-archives.1045711.
> n5.nabble.com/quot-Parallel-quot-component-rendering-td5729024.html. It's
> a very interesting read, with lots of interesting opinions.
>
> I have one different suggestion now: cache the results of these slow
> method calls so, the next time you have to make one, you already have the
> result ready. Of course, caching should be done very carefully, when when
> it's done, it does wonders for performance and request times.
>
>
> --
> Thiago H. de Paula Figueiredo
> Tapestry, Java and Hibernate consultant and developer
> http://machina.com.br
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>
Reply | Threaded
Open this post in threaded view
|

Re: parallel remote requests in Tapestry

Cezary Biernacki
In reply to this post by Тимур Бухараев
As I wrote before, PageAttached is invoked on all pages somehow related to
request (e.g. if some component uses @InjectPage to refer some other page),
not only on rendered page. I have not really used PageAttached in the
production code myself, so it is only speculations, but maybe you could
detect which components are from active page, by checking the active page
from RequestGlobal and the page name containing the component via
ComponentResources. For debugging purposes, you can also get component's ID
from ComponentResources.getCompleteId() - it might help you understand on
what components pageAttached() is invoked.

Regarding, Heartbeat, you can check how standard Tapestry's Label and Error
components use it. They are quite simple, and just modify a single
attribute,on a previously created Element, but potentially you can create
any DOM tree you want. Of course, it would require much more work then just
using normal Tapestry templates, and probably it would prevent using nested
components.

Depending on complexity of the project and time you can spend, I would
recommend considering the following questions in this order:

   - Can you make remote invocations somehow faster, e.g. by
   caching/preloading some data?

   - Can you put slow components either in ProgressiveDisplay or separate
   IFRAMEs, so initial page will appear faster? If you track users sessions,
   you might even initiate asynchronous calls on the main page load, and
   retrieve results in ProgressiveDisplay from the session.

   - Can you initiate remote calls in page's onActivate() and pass
   Future/Token object to components as parameters? Probably it would require
   some duplication in code, but it is a simple and easy solution.

   - If your slow components are quite simple (e.g. just display a single
   text/number value that is just slow to compute or retrieve), use Heartbeat.
   But if they are complicated and/or use subcomponents, Heartbeat-solution
   probably would be to cumbersome. If you are using Tapestry 5.4,
   try PartialTemplateRenderer service, it might help you to generate partial
   DOM from component body.

   - Try pageAttached() approach, but it does not guarantee success, and
   they are many corner cases.

   - Add your own prepareData() mechanism. I think it is possible, but
   requires a lot of Tapestry knowledge, and maybe accessing internal Tapestry
   API.


Best regards,
Cezary




On Tue, Apr 14, 2015 at 9:04 PM, Тимур Бухараев <[hidden email]> wrote:

> Yes, i tried PageAttached. I put logs to see call sequences. PageAttached
> works fine for page class, but i see many chaotic calls per component. I
> expect one call per request per component, but see there are many calls per
> component. I dont know why.
>
> Heartbeat is really interesting option. Thank you for idea. The next my
> question is: how update template with actual content in deffered commands?
>
> On Tue, Apr 14, 2015 at 9:05 PM, Cezary Biernacki <[hidden email]>
> wrote:
>
> > Hi Тимур,
> > Have you tried putting your asynchronous in pageAttached() methods (also
> > see @PageAttached annotation) in your components?
> >
> > https://tapestry.apache.org/page-life-cycle.html
> >
> > However pageAttached is invoked on all pages that are somehow involved in
> > the request processing (e.g. they are referenced via PageLink component)
> > and also for requests which are not rendered, so you would need some
> extra
> > checks to prevent unintended remote service calls.
> >
> > PageAttached is deprecated in Tapestry 5.3, but it seems to be back and
> > working in 5.4.
> >
> >
> >
> http://tapestry.apache.org/5.3/apidocs/org/apache/tapestry5/annotations/PageAttached.html
> >
> >
> http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/annotations/PageAttached.html
> >
> >
> > Another option is to use Heartbeat environmental service /
> > @HeartbeatDeferred annotation. In this case the component during normal
> > rendering just prepares some static template as Tapestry DOM, and invokes
> > asynchronous remote call, then on deferred call update the template with
> > actual content.
> >
> >
> > Best regards,
> > Cezary
> >
> >
> > On Tue, Apr 14, 2015 at 4:08 PM, Тимур Бухараев <[hidden email]>
> > wrote:
> >
> > > I don't know how to solve my problem with Future. If you know, explain
> > > please.
> > >
> > > ProgressiveDisplay is a solution, but has some disadvantages.
> > >
> > > Now about moving data fetch logic.
> > >
> > > The problem is components are independent. Page class doesn't know
> about
> > > Component classes, component classes don't know about page and other
> > > components. They just embedded in a single tml document. So designer
> > could
> > > move component to other place, and it still works. Each component
> fetches
> > > his own remote data independently. I can cache this data in service, if
> > > some components need same data, so the second component get cached
> data.
> > > But component is the only place who knows, what data it needs. For
> > example,
> > > component displaying user profile. It needs user profile data, and it
> > > fetches it. So component is the only thing who knows it need profile
> > data.
> > > But i can embed it in any tml in any place.
> > >
> > > On Tue, Apr 14, 2015 at 4:27 PM, Thiago H de Paula Figueiredo <
> > > [hidden email]> wrote:
> > >
> > > > On Tue, 14 Apr 2015 09:22:36 -0300, Тимур Бухараев <
> > [hidden email]>
> > > > wrote:
> > > >
> > > >  sorry, some mistake in sequence
> > > >>
> > > >> it should be:
> > > >> component1.setupRender();
> > > >> other component1 rendering
> > > >> component2.setupRender();
> > > >> other component2 rendering
> > > >>
> > > >
> > > > If you think Future is not the way to go (and that's what I'd use
> and I
> > > > think it covers your problem from in the description you gave) and
> > > neither
> > > > ProgressiveDisplay is (which is a good other solution), why don't you
> > > move
> > > > the data fetch logic for all components in a single place
> (preferably a
> > > > service, maybe the page) so you can properly parallelize it and the
> > > > components themselves just receive the data instead of fetching it?
> > > >
> > > >
> > > >
> > > >> On Tue, Apr 14, 2015 at 3:17 PM, Тимур Бухараев <
> [hidden email]>
> > > >> wrote:
> > > >>
> > > >>  Hello,
> > > >>>
> > > >>> Future would not helps, because components renders one after one.
> > > >>> For example page contains component1 and component2.
> > > >>>
> > > >>> The render sequence is next:
> > > >>>
> > > >>> component1.setupRender();
> > > >>> other component1 rendering
> > > >>> component1.setupRender();
> > > >>> other component2 rendering
> > > >>>
> > > >>> So if i create Future in setupRender and get result, i get delay1
> in
> > > >>> rendering component1, and delay2 in rendering component2. Overall
> > delay
> > > >>> would be delay1+delay2.
> > > >>> If page is complex and contains many independent components which
> > call
> > > >>> many remote services, overall delay could be very much.
> > > >>>
> > > >>>
> > > >>> Thank you and Chris for ProgressiveDisplay recommending, i'll look
> > it.
> > > >>>
> > > >>> On Tue, Apr 14, 2015 at 3:00 PM, Dmitry Gusev <
> > [hidden email]>
> > > >>> wrote:
> > > >>>
> > > >>>  Hi,
> > > >>>>
> > > >>>> could you create a Future in your setupRender and use actual
> results
> > > w/
> > > >>>> Future.get() during the rendering?
> > > >>>>
> > > >>>> As Chris said I'd also recommend you looking at the
> > ProgressiveDisplay
> > > >>>> component.
> > > >>>>
> > > >>>>
> > > >>>>
> > > >>>> On Tue, Apr 14, 2015 at 2:56 PM, Тимур Бухараев <
> > [hidden email]>
> > > >>>> wrote:
> > > >>>>
> > > >>>> > I can't call both in setupRender, because i need one blocking
> wait
> > > to
> > > >>>> > receive all requests in parallel.
> > > >>>> >
> > > >>>> > Steps:
> > > >>>> > 1. prepareData(), all components send their request for data,
> > > remember
> > > >>>> all
> > > >>>> > requests.
> > > >>>> > 2. setupRender(), all components gets data from tokens.
> getData()
> > > >>>> could
> > > >>>> be
> > > >>>> > like this:
> > > >>>> >    Response getData() {
> > > >>>> >        while ( !allRequestsAreRecieved() ) {
> > > >>>> >            Thread.sleep( 10 );
> > > >>>> >        }
> > > >>>> >        return data;
> > > >>>> >    }
> > > >>>> >
> > > >>>> > Now, we if we need 3 data: data1, data2, data3, we dont wait on
> > > >>>> blocking
> > > >>>> > calls 3 times one after one. We do one blocking call. So overall
> > > delay
> > > >>>> > would be max( delay1. delay2, delay3), not delay1 + delay2 +
> > delay3
> > > >>>> >
> > > >>>> > On Tue, Apr 14, 2015 at 2:39 PM, Chris Poulsen <
> > > >>>> [hidden email]>
> > > >>>> > wrote:
> > > >>>> >
> > > >>>> > > Or maybe you can use progressive display?
> > > >>>> > >
> > > >>>> > >
> > > >>>> >
> > > >>>> http://jumpstart.doublenegative.com.au/jumpstart7/examples/ajax/
> > > >>>> progressivedisplayvariations
> > > >>>> > >
> > > >>>> > > On Tue, Apr 14, 2015 at 1:36 PM, Chris Poulsen <
> > > >>>> [hidden email]>
> > > >>>> > > wrote:
> > > >>>> > >
> > > >>>> > > > If your prepareData() is non-blocking, why not just call it
> > > right
> > > >>>> > before
> > > >>>> > > > you do the token.getData() ? (both in setupRender() )
> > > >>>> > > >
> > > >>>> > > > On Tue, Apr 14, 2015 at 1:03 PM, Тимур Бухараев <
> > > >>>> [hidden email]>
> > > >>>> > > > wrote:
> > > >>>> > > >
> > > >>>> > > >> Hi,
> > > >>>> > > >>
> > > >>>> > > >> My pages consist page class and several components inside.
> > > >>>> > > >>
> > > >>>> > > >> Page and its components needs some information from remote
> > > >>>> services. I
> > > >>>> > > get
> > > >>>> > > >> this information with blocking calls in setupRender(). For
> > > >>>> example,
> > > >>>> > if i
> > > >>>> > > >> need user's profile data, i get it like this:
> > > >>>> > > >>
> > > >>>> > > >> setupRender() {
> > > >>>> > > >>  profileData = loadProfileDate(); // blocking call, waiting
> > for
> > > >>>> the
> > > >>>> > > >> response
> > > >>>> > > >> }
> > > >>>> > > >>
> > > >>>> > > >> And now i can use profileData in render to show some
> > > information.
> > > >>>> > > >>
> > > >>>> > > >> The problem is page and components need many remote data,
> so
> > > >>>> there
> > > >>>> are
> > > >>>> > > >> many
> > > >>>> > > >> serial requests to remote services. It harms latency,
> because
> > > >>>> overall
> > > >>>> > > >> latency is sum of serial requests delays.
> > > >>>> > > >>
> > > >>>> > > >> I have idea to improve latency, sending requests in
> > parallel. I
> > > >>>> want
> > > >>>> > > make
> > > >>>> > > >> non blocking function sendRequest, which returns me token.
> > All
> > > >>>> > > components
> > > >>>> > > >> call non blocking sendRequest for remote data, then i'll
> wait
> > > in
> > > >>>> > > blocking
> > > >>>> > > >> call waitResponses(), which wait for all responses.Then
> > > component
> > > >>>> get
> > > >>>> > > >> their
> > > >>>> > > >> data from token.
> > > >>>> > > >>
> > > >>>> > > >> Some code for illustration:
> > > >>>> > > >>
> > > >>>> > > >> MyComponent {
> > > >>>> > > >>     @Inject
> > > >>>> > > >>     private RemoteService remoteService;
> > > >>>> > > >>
> > > >>>> > > >>     private Token<Response> token;
> > > >>>> > > >> }
> > > >>>> > > >>
> > > >>>> > > >> void prepareData() {
> > > >>>> > > >>     token = remoteService.sendRequest(); // non blocking
> call
> > > >>>> > > >> }
> > > >>>> > > >>
> > > >>>> > > >> void setupRender() {
> > > >>>> > > >>     Response response = token.getData(); // first call is
> > > >>>> blocking,
> > > >>>> > wait
> > > >>>> > > >> for all responses, other calls just return data;
> > > >>>> > > >> }
> > > >>>> > > >>
> > > >>>> > > >> Why i did not just realize my idea and write this post?
> > > >>>> > > >>
> > > >>>> > > >> Because i need two separate phases: first for send request,
> > and
> > > >>>> second
> > > >>>> > > for
> > > >>>> > > >> prepare rendering. All componets should send in first
> phase,
> > > and
> > > >>>> after
> > > >>>> > > get
> > > >>>> > > >> data in second.
> > > >>>> > > >>
> > > >>>> > > >> Tapestry have setupRender and beginRender, but they have
> > > another
> > > >>>> > order.
> > > >>>> > > It
> > > >>>> > > >> call setupRender and beginRender for first component, and
> > then
> > > -
> > > >>>> for
> > > >>>> > > >> second. But i need phase 1 calls for all components, then
> > > phase 2
> > > >>>> call
> > > >>>> > > for
> > > >>>> > > >> all components.
> > > >>>> > > >>
> > > >>>> > > >> And now my question is: is there any way in Tapestry to
> > create
> > > >>>> this
> > > >>>> > > >> phases?
> > > >>>> > > >> Thank you for your attention, sorry for my English.
> > > >>>> > > >>
> > > >>>> > > >
> > > >>>> > > >
> > > >>>> > >
> > > >>>> >
> > > >>>>
> > > >>>>
> > > >>>>
> > > >>>> --
> > > >>>> Dmitry Gusev
> > > >>>>
> > > >>>> AnjLab Team
> > > >>>> http://anjlab.com
> > > >>>>
> > > >>>>
> > > >>>
> > > >>>
> > > >
> > > > --
> > > > Thiago H. de Paula Figueiredo
> > > > Tapestry, Java and Hibernate consultant and developer
> > > > http://machina.com.br
> > > >
> > > > ---------------------------------------------------------------------
> > > > To unsubscribe, e-mail: [hidden email]
> > > > For additional commands, e-mail: [hidden email]
> > > >
> > > >
> > >
> >
>
Reply | Threaded
Open this post in threaded view
|

Re: parallel remote requests in Tapestry

Thiago H de Paula Figueiredo
In reply to this post by Тимур Бухараев
On Tue, 14 Apr 2015 16:17:48 -0300, Тимур Бухараев <[hidden email]>  
wrote:

> The question is really about Tapestry rendering pipeline. I need iterate
> over all components in page before they start render, to send remote
> requests.

Well, in a page or component you can @Inject ComponentResources resources;  
and use resources.getComponentModel().getEmbeddedComponentIds() to know  
the ids of the components declared in its template and  
resources.getEmbeddedComponent(String embeddedId), to get the component  
instance, returned as a Component interface reference, and do this  
recursively, traversing the component tree. You cannot add your own  
component rendering lifecycle events. From now, you can define an  
interface your "parallel" components can implement and call its methods in  
case the component instances implement this interface. Another option,  
maybe the most recommended, but you can trigger events on them by calling  
getComponentResources().triggerEvent() method on the Component instance.  
When Tapestry does bytecode manipulation on your page and component  
classes, it makes them implement the Component interface.

By itself, the Tapestry rendering pipeline doesn't support parallel  
rendering.

--
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: parallel remote requests in Tapestry

Thiago H de Paula Figueiredo
In reply to this post by Тимур Бухараев
On Tue, 14 Apr 2015 16:04:27 -0300, Тимур Бухараев <[hidden email]>  
wrote:

> Heartbeat is really interesting option. Thank you for idea. The next my
> question is: how update template with actual content in deffered  
> commands?

Templates cannot be rendered in a deferred way. What Label does is to use  
MarkupWriter to generate markup programatically:

     boolean beginRender(MarkupWriter writer)
     {
         final Field field = this.field;

         decorator.beforeLabel(field);

         labelElement = writer.element("label");

         resources.renderInformalParameters(writer);

         // Since we don't know if the field has rendered yet, we need to  
defer writing the for and id
         // attributes until we know the field has rendered (and set its  
clientId property). That's
         // exactly what Heartbeat is for.

         Runnable command = new Runnable()
         {
             public void run()
             {
                 String fieldId = field.getClientId();

                 labelElement.forceAttributes("for", fieldId, "id", fieldId  
+ "-label");

                 decorator.insideLabel(field, labelElement);
             }
         };

         heartbeat.defer(command);

         return !ignoreBody;
     }

Anyway, the approach I described in another e-mail in this thread should  
be enough for you to traverse the component tree, trigger an event telling  
components to start fetching data (probably wrapped in a Future) and after  
that letting rendering happen normally.

--
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: parallel remote requests in Tapestry

Thiago H de Paula Figueiredo
In reply to this post by Cezary Biernacki
On Tue, 14 Apr 2015 14:05:33 -0300, Cezary Biernacki <[hidden email]>  
wrote:

> Hi Тимур,
> Have you tried putting your asynchronous in pageAttached() methods (also
> see @PageAttached annotation) in your components?
>
> https://tapestry.apache.org/page-life-cycle.html
>
> However pageAttached is invoked on all pages that are somehow involved in
> the request processing (e.g. they are referenced via PageLink component)

@PageAttached only makes sense in a page pool and Tapestry doesn't use one  
since 5.2. I guess its undeprecation was a mistake. Or I have no idea why  
that happened.

--
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: parallel remote requests in Tapestry

Cezary Biernacki
It seems that PageAttached was un-deprecated in 5.4 some time ago, however
I am not sure about the motivation:

https://apache.googlesource.com/tapestry-5/+/0998b92d51d475ed20fa5aadea06bc5bd37c39a8%5E%21/

I believe that PageAttached can still be useful even when there is no page
pool. The code still can set internal component fields with some dynamic
values, even if actually it sets some request attributes. PageAttached is a
bit more comprehensive than onActivate() because can be implemented by
components and non-active pages.



On Tue, Apr 14, 2015 at 11:50 PM, Thiago H de Paula Figueiredo <
[hidden email]> wrote:

> On Tue, 14 Apr 2015 14:05:33 -0300, Cezary Biernacki <[hidden email]>
> wrote:
>
>  Hi Тимур,
>> Have you tried putting your asynchronous in pageAttached() methods (also
>> see @PageAttached annotation) in your components?
>>
>> https://tapestry.apache.org/page-life-cycle.html
>>
>> However pageAttached is invoked on all pages that are somehow involved in
>> the request processing (e.g. they are referenced via PageLink component)
>>
>
> @PageAttached only makes sense in a page pool and Tapestry doesn't use one
> since 5.2. I guess its undeprecation was a mistake. Or I have no idea why
> that happened.
>
> --
> Thiago H. de Paula Figueiredo
> Tapestry, Java and Hibernate consultant and developer
> http://machina.com.br
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>
Reply | Threaded
Open this post in threaded view
|

Re: parallel remote requests in Tapestry

Lance Java
In reply to this post by Тимур Бухараев
For this to work, I think the actual rendering needs to happen on the
request thread.

See the gist here: https://gist.github.com/anonymous/379b3aae199147684841

By using the parallel component you can ask for an Invokable (which does
the 'work') and a binding (the property to set).
You would provide a body template for each 'parallel' instance which
ultimately references the property
The parallelContainer component would orchestrate the whole thing (using an
environmental)

1. Invokables are fired in parallel
2. Once all invokables have finished, the bindings is set with the result
(on the request thread)
3. Once the binding is set, the body (of each parallel component) can be
renderered (on the request thread)
Reply | Threaded
Open this post in threaded view
|

Re: parallel remote requests in Tapestry

Lance Java
In reply to this post by Тимур Бухараев
This sounded like a fun challenge so I implemented it in tapestry-stitch
Demo here with source code: http://t5stitch-lazan.rhcloud.com/paralleldemo
Rendering all happens on the request thread, workers are invoked in
parallel.

Enjoy!