NAME

Net::Blossom::Server::Backend::Filesystem - Filesystem storage for Blossom servers

SYNOPSIS

use DBI;
use Net::Blossom::Server;
use Net::Blossom::Server::Backend::Filesystem;
use Net::Blossom::Server::Backend::SQLite::MetadataStore;

my $dbh = DBI->connect('dbi:SQLite:dbname=blossom.sqlite', '', '', {
    AutoCommit => 1,
    RaiseError => 1,
    PrintError => 0,
});
my $metadata = Net::Blossom::Server::Backend::SQLite::MetadataStore->new(
    dbh => $dbh,
);
my $storage = Net::Blossom::Server::Backend::Filesystem->new(
    metadata_store => $metadata,
    root           => '/srv/blossom',
    base_url       => 'https://cdn.example.com',
);
$storage->deploy_schema;

my $server = Net::Blossom::Server->new(storage => $storage);

DESCRIPTION

This module implements Net::Blossom::Server::Storage for Net::Blossom::Server. By default, blob bytes are stored in ordinary files. Blob metadata is supplied separately through any Net::Blossom::Server::MetadataStore implementation. This distribution has no runtime dependency on a particular metadata backend; install one separately.

The default blob store stages uploads below root, synchronizes them, and publishes them under immutable, generation-specific keys. Blob paths are sharded by the first four hexadecimal characters of their SHA-256 hash. Downloads stream from open filehandles and do not load complete blobs into memory.

CONSTRUCTOR

new

my $storage = Net::Blossom::Server::Backend::Filesystem->new(%args);

Requires metadata_store and an HTTP or HTTPS base_url. Also requires either root or blob_store. With the default blob store, root is converted to an absolute path and deploy_schema creates the root, blob, and staging directories when needed. The platform and filesystem must support hard links and directory synchronization. root/blobs and root/.staging must be on the same filesystem.

generation may supply a callback that returns the safe filename suffix for each new blob. The suffix must begin with an ASCII letter or digit and contain only ASCII letters, digits, periods, underscores, or hyphens. The default is a random 128-bit hexadecimal value. Reusing a suffix for the same hash makes the upload fail instead of overwriting the existing file.

A custom blob_store may replace the default filesystem component. It must implement Net::Blossom::Server::BlobStore. It must accept get_blob($key, size => $bytes) and permit deletion after the metadata transaction commits. It cannot be combined with root or generation.

cleanup_error_handler may provide a callback for a blob cleanup failure that occurs after metadata commits. It receives the error and storage key. The default handler warns.

CONSISTENCY

This section describes the default blob store. Prepared files are durable before their storage keys enter metadata. Publishing uses a non-overwriting hard link, so concurrent writers cannot replace an existing generation. A metadata rollback after publication can leave an unreferenced file. With uploads stopped, operators may remove files whose keys are absent from the metadata store.

A process crash can leave files in root/.staging. With uploads stopped, all files in that directory may be removed.

Deletion commits metadata before unlinking the file. A cleanup failure is reported through cleanup_error_handler and may also leave an unreferenced file. Generation-specific keys prevent delayed deletion from erasing a later upload of the same hash.

The storage root must be writable only by trusted service processes. Files are created with owner-only permissions. Direct external changes can violate the backend's consistency guarantees.

SHARED FILESYSTEMS

With the default blob store, multiple processes on one host may use the same root when all processes use the same metadata store and it serializes their changes. This release is tested only on a local Linux filesystem. It makes no compatibility claim for multi-node filesystems such as NFS or CephFS.

METHODS

These methods implement Net::Blossom::Server::Storage.

BUILDARGS

Internal Class::Tiny constructor hook.

metadata_store

Returns the configured metadata store.

blob_store

Returns the configured blob store.

base_url

Returns the public base URL without a trailing slash.

cleanup_error_handler

Returns the post-commit cleanup error callback.

deploy_schema

Deploys the blob store and metadata store.

begin_upload

Returns a streaming upload writer coordinated with the metadata store.

get_blob

Returns a Net::Blossom::Server::BlobResult or undef when metadata or bytes are absent.

get_blob_range

Returns one requested byte range as a positioned, bounded file stream, or undef when metadata or bytes are absent.

head_blob

Returns a Net::Blossom::BlobDescriptor from metadata without opening bytes.

delete_blob

Deletes one owner or the complete blob. Returns true when the requested record existed.

list_blobs

Returns an array reference of descriptors in metadata-store order.