AmberDB
view release on metacpan or search on metacpan
lib/AmberDB/Cache.pm view on Meta::CPAN
my $tbl_dir = $self->cache_tbl_dir() or return;
my $db_ext = $self->{db_ext} // 'db';
my $cache_db = "$tbl_dir/${tableid}.${db_ext}";
if ( !-e $cache_db || !$self->_check_cache_ttl( $tableid, $cache_db ) ) {
$self->cache_preload($tableid);
}
return $cache_db;
}
# my @data = $adb->cache_read($tableid, $key, [$type]);
# Reads entry from cache/$tableid.db (for numeric/records) or cache/$tableid.inx (for meta/keys).
# ------------------------------------------------
sub cache_read {
my ( $self, $tableid, $key, $type ) = @_;
$tableid or return;
defined $key && $key ne '' or return;
my $table_info = $self->table_info($tableid);
return unless $table_info && $table_info->{use_cache};
if ( $table_info->{use_cache} == 2 ) {
$self->cache_ensure($tableid);
}
my $cache_file = $self->cache_file_for( $tableid, $key, $type ) or return;
return unless -e $cache_file;
return unless $self->_check_cache_ttl( $tableid, $cache_file );
my $res = $self->recs_get( $cache_file, $key );
return unless $res && defined $res->{$key} && $res->{$key} ne '';
return $self->db_decode( $res->{$key} );
}
# my $ok = $adb->cache_write($tableid, $key, @records);
# Writes entry to cache/$tableid.db (for numeric/records) or cache/$tableid.inx (for meta/keys).
# ------------------------------------------------
sub cache_write {
my ( $self, $tableid, $key, @records ) = @_;
$tableid or return;
defined $key && $key ne '' or return;
return unless @records;
my $table_info = $self->table_info($tableid);
return unless $table_info && $table_info->{use_cache};
my $cache_file = $self->cache_file_for( $tableid, $key );
my $encoded_val = $self->db_encode(@records);
$self->recs_put( $cache_file, [ $key, $encoded_val ] );
return 1;
}
# my $ok = $adb->cache_delete($tableid, [$key], [$type]);
# Invalidates entry from cache/$tableid.db / .inx or removes entire table cache files.
# ------------------------------------------------
sub cache_delete {
my ( $self, $tableid, $key, $type ) = @_;
$tableid or return;
my $table_info = $self->table_info($tableid);
return unless $table_info && $table_info->{use_cache};
if ( defined $key && $key ne '' ) {
my $cache_file = $self->cache_file_for( $tableid, $key, $type );
if ( $cache_file && -e $cache_file ) {
$self->recs_del( $cache_file, $key );
}
}
else {
my $tbl_dir = $self->cache_tbl_dir() or return;
my $db_ext = $self->{db_ext} // 'db';
my $clean_tid = $self->can('sanitize_table') ? $self->sanitize_table($tableid) : $tableid;
my $db_file = "$tbl_dir/${clean_tid}.${db_ext}";
my $inx_file = "$tbl_dir/${clean_tid}.inx";
foreach my $file ( $db_file, $inx_file ) {
if ( -e $file ) {
$self->table_close($file);
unlink $file;
}
}
}
return 1;
}
# my $ok = $adb->cache_preload($tableid);
# Preloads all records and metadata from tables/ into cache/ for use_cache => 2 (Hard Cache)
# Uses atomic temporary writes (.tmp.$$) to prevent multi-process race conditions.
# ------------------------------------------------
sub cache_preload {
my ( $self, $tableid ) = @_;
$tableid or return;
$tableid = $self->can('sanitize_table') ? $self->sanitize_table($tableid) : $tableid;
return unless defined $tableid && length $tableid;
my $table_info = $self->table_info($tableid);
return unless $table_info && $table_info->{use_cache} && $table_info->{use_cache} == 2;
my $tbl_dir = $self->cache_tbl_dir() or return;
unless ( -d $tbl_dir ) {
warn "[AMBERDB_CACHE] Cache tables directory does not exist: $tbl_dir\n";
return;
}
my $db_ext = $self->{db_ext} // 'db';
my $cache_db = "$tbl_dir/${tableid}.${db_ext}";
my $cache_inx = "$tbl_dir/${tableid}.inx";
my $table_path = $self->table_path($tableid);
my $src_db = "$table_path.${db_ext}";
my $src_inx = "$table_path.inx";
lib/AmberDB/Cache.pm view on Meta::CPAN
AmberDB::Cache - Native .db and .inx RAM-Disk (tmpfs) unified cache and persistent staging buffer engine
=head1 SYNOPSIS
# 1. Soft Cache (use_cache => 1):
# Custom caching for key-value datasets:
$adb->cache_write("catalog_product", "featured_items", @product_records);
my @records = $adb->cache_read("catalog_product", "featured_items");
$adb->cache_delete("catalog_product", "featured_items");
# 2. Hard Cache (use_cache => 2):
# Preloads entire database and index files into tmpfs RAM-disk:
$adb->cache_preload("catalog_category");
# 3. Persistent Disk Buffer Staging (stored in dbstore/buffer/):
$adb->buffer_write("export_job", @large_dataset_chunks);
my @staged_data = $adb->buffer_read("export_job");
$adb->buffer_delete("export_job");
# 4. RAM-Disk diagnostics and setup info:
my $info = $adb->cache_setup();
=head1 DESCRIPTION
C<AmberDB::Cache> provides two complementary high-performance caching subsystems:
=over 4
=item 1. B<Unified RAM-Disk (tmpfs / ImDisk) Cache:> Mirrors AmberDB's native C<.db> (record data) and C<.inx> (primary indexes) files in ultra-fast memory storage under C<dbstore/cache/>. Supports TTL expiration (C<cache_ttl>) and atomic background ...
=item 2. B<Persistent Disk Buffer Staging:> Manages temporary serialized staging tables under C<dbstore/buffer/> for multi-stage ETL pipelines, large dataset transformations, or batch background workers.
=back
B<Inheritance Note:> C<AmberDB> inherits from C<AmberDB::Cache> via C<use parent>. All cache and buffer methods documented below can be invoked directly on any C<$adb> instance.
=head1 METHODS
=head2 cache_setup()
Inspects operating system environment (Linux C<tmpfs> or Windows C<ImDisk>), returns diagnostic metadata, mount status, configured cache size, and paths to RAM-disk helper setup scripts (bash, powershell, perl).
my $diag = $adb->cache_setup();
# Returns: { is_mounted => 1, mount_desc => "tmpfs mounted on ...", cache_size => "512M", ... }
=head2 cache_read($tableid, $key, [$type])
Reads and deserializes a cached record from C<cache/$tableid.db> (for record data) or C<cache/$tableid.inx> (for metadata keys). Returns the decoded list of fields. Checks TTL expiration automatically.
my @cached_row = $adb->cache_read("catalog_product", "101");
=head2 cache_write($tableid, $key, @records)
Serializes and writes record data to the RAM-disk cache file.
$adb->cache_write("catalog_product", "top_sellers", [ 101, "Prod A" ], [ 102, "Prod B" ]);
=head2 cache_delete($tableid, [$key], [$type])
Invalidates cache entries. If C<$key> is provided, removes only that specific key. If C<$key> is omitted, removes and unlinks the entire table cache files (both C<.db> and C<.inx>).
$adb->cache_delete("catalog_product", "featured_items"); # Invalidate single entry
$adb->cache_delete("catalog_product"); # Clear entire table cache
=head2 cache_preload($tableid)
Preloads all records and metadata from the persistent storage tables directory into the RAM-disk cache directory. Uses atomic temporary files (C<.tmp.$$>) and file locking to prevent race conditions during live updates.
$adb->cache_preload("catalog_category");
=head2 cache_ensure($tableid)
Ensures that the RAM-disk cache for a table configured with C<use_cache =E<gt> 2> is populated and valid. Automatically triggers C<cache_preload> if the cache file is absent or expired.
my $cache_path = $adb->cache_ensure("catalog_category");
=head2 buffer_write($tableid, @records)
Writes structured records to a persistent disk buffer file located at C<dbstore/buffer/${tableid}.tmp>. Uses atomic temp-file replacement for safe multi-process writes.
$adb->buffer_write("nightly_import", @processed_rows);
=head2 buffer_read($tableid)
Reads and deserializes all staged records from the disk buffer file. Returns a list of array references.
my @rows = $adb->buffer_read("nightly_import");
=head2 buffer_delete($tableid)
Deletes and unlinks the disk buffer staging file for the given table ID.
$adb->buffer_delete("nightly_import");
=head1 AUTHOR
Maruf Cetin <marufcetin@gmail.com>
=head1 LICENSE AND COPYRIGHT
Copyright (C) 2020-2026 Maruf Cetin.
This library is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0.
=cut
( run in 0.920 second using v1.01-cache-2.11-cpan-d01c6094234 )