Re: Callback to delay a Server::TCP component?

Mike Schilli <[email protected]> Sun, 18 Apr 2010 22:45:01 -0700 (PDT)
Newsgroups gmane.comp.lang.perl.poe
Message-ID <alpine.LRH.1.00.1004182133100.19219@pyramidlake.greatamerica.corp.yahoo.com>
On Sun, 18 Apr 2010, [email protected] wrote:

>   This is a problem that we've thought of and solved. See the
>   "Concurrency" option to PoCo::Server::TCP

I should have been more clear. In my case, the server has already
accepted the client connection, but needs to hold off on forwarding the
request to the forwarding port until PoCo::Client::TCP has established
the outgoing connection.

I've reworked the code to use a heap variable instead of a global, and
all of a sudden it doesn't look so bad now:

     ###########################################
     sub client_request {
     ###########################################
       my ($kernel, $heap, $request) =
          @_[ KERNEL, HEAP, ARG0 ];

       INFO "Waiting for turn ...";
       $kernel->run_one_timeslice() while
         ! $heap->{client_heap}->{connected};

       INFO "Done waiting.";

       $heap->{client_heap}->
              {server}->put( $request );
     }

Only remaining ugliness is the run_one_timeslice(), which I'm not a big
fan of, as it makes it harder to follow the event flow.

Coming back to my original question, which is not really related to
PoCo::Server/Client::TCP specifically, but to POE in general: If
a component offers a callback, the approved/best way to 'wait' for an
event within the callback seems to be run_one_timeslice()?

Too bad the callback is a syncronous call and not an event and therefore
I can't say "erm, I'm not ready for this callback yet, come back after
two seconds" unless the component implements this explicitly.

-- Mike

Mike Schilli
[email protected]

>   http://search.cpan.org/~rcaputo/POE-1.289/lib/POE/Component/Server/TCP.pm#Concurrency
>
>   You must have missed that part or the docs wasn't clear. If you have 
> suggestions on how to make it more clearer - please let us know!
>
>   Happy hacking! :)
>
> ~Apocalypse
>
> Mike Schilli wrote:
>> Hi POE folks,
>> 
>> while writing a port forwarder similar to the one in the POE cookbook,
>> just by using POE::Component::Server::TCP and ::Client::TCP instead, I hit
>> a roadblock when it came to synchronizing the components.
>> 
>> After POE::Component::Server::TCP has started up (binding to the 'From'
>> port), if a client connects to it, the server will call the
>> client_connect callback, which I'm using to spawn an instance of
>> POE::Component::Client::TCP to connect to the 'To' port.
>> 
>> At this time, I need the server to wait accepting requests from the
>> connecting client *until* POE::Component::Client::TCP has connected to the
>> 'To' port.
>> 
>> However, there's no way to say in the client_connect callback that the
>> server should not proceed to the 'client_request' stage yet.
>> 
>> I found a workaround by setting a global variable $CONNECTED in
>>
>>   my $client_session =
>>     POE::Component::Client::TCP->new(
>>         # ...
>>         Connected => sub { $CONNECTED = 1; },
>>         # ...
>> 
>> and adding
>>
>>   $kernel->run_one_timeslice() while !$CONNECTED;
>> 
>> to the client_request callback of the POE::Component::Server::TCP
>> server. This does the trick, but I don't like that it's a
>> global variable that allows only single use of this component.
>> 
>> Is there a better way?
>> 
>> -- Mike
>> 
>> Mike Schilli
>> [email protected]
>