added exceptions, docs, and removed disableCache

This commit is contained in:
JT Smith 2009-09-25 18:41:03 -05:00
parent a34f584780
commit af705232a8
7 changed files with 224 additions and 107 deletions

View file

@ -265,10 +265,8 @@ sub getFirstChild {
my $lineage = $assetLineage->{firstChild}{$self->getId};
unless ($lineage) {
($lineage) = $self->session->db->quickArray("select min(asset.lineage) from asset,assetData where asset.parentId=? and asset.assetId=assetData.assetId and asset.state='published'",[$self->getId]);
unless ($self->session->config->get("disableCache")) {
$assetLineage->{firstChild}{$self->getId} = $lineage;
$self->session->stow->set("assetLineage", $assetLineage);
}
$assetLineage->{firstChild}{$self->getId} = $lineage;
$self->session->stow->set("assetLineage", $assetLineage);
}
$child = WebGUI::Asset->newByLineage($self->session,$lineage);
$self->cacheChild(first => $child);

View file

@ -21,7 +21,7 @@ use HTTP::Request;
use LWP::UserAgent;
use Memcached::libmemcached;
use Storable ();
use WebGUI::Error;
use WebGUI::Exception;
use Params::Validate qw(:all);
Params::Validate::validation_options( on_fail => sub { WebGUI::Error::InvalidParam->throw( error => shift ) } );
@ -71,14 +71,29 @@ The key to delete.
=cut
sub delete {
validate(@_,
{ name => {
type => SCALAR
}
});
my ($self, $name) = @_;
Memcached::libmemcached::memcached_delete($self->getMemcached, $self->parseKey($name));
my ($self, $name) = validate_pos(@_,
1,
{ type => SCALAR | ARRAYREF },
);
my $memcached = $self->getMemcached;
Memcached::libmemcached::memcached_delete($memcached, $self->parseKey($name));
if ($memcached->errstr eq 'SYSTEM ERROR Unknown error: 0') {
WebGUI::Error::Connection->throw(
error => "Cannot connect to memcached server."
);
}
elsif ($memcached->errstr eq 'NO SERVERS DEFINED') {
WebGUI::Error->throw(
error => "No memcached servers specified in config file."
);
}
elsif ($memcached->errstr ne 'SUCCESS' # deleted
&& $memcached->errstr ne 'PROTOCOL ERROR' # doesn't exist to delete
) {
WebGUI::Error->throw(
error => "Couldn't delete $name from cache because ".$memcached->errstr
);
}
}
#-------------------------------------------------------------------
@ -91,7 +106,23 @@ Empties the caching system.
sub flush {
my ($self) = @_;
Memcached::libmemcached::memcached_flush($self->getMemcached);
my $memcached = $self->getMemcached;
Memcached::libmemcached::memcached_flush($memcached);
if ($memcached->errstr eq 'SYSTEM ERROR Unknown error: 0') {
WebGUI::Error::Connection->throw(
error => "Cannot connect to memcached server."
);
}
elsif ($memcached->errstr eq 'NO SERVERS DEFINED') {
WebGUI::Error->throw(
error => "No memcached servers specified in config file."
);
}
elsif ($memcached->errstr ne 'SUCCESS') {
WebGUI::Error->throw(
error => "Couldn't flush cache because ".$memcached->errstr
);
}
}
#-------------------------------------------------------------------
@ -107,10 +138,35 @@ The key to retrieve.
=cut
sub get {
my ($self, $name) = @_;
my $content = Memcached::libmemcached::memcached_get($self->getMemcached, $self->parseKey($name));
my ($self, $name) = validate_pos(@_,
1,
{ type => SCALAR | ARRAYREF },
);
my $memcached = $self->getMemcached;
my $content = Memcached::libmemcached::memcached_get($memcached, $self->parseKey($name));
if ($memcached->errstr eq 'NOT FOUND' ) {
WebGUI::Error::ObjectNotFound->throw(
error => "The cache key $name has no value.",
id => $name,
);
}
elsif ($memcached->errstr eq 'NO SERVERS DEFINED') {
WebGUI::Error->throw(
error => "No memcached servers specified in config file."
);
}
elsif ($memcached->errstr eq 'SYSTEM ERROR Unknown error: 0') {
WebGUI::Error::Connection->throw(
error => "Cannot connect to memcached server."
);
}
elsif ($memcached->errstr ne 'SUCCESS') {
WebGUI::Error->throw(
error => "Couldn't get $name from cache because ".$memcached->errstr
);
}
$content = Storable::thaw($content);
return undef unless $content && ref $content;
return undef unless ref $content;
return ${$content};
}
@ -141,10 +197,25 @@ An array reference of keys to retrieve.
=cut
sub mget {
my ($self, $names) = @_;
my ($self, $names) = validate_pos(@_,
1,
{ type => ARRAYREF },
);
my @parsedNames = map { $self->parseKey($_) } @{ $names };
my %result;
$self->getMemcached->mget_into_hashref(\@parsedNames, \%result);
my $memcached = $self->getMemcached;
$memcached->mget_into_hashref(\@parsedNames, \%result);
if ($memcached->errstr eq 'SYSTEM ERROR Unknown error: 0') {
WebGUI::Error::Connection->throw(
error => "Cannot connect to memcached server."
);
}
elsif ($memcached->errstr eq 'NO SERVERS DEFINED') {
WebGUI::Error->throw(
error => "No memcached servers specified in config file."
);
}
# no other useful status messages are returned
my @values;
foreach my $name (@parsedNames) {
my $content = Storable::thaw($result{$name});
@ -156,7 +227,7 @@ sub mget {
#-------------------------------------------------------------------
=head2 new ( session, [ namespace ] )
=head2 new ( session )
The new method will return a handler for the configured caching mechanism. Defaults to WebGUI::Cache::FileCache. You must override this method when building your own cache plug-in.
@ -164,23 +235,23 @@ The new method will return a handler for the configured caching mechanism. Defa
A reference to the current session.
=head3 namespace
A subdivider to store this cache under. When building your own cache plug-in default this to the WebGUI config file.
=cut
sub new {
my ($class, $session, $namespace) = @_;
my ($class, $session) = validate_pos(@_,
1,
{ isa => 'WebGUI::Session' },
);
my ($class, $session) = @_;
my $config = $session->config;
$namespace ||= $config->getFilename;
my $memcached = Memcached::libmemcached::memcached_create();
my $namespace = $config->getFilename;
my $memcached = Memcached::libmemcached::memcached_create(); # no exception because always returns success
foreach my $server (@{$config->get('cacheServers')}) {
if (exists $server->{socket}) {
Memcached::libmemcached::memcached_server_add_unix_socket($memcached, $server->{socket});
Memcached::libmemcached::memcached_server_add_unix_socket($memcached, $server->{socket}); # no exception because always returns success
}
else {
Memcached::libmemcached::memcached_server_add($memcached, $server->{host}, $server->{port});
Memcached::libmemcached::memcached_server_add($memcached, $server->{host}, $server->{port}); # no exception because always returns success
}
}
bless {_memcached => $memcached, _namespace => $namespace, _sesssion => $session}, $class;
@ -199,16 +270,16 @@ Can either be a text key, or a composite key. If it's a composite key, it will b
=cut
sub parseKey {
my ($self, $name) = @_;
my ($self, $name) = validate_pos(@_,
1,
{ type => SCALAR | ARRAYREF },
);
# prepend namespace to the key
my @key = ($self->{_namespace});
# check for composite or simple key, make array from either
if (! $name) {
# throw exception because no key was specified
}
elsif (ref $name eq 'ARRAY') {
if (ref $name eq 'ARRAY') {
push @key, @{ $name };
}
else {
@ -253,10 +324,30 @@ A time in seconds for the cache to exist. When you override default it to 60 sec
=cut
sub set {
my ($self, $name, $value, $ttl) = @_;
$ttl ||= 60;
my ($self, $name, $value, $ttl) = validate_pos(@_,
1,
{ type => SCALAR | ARRAYREF },
{ type => SCALAR },
{ type => SCALAR | UNDEF, optional => 1, default=> 60 },
);
my $frozenValue = Storable::nfreeze(\(scalar $value)); # Storable doesn't like non-reference arguments, so we wrap it in a scalar ref.
Memcached::libmemcached::memcached_set($self->getMemcached, $self->parseKey($name), $frozenValue, $ttl);
my $memcached = $self->getMemcached;
Memcached::libmemcached::memcached_set($memcached, $self->parseKey($name), $frozenValue, $ttl);
if ($memcached->errstr eq 'SYSTEM ERROR Unknown error: 0') {
WebGUI::Error::Connection->throw(
error => "Cannot connect to memcached server."
);
}
elsif ($memcached->errstr eq 'NO SERVERS DEFINED') {
WebGUI::Error->throw(
error => "No memcached servers specified in config file."
);
}
elsif ($memcached->errstr ne 'SUCCESS') {
WebGUI::Error->throw(
error => "Couldn't set $name to cache because ".$memcached->errstr
);
}
return $value;
}
@ -282,22 +373,42 @@ The time to live for this content. This is the amount of time (in seconds) that
=cut
sub setByHttp {
my ($self, $name, $url, $ttl) = @_;
my ($self, $name, $url, $ttl) = validate_pos(@_,
1,
{ type => SCALAR | ARRAYREF },
{ type => SCALAR },
{ type => SCALAR, optional => 1 },
);
my $userAgent = new LWP::UserAgent;
$userAgent->env_proxy;
$userAgent->agent("WebGUI/".$WebGUI::VERSION);
$userAgent->timeout(30);
my $request = HTTP::Request->new(GET => $url);
my $response = $userAgent->request($request);
if ($response->is_error) {
$self->session->log->error($url." could not be retrieved.");
# show throw exception
return undef;
WebGUI::Error::Connection->throw(
error => "Couldn't fetch $url because ".$response->message,
resource => $url,
);
}
return $self->set($name, $response->decoded_content, $ttl);
}
=head1 EXCEPTIONS
This class throws a huge number of exceptions about everything you can imagine, and many things you can't. However, because cache should be treated as optional, none of them matter except for testing, debugging, or in very specific use cases. Therefore the best practice is to simply call each method with an eval wrapper, and then not even bother testing for specific exceptions like this:
my $value = eval { $session->cache->get($key) };
unless (defined $value) {
$value = $db->fetchValueFromTheDatabase;
}
=cut
1;

View file

@ -51,8 +51,6 @@ These exception classes are defined in this class:
=cut
use Exception::Class (
#-------------------------------------------------------------------
=head2 WebGUI::Error
@ -85,11 +83,6 @@ A read only exception method that returns the package name where the exception w
=cut
'WebGUI::Error' => {
description => "A general error occured.",
},
#-------------------------------------------------------------------
=head2 WebGUI::Error::OverrideMe
@ -98,12 +91,6 @@ An interface was not overriden as expected.
=cut
'WebGUI::Error::OverrideMe' => {
isa => 'WebGUI::Error',
description => 'This method should be overridden by subclasses.',
},
#-------------------------------------------------------------------
=head2 WebGUI::Error::MethodNotFound
@ -116,13 +103,6 @@ The method called.
=cut
'WebGUI::Error::MethodNotFound' => {
isa => 'WebGUI::Error',
description => q|Called a method that doesn't exist.|,
fields => 'method'
},
#-------------------------------------------------------------------
=head2 WebGUI::Error::InvalidObject
@ -139,13 +119,6 @@ The object type we got.
=cut
'WebGUI::Error::InvalidObject' => {
isa => 'WebGUI::Error::InvalidParam',
description => "Expected to get a reference to an object type that wasn't gotten.",
fields => ["expected","got"],
},
#-------------------------------------------------------------------
=head2 WebGUI::Error::InvalidParam
@ -158,13 +131,6 @@ Used to return the bad parameter, if present.
=cut
'WebGUI::Error::InvalidParam' => {
isa => 'WebGUI::Error',
description => "Expected to get a param we didn't get.",
fields => ["param"],
},
#-------------------------------------------------------------------
=head2 WebGUI::Error::ObjectNotFound
@ -177,13 +143,6 @@ The id of the object to be retrieved.
=cut
'WebGUI::Error::ObjectNotFound' => {
isa => 'WebGUI::Error',
description => "The object you were trying to retrieve does not exist.",
fields => ["id"],
},
#-------------------------------------------------------------------
=head2 WebGUI::Error::ObjectNotFound::Template
@ -196,13 +155,6 @@ The id of the object to be retrieved.
=cut
'WebGUI::Error::ObjectNotFound::Template' => {
isa => 'WebGUI::Error',
description => "The template an asset was trying to retrieve does not exist.",
fields => [qw/templateId assetId/],
},
#-------------------------------------------------------------------
=head2 WebGUI::Error::InvalidFile
@ -219,13 +171,6 @@ The line the error was found on.
=cut
'WebGUI::Error::InvalidFile' => {
isa => 'WebGUI::Error',
description => "The file you have provided has errors.",
fields => [qw{ brokenFile brokenLine }],
},
#-------------------------------------------------------------------
=head2 WebGUI::Error::Template
@ -234,12 +179,6 @@ Used when a template has parsing errors. ISA WebGUI::Error.
=cut
'WebGUI::Error::Template' => {
isa => 'WebGUI::Error',
description => "A template has errors that prevent it from being processed.",
},
#-------------------------------------------------------------------
=head2 WebGUI::Error::Connection
@ -252,6 +191,67 @@ The name or configuration or URL of the resource trying to be accessed.
=cut
use Exception::Class (
'WebGUI::Error' => {
description => "A general error occured.",
},
'WebGUI::Error::OverrideMe' => {
isa => 'WebGUI::Error',
description => 'This method should be overridden by subclasses.',
},
'WebGUI::Error::MethodNotFound' => {
isa => 'WebGUI::Error',
description => q|Called a method that doesn't exist.|,
fields => 'method'
},
'WebGUI::Error::InvalidObject' => {
isa => 'WebGUI::Error::InvalidParam',
description => "Expected to get a reference to an object type that wasn't gotten.",
fields => ["expected","got"],
},
'WebGUI::Error::InvalidParam' => {
isa => 'WebGUI::Error',
description => "Expected to get a param we didn't get.",
fields => ["param"],
},
'WebGUI::Error::ObjectNotFound' => {
isa => 'WebGUI::Error',
description => "The object you were trying to retrieve does not exist.",
fields => ["id"],
},
'WebGUI::Error::ObjectNotFound::Template' => {
isa => 'WebGUI::Error',
description => "The template an asset was trying to retrieve does not exist.",
fields => [qw/templateId assetId/],
},
'WebGUI::Error::InvalidFile' => {
isa => 'WebGUI::Error',
description => "The file you have provided has errors.",
fields => [qw{ brokenFile brokenLine }],
},
'WebGUI::Error::Template' => {
isa => 'WebGUI::Error',
description => "A template has errors that prevent it from being processed.",
},
'WebGUI::Error::Connection' => {
isa => 'WebGUI::Error',
description => "Couldn't establish a connection.",

View file

@ -467,7 +467,6 @@ sub open {
$sessionId = $self->id->generate unless $self->id->valid($sessionId);
my $noFuss = shift;
$self->{_var} = WebGUI::Session::Var->new($self,$sessionId, $noFuss);
$self->errorHandler->warn("You've disabled cache in your config file and that can cause many problems on a production site.") if ($config->get("disableCache"));
return $self;
}

View file

@ -118,7 +118,6 @@ sub get {
my $self = shift;
my $var = shift;
my $opt = shift || {};
return undef if $self->session->config->get("disableCache");
my $value = $self->{_data}{$var};
return undef unless defined $value;
my $ref = ref $value;
@ -190,8 +189,6 @@ The value of the stow variable. Any scalar or reference.
sub set {
my $self = shift;
$self->session->errorHandler->debug('Stow->set() is being called but cache has been disabled')
if $self->session->config->get("disableCache");
my $name = shift;
my $value = shift;
return undef unless ($name);