Home > Archive > PERL POE > June 2005 > Timing issues with PoCo::HTTPD and PoCo::IRC?
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Timing issues with PoCo::HTTPD and PoCo::IRC?
|
|
| Ciro The Spider-Man 2005-06-08, 9:04 pm |
| This is probably a really dumb question, but I've dug through the docs
and messed around with the code for hours, and I still can't solve
this one problem. Any help would be appreciated:
The project at hand is an IRC bot with web connectivity. The desired
end at this point is to visit http://hostname:port/whois/username, and
have the web browser output the data from the irc_whois event. I tried
throwing the event from within the ContentHandler, and when that
didn't work, I moved it all the way up to the transhandler, but it
still doesn't seem to want to cooperate. It seems to insist on going
ALL the way through the ContentHandler, THEN processing the
$irc->yield('whois', $nick); command, so effectively the web browser
is always 1 query behind. Is there any way I can make
POE::Component::Server::HTTP branch immediately and wait for the
result?
Here's the relevant (I think) code.
my $session = POE::Session->create(...);
my ($irc) = POE::Component::IRC->spawn('alias' => 'irc_client');
#Standard IRC events here.
sub irc_whois
{
my $info=parseWhois($_[ARG0]);
print "DEBUG: Whois Event Triggered\n";
$_[HEAP]->{'whoisinfo'} = $info;
if ($info ne '') {return 0;}
}
#more junk
my $httpd = POE::Component::Server::HTTP->new(
Port => 8080,
ContentHandler=> {
'/' => \&defaultHandler, # Just prints a generic message
'/whois/' => \&whoisHandler,
},
TransHandler => [ \&trans ],
);
sub trans
{
my ($request, $response) = @_;
my $nick = (split('/', $request->uri))[4];
$irc->yield('whois'=>nick);
}
sub whoisHandler
{
my ($request, $response) = @_;
my $heap= $session->get_heap();
my $output=$heap->{'whoisinfo'};
print "DEBUG: Outputting Page\n";
$response->content("$Output");
}
Yet the console output always comes out like so:
DEBUG: Outputting Page
DEBUG: Whois Event Triggered
So of course, when the next query comes around, the first query is
still sitting on the heap, so it gets used, then overwritten, etc...
What fundamental fact am I overlooking?
Thanks for any tips.
-C
--
| |
| Jay Jarvinen 2005-06-08, 9:04 pm |
| On Sun, 13 Mar 2005 06:28:24 -0500
Ciro The Spider-Man <g ciro@gmail.com> wrote:
> The project at hand is an IRC bot with web connectivity. The desired
> end at this point is to visit http://hostname:port/whois/username, and
> have the web browser output the data from the irc_whois event. I tried
[...]
> is always 1 query behind. Is there any way I can make
> POE::Component::Server::HTTP branch immediately and wait for the
> result?
[...]
> So of course, when the next query comes around, the first query is
> still sitting on the heap, so it gets used, then overwritten, etc...
>
> What fundamental fact am I overlooking?
>
> Thanks for any tips.
> -C
Greetings,
Be advised, my first post to the list, I'm new to POE. But it's been a
few hours without a reply, and this list doesn't see much traffic,
therefore .. I'll take a swing:
First, have you looked at this?
http://poe.perl.org/?POE_Cookbook/W...er_With_Forking
Next, although it's a client, not server, Randal's article entitled
"Doing many things at once" seems relevant:
http://www.stonehenge.com/merlyn/LinuxMag/col41.html
It sounds like you want to be using 'call' instead of 'yield'. (see
POE::Kernel) This of course, will block _everything_ until that whois
finishes. I'd worry about forking first, then your choice of call or
yield seems moot, I believe.
But now let me ask you this: Are you sure you want POE for the HTTP
server? (ayee! 1st post heresy?!) I understand this lets the IRC part
stay connected, as well as serving the HTTP requests. But have you
considered having a standard CGI talk to your stay-connected-POE IRC
bot (behind the scenes)? Just a thought ..
That, or even .. *must* it be real-time? Otherwise, you could just
periodically write out the whois for all users, to a place the server
can get to it.
No offense intended to the respective POE/HTTP authors, just trying to
provide alternatives, and I'm always very hesitant to reinvent Apache
for public use.
-Jay
| |
| Rocco Caputo 2005-06-08, 9:04 pm |
| On Sun, Mar 13, 2005 at 06:28:24AM -0500, Ciro The Spider-Man wrote:
> The project at hand is an IRC bot with web connectivity. The desired
> end at this point is to visit http://hostname:port/whois/username, and
> have the web browser output the data from the irc_whois event. I tried
> throwing the event from within the ContentHandler, and when that
> didn't work, I moved it all the way up to the transhandler, but it
> still doesn't seem to want to cooperate. It seems to insist on going
> ALL the way through the ContentHandler, THEN processing the
> $irc->yield('whois', $nick); command, so effectively the web browser
> is always 1 query behind. Is there any way I can make
> POE::Component::Server::HTTP branch immediately and wait for the
> result?
>
> Here's the relevant (I think) code.
>
> my $session = POE::Session->create(...);
> my ($irc) = POE::Component::IRC->spawn('alias' => 'irc_client');
> #Standard IRC events here.
>
> sub irc_whois
> {
> my $info=parseWhois($_[ARG0]);
> print "DEBUG: Whois Event Triggered\n";
> $_[HEAP]->{'whoisinfo'} = $info;
> if ($info ne '') {return 0;}
> }
The problem I see with irc_whois() is that it can only handle one
request at a time.
> #more junk
>
> my $httpd = POE::Component::Server::HTTP->new(
> Port => 8080,
> ContentHandler=> {
> '/' => \&defaultHandler, # Just prints a generic message
> '/whois/' => \&whoisHandler,
> },
> TransHandler => [ \&trans ],
> );
>
> sub trans
> {
> my ($request, $response) = @_;
> my $nick = (split('/', $request->uri))[4];
> $irc->yield('whois'=>nick);
> }
You're always whois'ing "nick" (or is it the result of evaluating sub
nick() ?) Either way, it's probably not what you intended.
> sub whoisHandler
> {
> my ($request, $response) = @_;
> my $heap= $session->get_heap();
> my $output=$heap->{'whoisinfo'};
> print "DEBUG: Outputting Page\n";
> $response->content("$Output");
> }
I think a better idea is to have whoisHandler return RC_WAIT (see
perldoc POE::Component::Client::HTTP) and pass $nick and $response to
the IRC part.
The IRC part can send its whois request to IRC, build the content for
$response, then call $response->continue() to pass the response back
to the browser.
To be sure, you could have the IRC bot deposit data for apache or some
other web server to pick up. The responses won't be realtime, but
that may not be an issue.
--
Rocco Caputo - http://poe.perl.org/
| |
| Matt S Trout 2005-06-08, 9:04 pm |
| On Sun, Mar 13, 2005 at 06:28:24AM -0500, Ciro The Spider-Man wrote:
> This is probably a really dumb question, but I've dug through the docs
> and messed around with the code for hours, and I still can't solve
> this one problem. Any help would be appreciated:
>
> The project at hand is an IRC bot with web connectivity. The desired
> end at this point is to visit http://hostname:port/whois/username, and
> have the web browser output the data from the irc_whois event. I tried
> throwing the event from within the ContentHandler, and when that
> didn't work, I moved it all the way up to the transhandler, but it
> still doesn't seem to want to cooperate. It seems to insist on going
> ALL the way through the ContentHandler, THEN processing the
> $irc->yield('whois', $nick); command, so effectively the web browser
> is always 1 query behind. Is there any way I can make
> POE::Component::Server::HTTP branch immediately and wait for the
> result?
>
> Here's the relevant (I think) code.
>
>
> my $session = POE::Session->create(...);
> my ($irc) = POE::Component::IRC->spawn('alias' => 'irc_client');
> #Standard IRC events here.
>
> sub irc_whois
> {
> my $info=parseWhois($_[ARG0]);
> print "DEBUG: Whois Event Triggered\n";
> $_[HEAP]->{'whoisinfo'} = $info;
> if ($info ne '') {return 0;}
> }
>
> #more junk
>
> my $httpd = POE::Component::Server::HTTP->new(
> Port => 8080,
> ContentHandler=> {
> '/' => \&defaultHandler, # Just prints a generic message
> '/whois/' => \&whoisHandler,
> },
> TransHandler => [ \&trans ],
> );
>
> sub trans
> {
> my ($request, $response) = @_;
> my $nick = (split('/', $request->uri))[4];
> $irc->yield('whois'=>nick);
> }
>
> sub whoisHandler
> {
> my ($request, $response) = @_;
> my $heap= $session->get_heap();
> my $output=$heap->{'whoisinfo'};
> print "DEBUG: Outputting Page\n";
> $response->content("$Output");
> }
>
> Yet the console output always comes out like so:
>
> DEBUG: Outputting Page
> DEBUG: Whois Event Triggered
>
> So of course, when the next query comes around, the first query is
> still sitting on the heap, so it gets used, then overwritten, etc...
>
> What fundamental fact am I overlooking?
You're not allowing time for the whois event to execute; POE is event-driven
so things happen asynchronously. Try storing the request and response
objects in the heap along with the query, with a unique key to access them,
then in the irc_whois sub pull the reponse object and populate it there.
--
Matt S Trout Brag sheet: http://trout.me.uk/services.html
LAMP, Infrastructure Contact: services@trout.me.uk
and Automation
specialist Do it once. Do it right.
| |
| Ciro The Spider-Man 2005-06-08, 9:04 pm |
| Matt S Trout said:
>Try storing the request and response
>objects in the heap along with the query, with a unique key to access them,
>then in the irc_whois sub pull the reponse object and populate it there.
Thought about that. I was afraid that was kludgy, so I figured I'd ask
here about a "right" way to do it. ;) I'm still learning POE, so the
input doesn't hurt. :)
Duane Beck said:
>Have you tried using call instead of yield? Yield just puts the
>specified event on the waiting queue to be handled after the current
>event returns. Call will call the event handler immediately and wait
>for the result.
Yep, that was the first thing I tried. I actually completely rewrote
the IRC portion of the bot to use the 'new way.'
Jay Jarvinen said:
> But now let me ask you this: Are you sure you want POE for the HTTP
> server?
Eh, whether I want to or not is moot. The bot is actually a buddy's
project, and he asked me for help because I'm the best perl programmer
in our little clique. Then I got obsessed and sort of took over. :)
That said, for something as small as this, apache is a bit of a
heavyweight.
Rocco said:
>You're always whois'ing "nick" (or is it the result of evaluating sub
> nick() ?) Either way, it's probably not what you intended.
Yeah, that was a typo in entering the code into the mail (lack of
cut/paste). It's correct in the actual code.
>I think a better idea is to have whoisHandler return RC_WAIT (see
>perldoc POE::Component::Client::HTTP) and pass $nick and $response to
>the IRC part.
I thought of that, too, but the doc for PoCo::HTTPD seems to be a bit,
shall we say, "light" on the subject of how to actually USE it.
Whenever I tried, it failed (squid gave me an error about a "zero
length response"). I know I'm doing something wrong, but I can't
figure out exactly what.
Anyway, thanks for all the input, guys. I'll mess with it some more
and see if I can make returning RC_WAIT work.
| |
| Kidney Bingos 2005-06-08, 9:04 pm |
| Hi,
Regarding the 'irc_whois' event there was a bug with that code which is fixed in version 3.8
If you just want a quick whois kind of query for a nickname that shares a channel with the bot you are writing, then it is possible to use POE::Component::IRC::State instead of vanilla POE::Component::IRC and use the object method 'nick_info()' to gain similar information to whois ( but without thatusers channel list ).
Just a thought.
Cheers,
--
Chris Williams
aka BinGOs
PGP ID 0x4658671F
http://www.gumbynet.org.uk
==========================
|
|
|
|
|