Badger::Storage
# 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);
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 following four methods are the canonical methods for creating, fetching, storing and deleting storage records. Subclasses should re-define these methods.
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;
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;
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().
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.
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()
A wrapper of convenience around the create()
method. This is the method that Cache::Cache
modules are
expecting to use, among others.
A wrapper of convenience around the create() method for compatibility with the REST (Representational State Transfer) architectural style.
A wrapper of convenience around the fetch()
method for compatibility with Cache::Cache
and the REST
(Representational State Transfer) architectural style.
A wrapper of convenience around the fetch() method for compatibility with the CRUD (Create/Retrieve/Update/Delete) architectural style.
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.
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.
A wrapper of convenience around the store() method for compatibility with the REST (Representational State Transfer) architectural style.
A wrapper of convenience around the store() method for compatibility with the CRUD (Create/Retrieve/Update/Delete) architectural style.
A wrapper of convenience around the store()
method to go with read()
for the filesystem geeks.
This method should be redefined by subclasses to perform any storage-specific initialisation.
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.
Andy Wardley http://wardley.org