PAGI-Server

 view release on metacpan or  search on metacpan

lib/PAGI/Server.pm  view on Meta::CPAN


=head1 METHODS

=head2 listen

    my $future = $server->listen;

Starts listening for connections. Returns a Future that completes when
the server is ready to accept connections.

=head2 shutdown

    my $future = $server->shutdown;

Initiates graceful shutdown. Returns a Future that completes when
shutdown is complete.

=head2 port

    my $port = $server->port;

Returns the bound port number. Useful when port => 0 is used.

=head2 socket_path

    my $path = $server->socket_path;

Returns the Unix socket path of the first Unix socket listener,
or C<undef> if no Unix socket listeners are configured.

=head2 listeners

    my $listeners = $server->listeners;

Returns an arrayref of all normalized listener specifications.
Each entry is a hashref with C<type> (C<'tcp'> or C<'unix'>)
and type-specific keys (C<host>/C<port> for TCP, C<path> for Unix).

=head2 is_running

    my $bool = $server->is_running;

Returns true if the server is accepting connections.

=head2 connection_count

    my $count = $server->connection_count;

Returns the current number of active connections.

=head2 effective_max_connections

    my $max = $server->effective_max_connections;

Returns the effective maximum connections limit. If C<max_connections>
was set explicitly, returns that value. Otherwise returns the default
of 1000.

=head1 FILE RESPONSE STREAMING

PAGI::Server supports efficient file streaming via the C<file> and C<fh>
keys in C<http.response.body> events:

    # Stream entire file
    await $send->({
        type => 'http.response.body',
        file => '/path/to/file.mp4',
        more => 0,
    });

    # Stream partial file (for Range requests)
    await $send->({
        type => 'http.response.body',
        file => '/path/to/file.mp4',
        offset => 1000,
        length => 5000,
        more => 0,
    });

    # Stream from filehandle
    open my $fh, '<:raw', $file;
    await $send->({
        type => 'http.response.body',
        fh => $fh,
        length => $size,
        more => 0,
    });
    close $fh;

The server streams files in 64KB chunks to avoid memory bloat. Small files
(under 64KB) are read synchronously for speed; larger files use async I/O
via a worker pool (L<PAGI::Server::AsyncFile>, backed by
L<IO::Async::Function>) to avoid blocking the event loop.

B<Deploy note:> a very large C<RLIMIT_NOFILE> (soft file-descriptor limit) on
the host -- around a million, the kind some container base images or systemd
units set by default -- makes each worker in this async-file-I/O pool take
over a second to start (measured: approximately 1.025s/worker at
C<nofile=1048576>). The cost is C<IO::Async::Internals::ChildManager>'s
post-fork file-descriptor-table sweep (it walks C<0 .. SC_OPEN_MAX>, the
path C<IO::Async::Function> uses to spawn a worker via C<spawn_child>); the
sweep's cost scales with the configured limit, not with how many descriptors
are actually open. This is specific to this worker pool: C<workers> worker
processes spawn via a bare C<fork> (no such sweep) and are unaffected
(measured: approximately 0.026s at the same C<nofile> setting). If large
files are served often enough that AsyncFile worker startup latency
matters, cap C<RLIMIT_NOFILE> to a realistic value for the deployment (a few
tens of thousands is enough for very high concurrency; see C<ulimit -n>
under L</System Tuning>) before starting the server.

=head2 Production Recommendations for Static Files

B<For production deployments, we strongly recommend delegating static file
serving to a reverse proxy:>

=over 4

=item 1. B<Use nginx, Apache, or a CDN>

Place a reverse proxy in front of PAGI::Server and let it handle static
files directly. This provides:



( run in 1.525 second using v1.01-cache-2.11-cpan-5c0b1e786e0 )