Re: retry a Poe::Wheel::ReadWrite->put()

Rocco Caputo <[email protected]>
Newsgroups gmane.comp.lang.perl.poe
Message-ID <[email protected]>
On Sep 29, 2008, at 13:12, Seth Daniel wrote:

> On Sat, Sep 27, 2008 at 11:45:57PM +0200, Martijn van Beers wrote:
>> On Sat, 2008-09-27 at 14:16 -0700, Seth Daniel wrote:
>>> Hi,
>>>
>>> Once the child session performs a put(), the write will fail and I
>>> receive an ErrorEvent.  I don't seem to be able to get the data  
>>> that was
>>> in the original put().  So, if I buffer the data, perform the  
>>> put(), and
>>> then receive an error I can use the wheel_id to identify the data  
>>> that
>>> failed to be written.  However, I don't get an event when the  
>>> write is
>>> successful so it doesn't seem like I can remove items from the  
>>> buffer.
>>
>> You can sign up for Wheel::ReadWrite's FlushedEvent, just like you  
>> had
>> to to receive the ErrorEvent.
>
> This seems to work well, but only if I have a new ReadWrite wheel for
> each write (my initial plan was to have a single ReadWrite wheel for  
> the
> lifetime of the session).  This way the write queue is guaranteed to
> either be flushed or have an error.  I can also use a ReadWrite wheel
> for some set amount of writes and then expire the wheel.  This saves  
> me
> from having to potentially create  millions of ReadWrite wheels over  
> the
> lifetime of the server.
>
> So buffering the data to be written and expiring ReadWrite objects  
> works
> pretty well.  My only question would be: is this really the best way  
> to
> 'retry' writes?  Seems like there should be an easier way.

I would do it differently.  I'd use a flag to busy out the connection  
until I received positive acknowledgment of transmission or an error:

1. On put(), set a "busy" flag.  Don't use the connection while it's  
busy.
2. On FlushedEvent, clear the "busy" flag, and poll for another  
transaction to be sent.
3. On ErrorEvent, push the failed transaction back into the queue, and  
recycle the connection.

By the way, you don't need one session per POE::Wheel::ReadWrite  
object.  A single session can maintain a hash of ReadWrite wheels,  
keyed on wheel ID.  The single session can then manage connections  
more directly, cleanly and with less overhead.  For example, you don't  
need to post() messages within the application before transmitting  
them on the wire.

I orignally considered introspecting into POE::Driver::SysRW's output  
buffer, but this doesn't really solve anything.  You can't reliably  
reuse the buffered data for at least two reasons: First, all type  
information is lost, so you can't be sure what it contains (but you  
can probably guess or assume, since it's your application).  Second,  
and much worse: The data may have been partly written, so it may not  
be reusable.  For example, a large HTTP upload may have been  
interrupted; retrying would fail as the headers are no longer in the  
buffer.

-- 
Rocco Caputo - [email protected]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.