Badger::Storage

NAME

Top Close Open

Badger::Storage - base class module for persistent storage

SYNOPSIS

Top Close Open
# Storage() is a shortcut to Badger::Storages->storage() which
# loads and instantiates instances of Badger::Storage subclasses
use Badger::Storages 'Storage';

# the following are all equivalent
my $storage = Storage('file:/path/to/directory');
my $storage = Storage( file => '/path/to/directory' );
my $storage = Storage({
    type => file,
    path => '/path/to/directory',
});

# specifying storage option (codec), the following are equivalent
my $storage = Storage(
    file => {
        path  => '/path/to/directory',
        codec => 'json',
    }
);
my $storage = Storage({
    type  => file,
    path  => '/path/to/directory',
    codec => 'json',
});

# using the storage object
my $data = { 
    # ...some perl data... 
};

# create() stores the data under a new identifier
my $id = $storage->create($data);

# store() stores data under an identifier
$storage->store($id, $data);

# fetch() fetches data under an identifier
my $data = $storage->fetch($id)
    || die $storage->reason;        # not found

# delete() delete the data under an identifier
$storage->delete($id);

DESCRIPTION

Top Close Open

This module implements an abstract interface for storing persistent data. It is not intended to be used by itself, but as a base class for other modules that implement the specifics of storing data in a filesystem, database, or some other environment.

The Badger::Storage::Filesystem module is a subclass for storing data in files on your local filesystem. Other storage modules are expected to follow in the fullness of time.

THE BIG FOUR METHODS

Top Close Open

The following four methods are the canonical methods for creating, fetching, storing and deleting storage records. Subclasses should re-define these methods.

create($data)

Top Close Open

The create() method first calls the the generate_id() method to generate a new identifier for the data. It then call the store() method, passing the identifier along with the data passed to it as an argument. It returns the newly created identifier.

my $id = $storage->create($data);

It returns the newly created identifier for the data record. Errors are thrown as exceptions. You can use the try() method inherited from Badger::Base if you want to catch any exceptions.

my $id = $storage->try->create($data)
    || warn $storage->error;

This is equivalent to:

my $id = eval { $storage->create($data) }
    || warn $storage->error;

fetch($id)

Top Close Open

This method is used to fetch data. The single argument is a unique identifier for the data, such as that returned by a previous call to the create() method, or passed as the first argument in a call to the store() method.

my $data = $storage->fetch($id);

If the data cannot be found then the method returns undef by calling its own decline() method (inherited from Badger::Base). You can call the error() method to view the message generated.

my $data = $storage->fetch('foo')
    || print $storage->error;       # e.g. File not found: foo

It is important to understand the difference between the method declining to return a value and an error. If the data for the requested identifier cannot be found then the method returns undef by calling its own decline() method. This is considered part of its normal operation. It is not an error to ask for something that doesn't exists. The method will politely turn you away.

On the other hand, if the method is prevented from looking for the data and either returning it or declining, for whatever reason, then an exceptions will be thrown. It could be that the the file contents got mangled, the database is offline, the network is down, or maybe you forgot to pass an identifier as a parameter. These are all error conditions that are considered outside of normal operation.

If your application dictates that a missing resource is an error then you should add the appropriate code to any call to fetch(). For example, if your application is loading a configuration file then you probably want to know right away if the configuration file is missing, misnamed, or otherwise unloaded for whatever reason.

my $config = $storage->fetch( $config_file_name )
    || die $storage->error;

store($id,$data)

Top Close Open

This method is used to store data. The first argument is a unique identifier for the data. The second argument should be a reference to the data to be stored (e.g. a hash or list reference).

$storage->store($id, $data);

It returns a true value which you can test if you want the warm glow of satisfaction that it performed its job as expected.

if ($storage->store($id, $data)) {
    # phew!
}

However, all errors are thrown as exceptions so there's no need to test the return value at all. If the method returns, then it succeeded. You can use eval { } if you want to trap errors, or the try() method, as shown in the documentation for create().

delete($id)

Top Close Open

Permanently deletes the data associated with the identifier passed as an argument.

$storage->delete($id);

Returns a true value on success. If the data does not exist then it returns undef. All errors are thrown as exceptions. As with fetch(), deleting a resource that does not exists is not considered an error. The method will decline() gracefully.

ALTERNATE METHODS

Top Close Open

A number of additional methods are defined as wrappers around the four core methods described above. These exist to provide a compatible interface with other modules (e.g. Cache::Cache), protocols (e.g. REST, CRUD) or simply for the sake of programmer convenience.

Core methods       create(), fetch(), store(), delete()
Cache::Cache       insert(), get(), set(), remove()
CRUD methods       create(), retrieve(), update(), delete()
REST methods       post(), get(), put(), delete()
File/IO methods    create(), read(), write(), remove()

insert()

Top Close Open

A wrapper of convenience around the create() method. This is the method that Cache::Cache modules are expecting to use, among others.

post()

Top Close Open

A wrapper of convenience around the create() method for compatibility with the REST (Representational State Transfer) architectural style.

get()

Top Close Open

A wrapper of convenience around the fetch() method for compatibility with Cache::Cache and the REST (Representational State Transfer) architectural style.

retrieve()

Top Close Open

A wrapper of convenience around the fetch() method for compatibility with the CRUD (Create/Retrieve/Update/Delete) architectural style.

read()

Top Close Open

A wrapper of convenience around the fetch() method for people who think that the 'R' in 'CRUD' stands for 'Read', or people who feel at home talking to filesystems.

set()

Top Close Open

A wrapper of convenience around the store() method for compatibility with Cache::Cache and to keep everyone happy in the Department of Stating the Bleedin' Obvious.

put()

Top Close Open

A wrapper of convenience around the store() method for compatibility with the REST (Representational State Transfer) architectural style.

update()

Top Close Open

A wrapper of convenience around the store() method for compatibility with the CRUD (Create/Retrieve/Update/Delete) architectural style.

write()

Top Close Open

A wrapper of convenience around the store() method to go with read() for the filesystem geeks.

remove()

Top Close Open

A wrapper of convenience around the delete() method. This is the method that Cache::Cache modules are expecting to use, among others.

INTERNAL METHODS

Top Close Open

init_storage($config)

Top Close Open

This method should be redefined by subclasses to perform any storage-specific initialisation.

generate_id(@args)

Top Close Open

This method is called by the create() method to generate a new identifier for the data record. All of the arguments passed to the create() method are forwarded to the generate_id() method.

In the base class this method generates a random MD5 hex string using the random_name() function imported from Badger::Utils. The length of the identifier default to 32 characters. This can be changed using the id_length configuration parameter.

my $storage = Badger::Storage::Filesystem(
    path      => '/path/to/dir',
    id_length => 64,
);

Subclasses can redefine the method to do something different.

AUTHOR

Top Close Open

Andy Wardley http://wardley.org

COPYRIGHT

Top Close Open

Copyright (C) 2007-2009 Andy Wardley. All Rights Reserved.

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

Fork Me on Github