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 )