Ahh, thanks for clarifying this! Yeah, I agree that using
run_one_timeslice() is a path to insanity, ha!
What I would recommend is the "tried and true" method of... buffering
the request? The server simply sends the request to the "forwarder" tcp
session
and it just stores the request in it's heap and when it's connected, it
gets the request and does it's stuff? You can always create new
InlineStates in
the PoCo::Client::TCP session and use it to queue up requests.
Pseudocode:
server tcp session:
client connects, sends request
spawn forwarder session
send request to forwarder session -> event "queue_request"
forwarder session:
event "queue_request" receives requests and stores it in an array in
the heap
on connect, retrieve requests from queue and send them
event "queue_request" now changes behavior and does not store
requests in the array - it's connected so it immediately does a put()
if it fails to connect, get request from queue and reply back to
server with an error
Hope this makes sense and is the right concept now :)
P.S. This kind of design pattern is exactly what Rocco is trying to
simplify with "Reflex" - you should check out his great work on it!
~Apocalypse
Mike Schilli wrote:
On Sun, 18 Apr 2010, p...@0ne.us 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
m...@perlmeister.com
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
m...@perlmeister.com