From Code to Community: Sponsoring The Perl and Raku Conference 2025 Learn more

=head1 NAME
UniEvent::Streamer::Output - base class for custom consumers for streamer
=head1 SYNOPSYS
package MyOutput;
use parent 'UniEvent::Streamer::Output';
use 5.012;
sub new {
my ($class, ...) = @_;
my $self = $class->SUPER::new();
...
return $self;
}
sub start { ... }
sub stop { ... }
sub write { ... }
sub write_queue_size { return length(shift->{buffer}) }
...
my $output = MyOutput->new(...);
my $streamer = UE::Streamer->new($input, $output);
...
=head1 DESCRIPTION
This is base class for custom output streams, meant to be assigned with L<UniEvent::Streamer>.
It is assumed, that you will send data, given by L<UniEvent::Streamer>, to some external destination will generate data and eof event, and
C<Streamer> will use output object as follows: it will call C<start()> once and then will periodically call C<write()>. You are expected to write that data somewhere
and call C<handle_write()> for each corresponding C<write()>. In case of any error you must call C<handle_write()> with error.
You must implement any kind of dynamic-size buffer (if it's not already implemented by lower level objects that you use to write data) and return summary size
of all not yet completed writes from method C<write_queue_size()> which will be called by C<Streamer> periodically.
C<Streamer> will call C<stop()> method once when the process finishes successfully or with error.
=head1 METHODS
=head2 new()
Constructs new output stream.
If you override this method, you MUST proxy to parent and use return value as C<$self>.
=head2 start($loop)
This method will be invoked by C<Streamer> upon start. Executed once per object lifetime.
This method should return C<undef> if no error occured or L<XS::ErrorCode> object otherwise.
NOTE: This is a callback, do not call this method by yourself!
=head2 stop()
This method is invoked when C<Streamer> finishes. Executed once per object lifetime. No any further I/O is expected.
In this method you are expected to release all resources.
NOTE: This is a callback, do not call this method by yourself!
=head2 write($data)
This method is invoked when C<Streamer> receives chunk of data from input.
You are expected to start writing process for that chunk. When the process finishes you must call C<handle_write()>. C<Streamer> may call C<write()> many times
without waiting for you to call C<handle_write()> for previous requests.
Regardless of how calls to C<write()> were made you must call C<handle_write()> for each C<write()> when appropriate write request finishes.
This method should return C<undef> if no error occured or L<XS::ErrorCode> object otherwise. If an error occurs later, in async writing process, call
C<handle_write()> with error. Anyway, regardless of how you return error (in this method or with C<handle_write()>), after that the process will stop immediately
and C<stop()> will be called. You should not call C<handle_write()> after that.
NOTE: This is a callback, do not call this method by yourself!
=head2 write_queue_size()
This method must return size of data buffered in memory in your output object or in lower-level objects.
If this size will be greater than configured max buffer size in C<Streamer>, it will temporarily suspend input stream, giving you time to complete a part of
pending writes.
You must implement such buffer by yourself. The reason why this buffer is not implemented in C<Streamer> itself is that many objects already have output buffer.
For example L<UniEvent::Stream> handles have output buffer and C<write_queue_size()> method. In this case implementing such buffer in C<Streamer> would lead
to less efficient execution.
NOTE: This is a callback, do not call this method by yourself!
=head2 handle_write([$error])
You must call this method when one of pending write requests finishes. If any error occured during sending data, pass C<$error> argument.
C<$error> must be L<XS::ErrorCode> object. You can use UniEvent::SystemError::* constants to create errors.
$self->handle_write(UniEvent::SystemError::timed_out);
=cut