<br>We've been using Perlbal at IMVU since January of this year.&nbsp; IMVU is a community service built around a 3D avatar chat client.&nbsp; We've been made some extensions to Perlbal that others might find useful.<br><br>Our chat protocol is XML over HTTP with the client polling for messages.&nbsp; We store the message queues for all the chats in memcached (the data is inherently ephemeral and the protocol can recover if messages get dropped due to a restart).&nbsp; About a week ago we switched to an implementation where Perlbal handles the polling requests internally using a plugin.&nbsp; Our plugin recognizes inbound polling requests, makes the calls to memcached to determine if there are any messages for the client, and if there are messages sends the response. &nbsp; If there are no messages, the plugin puts the request into a buffer and retries again one second later.&nbsp; 
<br><br>We've been very happy with Perlbal.&nbsp; The new code is much more efficient because there is no HTTP traffic to the client unless there are messages that need to go out, because Perlbal can keep many more connections alive than Apache, and because Perlbal can share state across connections.&nbsp; Since Perlbal was written in Perl (as opposed to C) and has a plugin architecture I was able to write and ship this extension in under a week. &nbsp;&nbsp; 
<br><br>I made one change to the Perlbal 1.41 distribution to add a hook after the POST data has been received from the client.&nbsp; I've appended the patch to the end of the email if anyone is interested.<br><br>There is a comment in the source for Danga socket that seemed inaccurate.&nbsp; The Danga socket source says:
<br><br><span style="font-family: courier new,monospace;">&nbsp; &nbsp; # watch for <span style="font-family: courier new,monospace;">writability.&nbsp; not needed with -&gt;write().&nbsp; write()</span></span><br style="font-family: courier new,monospace;">


<span style="font-family: courier new,monospace;">&nbsp;&nbsp;&nbsp; # will automatically turn on watch_write when you wrote too much</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">
&nbsp; &nbsp; # and turn it off when done</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">&nbsp;&nbsp;&nbsp; $my_sock-&gt;watch_write($bool);</span><br><br>The behavior I observed was that Danga::Socket never actually called watch_write(0) to turn off polling for writes and that CPU usage went to 100%.&nbsp; My work around was to copy the code used elsewhere in Perlbal to turn off write notifications by passing a coderef to a subroutine as the last thing to write.
<br><br>I also was tripped up by the management code in <a href="http://Perlbal.pm" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">Perlbal.pm</a> that assumes all instances of Danga::Socket are also instances of Perlbal::Socket.&nbsp;&nbsp; I created an asynchronous memcached client that initially inherited from Danga::Socket, but was forced to inherit from Perlbal::Socket to avoid failures in the management code.
<br><br>In addition to chat, the approach we used here might be interesting on any site using AJAX techniques to keep data on web pages up to date.&nbsp; Although our plugin is pretty specific to our situation, we would be glad to share with anyone interested.&nbsp; I've got a few more things I want to do to the asynchronous memcached client, but I expect to post that to the memcached mailing list in a week or so.
<br><br>Chris<br><br>-- <br><a href="http://avatars.imvu.com/chris" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">http://avatars.imvu.com/chris</a><br><br><br><br><br>Index: C:/imvu/operations/software/Perlbal-
1.41/lib/Perlbal/ClientProxy.pm<br>===================================================================<br>--- C:/imvu/operations/software/Perlbal-1.41/lib/Perlbal/ClientProxy.pm&nbsp;&nbsp;&nbsp; (revision 8072)<br>+++ C:/imvu/operations/software/Perlbal-
1.41/lib/Perlbal/ClientProxy.pm&nbsp;&nbsp;&nbsp; (revision 8150)<br>@@ -684,6 +684,10 @@<br>&nbsp;&nbsp;&nbsp;&nbsp; # over the buffer-to-memory size, see if we should start spooling to disk.<br>&nbsp;&nbsp;&nbsp;&nbsp; return if $self-&gt;{service}-&gt;{buffer_uploads} &amp;&amp; $self-&gt;decide_to_buffer_to_disk;
<br>&nbsp;<br>+&nbsp;&nbsp;&nbsp; # give plugins a chance to act on the request before we request a backend<br>+&nbsp;&nbsp;&nbsp; my $svc = $self-&gt;{service};<br>+&nbsp;&nbsp;&nbsp; return if $svc-&gt;run_hook('proxy_read_request', $self);<br>+<br>&nbsp;&nbsp;&nbsp;&nbsp; # if we fall through to here, we need to ensure that a backend is on the
<br>&nbsp;&nbsp;&nbsp;&nbsp; # way, because no specialized handling took over above<br>&nbsp;&nbsp;&nbsp;&nbsp; print &quot;&nbsp; finally requesting a backend\n&quot; if Perlbal::DEBUG &gt;= 3;<br><br><br>