http://qs321.pair.com?node_id=357494

epoptai has asked for the wisdom of the Perl Monks concerning the following question:

I've got a POE::Component::IRC bot with some loops that cause it to pause. This is a POE FAQ which I've read many times along with the other docs and tried to implement to no avail. These subs handle private IRC messages, and "do_help" is where the program pauses. I appreciate any assistance you can offer in using yield to handle simultaneous requests.
# HANDLES PRIVATE MSG sub irc_msg { my $kernel = $_[KERNEL]; my $nick = (split /!/, $_[ARG0])[0]; my $msg = $_[ARG2]; my $say = process_msg($kernel, $nick, $msg); if ($say) { $kernel->post($bot, 'privmsg', $nick, $say); } } # PROCESSES PRIVATE MSG sub process_msg { my ($kernel,$nick,$arg) = @_; if ($arg =~ /^help/) { do_help($kernel,$nick) } } # PRINTS BOT HELP sub do_help { my ($kernel,$nick) = @_; my @help = ( "This array has many lines..", ); for (@help) { # BOT PAUSES TO COMPLETE THIS LOOP $kernel->post($bot, 'privmsg', $nick, $_); } }

--
perl -MO=Deparse -e"u j t S n a t o e h r , e p l r a h k c r e"

Replies are listed 'Best First'.
•Re: Prevent POE IRC bot pause
by merlyn (Sage) on May 29, 2004 at 19:04 UTC
Re: Prevent POE IRC bot pause
by rcaputo (Chaplain) on May 30, 2004 at 20:02 UTC

    Update: Replaced the pre tags around the code with code tags, per tye's recommendation.

    This question comes up a lot, so I've written a response for the FAQ at POE's wiki. The rest of this node is a copy of that FAQ answer.

    POE::Component::IRC seems slow for three reasons.

    IRC servers have evolved in hostile environments. Less mature users send messages in rapid succession as a form of denial of service attack against networks and other users.

    IRC servers buffer and rate-limit input to minimize the effects of these "flood" attacks. Client input is released from the server's buffers at human typing speeds. This is the first reason why POE::Component::IRC seems slow.

    IRC servers detect floods by watching their buffer sizes. The backlog between what a client sends and what a channel sees increases as a client continues to flood. The IRC server disconnects clients with backlogs beyond a configurable limit. This is known as "flooding yourself off" a server.

    POE::Component::IRC performs its own rate limiting. It uses the hybrid same rate limiting algorithm as the hybrid IRC server to send data as fast as possible without overflowing the IRC server's buffers. This prevents bots written with POE::Component::IRC from flooding themselves off, even if the developer does something stupid (like sending 100 lines of text all at once). This is the second reason why POE::Component::IRC seems slow.

    POE::Component::IRC's flood protection can be disabled. When connecting to an IRC server, include a Flood => 1 parameter.

    $kernel->post( bot => connect => { Nick => "my_nick", Server => "irc.wherever.com", Port => 6667, Username => "my_user_name", Ircname => "my_irc_name", LocalAddr => "my.v.host", Flood => 1, # Allow flooding. } );

    This is mostly useful when you manage your own IRC server and can disable its flood protection.

    The third reason for POE::Component::IRC's seemingly slow output has to do with the way its rate limiting works. The component must buffer its own output to perform rate limiting. For fairness, messages being transmitted to a server are kept more or less in the same order they've been sent.

    For example, a 100-line help message is kept together in the outgoing message buffer. It will be transmitted at human typing speeds to prevent the bot from flooding itself off the IRC server.

    Meanwhile, any responses to other users will be put into the buffer behind that 100-line message. The bot will seem unresponsive, even though it has received and handled user requests. The other responses will be sent in their turn, after the 100-line message.

    A workaround has been suggested on POE's mailing list. Rather than have all responses go through a single queue, split them into one queue per destination. If POE::Component::IRC services each destination in turn, then short responses won't need to wait for longer ones to finish.

    This workaround does have its drawbacks:

    It only works in flood-protected mode. When Flood => 1, there is no client buffer. All the flood protection will happen on the server side, which may or may not be under your control.

    The lag for each user increases as the number of simultaneous responses increases. If there are 2 simultaneous responses, each is serviced in 2x the usual time. If there are 10, then each response takes 10x as much time to be sent. This is because the overall rate limiting must be maintained to avoid the bot flooding itself off.

    The workaround has not been implemented as of this writing.