The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Dancer::Plugin::StreamData - stream long responses instead of sending them in one piece

SYNOPSIS

    package MyWebApp;
    
    use Dancer;
    use Dancer::Plugin::StreamData;
    
    get '/some_route' => sub {

        # ...
        
        return stream_data($data_obj, \&stream_my_data);
    };
    
    sub stream_my_data {
    
        my ($data_obj, $writer) = @_;
        
        while ( $output = $data_obj->get_some_data() )
        {
            $writer->write($output);
        }
        
        $writer->close();
    }

DESCRIPTION

This plugin is useful for situations in which a Dancer application wants to return a large set of data such as the results from a database query. This is especially important where the result set might total tens or hundreds of megabytes, which would be awkward to marshall within the memory of a single server process and could lead to a long delay before the start of data delivery.

The stream_data function allows the application to stream a response one chunk at a time. For example, the data could be fetched row by row from a database server, with each row processed and then dispatched to the client via the write() method.

The reason for this plugin is that the interface defined by PSGI for data streaming is annoyingly complex and difficult to work with. By hiding the complexity, this plugin makes it simple to set up an application which streams long responses instead of marshalling them into a single response message.

This plugin can be used with any PSGI compatible web server, and includes a method by which you can check whether the server supports streaming.

USAGE

stream_data

This function takes two parameters: a data object, and a stream callback. The data object need not contain the data itself; it may be a database handle or other reference by means of which the data will be obtained. The callback can be specified either as a code reference, or as a string. In the latter case, it will be invoked as a method call on the data object.

Before calling stream_data, the HTTP status and response headers may be set by the usual mechanisms of Dancer. A call to stream_data will terminate route processing, analagous to send_file. Any further code in the route handler will be ignored. If an 'after' hook is defined in this app, it will be called as usual after route processing and may modify the response status and/or headers.

The callback is invoked after the response headers have been sent. Its job is to stream the body of the response. The callback is passed two parameters: the data object, and a 'writer' object.

The writer object, as specified by PSGI, implements two methods:

write

Sends its argument immediately to the client as the next piece of the response. You can call this method as many times as necessary to send all of the data.

close

Closes the connection to the client, terminating the response. It is important to call close at the end of processing, otherwise the client will erroneously report that the connection was closed prematurely before all of the data was sent.

server_supports_streaming

This function returns true if the server you are working with supports PSGI-style streaming, false otherwise.

Here is an example of how you might use it:

    if ( server_supports_streaming ) {
        stream_data($query, 'streamResult');
    } else {
        return $query->generateResult();
    }

AUTHOR

Michael McClennen, mmcclenn 'at' cpan.org

SEE ALSO

Dancer

PSGI

BUGS

Please report any bugs or feature requests to bug-dancer-plugin-streamdata at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Dancer-Plugin-StreamData. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

COPYRIGHT AND LICENSE

Copyright (C) 2014 by Michael McClennen

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.