NAME

PAGI::Runner - PAGI application loader and server runner

SYNOPSIS

# Command line usage via pagi-server
pagi-server PAGI::App::Directory root=/var/www
pagi-server ./app.pl -p 8080
pagi-server                        # serves current directory

# Programmatic usage
use PAGI::Runner;

my $runner = PAGI::Runner->new;
$runner->parse_options(@ARGV);
$runner->run;

# Or all-in-one
PAGI::Runner->new->run(@ARGV);

# For testing
my $runner = PAGI::Runner->new(port => 0, quiet => 1);
$runner->load_app('PAGI::App::Directory', root => '.');
my $server = $runner->prepare_server;

DESCRIPTION

PAGI::Runner is a loader and runner for PAGI applications, similar to Plack::Runner for PSGI. It handles CLI argument parsing, app loading (from files or modules), and server orchestration.

APP LOADING

The runner supports three ways to specify an application:

Module Name

If the app specifier contains ::, it's treated as a module name:

pagi-server PAGI::App::Directory root=/var/www show_hidden=1

The module is loaded, instantiated with the provided key=value arguments, and to_app is called to get the PAGI app coderef.

File Path

If the app specifier contains / or ends with .pl or .psgi, it's treated as a file path:

pagi-server ./app.pl
pagi-server /path/to/myapp.psgi

The file is loaded via do and must return a coderef.

Default

If no app is specified, defaults to serving the current directory:

pagi-server                        # same as: PAGI::App::Directory root=.

CONSTRUCTOR ARGUMENTS

Arguments after the app specifier are parsed as key=value pairs and passed to the module constructor:

pagi-server PAGI::App::Directory root=/var/www show_hidden=1

Becomes:

PAGI::App::Directory->new(root => '/var/www', show_hidden => 1)->to_app

METHODS

new

my $runner = PAGI::Runner->new(%options);

Creates a new runner instance. Options:

host => $host

Bind address. Default: '127.0.0.1' (localhost only)

The default is secure - it only accepts local connections. For headless servers or deployments requiring remote access, use '0.0.0.0' to bind to all IPv4 interfaces. See PAGI::Server for detailed documentation

port => $port

Bind port. Default: 5000

workers => $num

Number of worker processes. Default: 1

listener_backlog => $num

Listener queue size. No default, if left blank then the server sets a default that is rational for itself.

timeout => $num

Seconds before we timeout the request. If left blank will default to whatever is default for the server.

quiet => $bool

Suppress startup messages. Default: 0

loop => $loop_type

Event loop backend (EV, Epoll, UV, Poll). Default: auto-detect

ssl_cert => $path

Path to SSL certificate file.

ssl_key => $path

Path to SSL private key file.

access_log => $path

Path to access log file. Default: STDERR

no_access_log => $bool

Disable access logging entirely. Eliminates per-request I/O overhead, which can improve throughput by 5-15% depending on workload. Default: 0

log_level => $level

Controls the verbosity of server log messages. Valid levels from least to most verbose: 'error', 'warn', 'info', 'debug'. Default: 'info'

reuseport => $bool

Enable SO_REUSEPORT mode for multi-worker servers. Each worker creates its own listening socket, allowing the kernel to distribute connections. Reduces accept() contention and can improve p99 latency under high concurrency. Default: 0

max_receive_queue => $count

Maximum WebSocket receive queue size (message count). When exceeded, connection is closed with code 1008. DoS protection for slow consumers. Default: 1000

max_ws_frame_size => $bytes

Maximum WebSocket frame payload size in bytes. When a client sends a frame larger than this limit, the connection is closed. Default: 65536 (64KB)

max_requests => $count

Maximum requests per worker before restart. Default: 0 (unlimited)

max_connections => $count

Maximum concurrent connections per worker. Default: 0 (auto-detect). See "max_connections" in PAGI::Server for details.

max_body_size => $bytes

Maximum request body size in bytes. Default: 10,000,000 (10MB). Set to 0 for unlimited. See "max_body_size" in PAGI::Server for details.

libs => \@paths

Additional library paths to add to @INC before loading the app. Similar to perl -I. Default: []

daemonize => $bool

Fork to background and detach from terminal. Default: 0

pid_file => $path

Write process ID to this file. Useful for init scripts and process managers.

user => $username

Drop privileges to this user after binding to port. Requires starting as root.

group => $groupname

Drop privileges to this group after binding to port. Requires starting as root.

parse_options

my @remaining = $runner->parse_options(@args);

Parses CLI options from the argument list. Known options are extracted and stored in the runner object. Returns remaining arguments (app specifier and constructor args).

Supported options:

-I, --lib       Add path to @INC (repeatable, like perl -I)
-a, --app       App file path (legacy, for backward compatibility)
-h, --host      Bind address
-p, --port      Bind port
-w, --workers   Number of workers
-l, --loop      Event loop backend
--ssl-cert      SSL certificate path
--ssl-key       SSL key path
--access-log    Access log path
--no-access-log Disable access logging (for max performance)
--log-level     Log verbosity: debug, info, warn, error (default: info)
--reuseport     Enable SO_REUSEPORT for multi-worker scaling
--max-requests  Requests per worker before restart (default: unlimited)
-q, --quiet     Suppress output
--help          Show help

load_app

my $app = $runner->load_app();
my $app = $runner->load_app($app_spec);
my $app = $runner->load_app($app_spec, %constructor_args);

Loads a PAGI application. If no app_spec is provided and one was set via parse_options, uses that. If still no app_spec, defaults to PAGI::App::Directory with root set to current directory.

Returns the loaded app coderef and stores it in the runner.

prepare_server

my $server = $runner->prepare_server;

Creates and configures a PAGI::Server instance based on the runner's settings. The app must be loaded first via load_app.

Returns the server instance (not yet started).

run

$runner->run(@args);

Convenience method that parses options, loads the app, creates the server, and runs the event loop. This is the main entry point for CLI usage.

SEE ALSO

PAGI::Server, Plack::Runner

AUTHOR

John Napiorkowski <jjnapiork@cpan.org>

LICENSE

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.