NAME
PAGI::Util::AsyncFile - Non-blocking file I/O for PAGI applications
SYNOPSIS
use PAGI::Util::AsyncFile;
# Get the loop from PAGI scope
my $loop = $scope->{pagi}{loop};
# Read entire file
my $content = await PAGI::Util::AsyncFile->read_file($loop, '/path/to/file');
# Read file in chunks (streaming)
await PAGI::Util::AsyncFile->read_file_chunked($loop, '/path/to/file', async sub {
my ($chunk) = @_;
# Process each chunk
await $send->({ type => 'http.response.body', body => $chunk, more => 1 });
}, chunk_size => 65536);
# Write file
await PAGI::Util::AsyncFile->write_file($loop, '/path/to/file', $content);
# Append to file
await PAGI::Util::AsyncFile->append_file($loop, '/path/to/file', $log_line);
DESCRIPTION
This module provides non-blocking file I/O operations for use in PAGI async applications. It uses IO::Async::Function to offload blocking file operations to worker processes, preventing the main event loop from being blocked during disk I/O.
Regular file I/O in POSIX is always blocking at the kernel level - even select()/poll()/epoll() report regular files as always "ready". This module works around this limitation by running file operations in separate worker processes, similar to how Node.js/libuv handles file I/O.
CLASS METHODS
read_file
my $content = await PAGI::Util::AsyncFile->read_file($loop, $path);
Read the entire contents of a file asynchronously. Returns a Future that resolves to the file contents.
Parameters:
$loop- IO::Async::Loop instance$path- Path to the file to read
Throws an exception if the file cannot be read.
read_file_chunked
await PAGI::Util::AsyncFile->read_file_chunked($loop, $path, async sub {
my ($chunk) = @_;
# Process chunk
}, chunk_size => 65536);
# For Range requests (partial file):
await PAGI::Util::AsyncFile->read_file_chunked($loop, $path, $callback,
offset => 1000, # Start at byte 1000
length => 5000, # Read 5000 bytes total
);
Read a file in chunks, calling a callback for each chunk. This is suitable for streaming large files without loading the entire file into memory.
Parameters:
$loop- IO::Async::Loop instance$path- Path to the file to read$callback- Async callback called with each chunk. Receives the chunk data.%opts- Options:chunk_size- Size of each chunk in bytes (default: 65536)offset- Byte offset to start reading from (default: 0)length- Maximum bytes to read; omit to read to EOF
Returns a Future that resolves to the number of bytes read when complete. The callback should return/await properly if it needs to do async operations.
write_file
await PAGI::Util::AsyncFile->write_file($loop, $path, $content);
Write content to a file asynchronously, replacing any existing content.
Parameters:
$loop- IO::Async::Loop instance$path- Path to the file to write$content- Content to write
Returns a Future that resolves to the number of bytes written.
append_file
await PAGI::Util::AsyncFile->append_file($loop, $path, $content);
Append content to a file asynchronously.
Parameters:
$loop- IO::Async::Loop instance$path- Path to the file$content- Content to append
Returns a Future that resolves to the number of bytes written.
file_size
my $size = await PAGI::Util::AsyncFile->file_size($loop, $path);
Get the size of a file asynchronously.
file_exists
my $exists = await PAGI::Util::AsyncFile->file_exists($loop, $path);
Check if a file exists asynchronously.
cleanup
PAGI::Util::AsyncFile->cleanup($loop);
Clean up the worker pool for a given loop. Call this during application shutdown to properly terminate worker processes.
CONFIGURATION
The worker pool is configured with sensible defaults:
min_workers: 1 - Minimum worker processes to keep alivemax_workers: 4 - Maximum concurrent worker processesidle_timeout: 30 - Seconds before idle workers are shut down
These settings balance responsiveness with resource usage. For applications with heavy file I/O, you may want to adjust these values by modifying the _get_function method or by configuring at the application level.
THREAD SAFETY
Each IO::Async::Loop gets its own worker pool. Worker processes are forked from the main process, so they inherit the initial state but operate independently. File operations in workers do not affect the main process state.
SEE ALSO
IO::Async::Function, IO::Async::Loop
AUTHOR
PAGI Contributors