I have a perl script that uses the CGI::Session::Drive::memcached, but I want to be able to fallback on the default Session driver or another driver if it's available on the system...
This is how I started off using Memcache, but this doesnt necessarily solve the problem of the case when Cache::Memecached and/or CGI::Session::Driver::memcached are not available...
package MySession;
use Moose::Role;
use Moose::Util::TypeConstraints;
use namespace::autoclean;
use CGI::Session ('-ip_match');
use CGI::Session::Driver::memcached;
use Cache::Memcached::Fast;
#would be nice to create this conditionally, or use a delegate maybe
has 'memeCached' => (
is => 'rw',
isa => 'Maybe[Cache::Memcached::Fast]',
default => sub{ return Cache::Memcached::Fast->new( {'servers' => [ '10.x.x.x.:10001' ],'compress_threshold' => '100000','nowait' => 1,'utf8' => 1} ) },
);
sub buildSession{
my($this,$cgi,$sessionDir) = @_;
$cgi = $cgi || $this->getCGI();
my $sid = $this->SID();
my $mem = $this->memeCached();
my $sss;
if(!$mem){
$sss = CGI::Session->load(undef, $cgi, {Directory=>$sessionDir}) or die CGI::Session->errstr();
}else{
$sss = CGI::Session->load( "driver:memcached", $cgi, { Memcached => $mem }) or die CGI::Session->errstr();
}
...
Then this got me thinking, how do I do this -- in a general sense? or what's the best way to do this (especially using Moose)?
I had a similar situation. We use Windows domains, which I can connect to Net::LDAP. In my program, I want to be able to take the user ID jsmith
, and instead of printing on the user ID, I want to be able to print out the name John Smith
.
Many people at my company use my program, but not all are Perl experts and most wouldn't know how to install a Perl module. And, since Net::LDAP is not a standard module, many people don't have it.
Instead, I wanted a fallback routine. If I could look up the name with Net::LDAP
, I would print the name, if I couldn't load Net::LDAP
, I would fallback and just print the user ID.
I used the following for testing if Net::LDAP
was installed, and load it if possible:
BEGIN {
eval { require Net::LDAP; };
our $Net_Ldap_Status = 1 if (not $@);
}
What you have to understand is that:
use Foo::Bar;
is the same as:
BEGIN {
require Foo::Bar;
}
It loads in the module at compile time. By surrounding the require
with an eval
I can test whether the statement succeeds (and the module is loaded) or fails (the module doesn't load, but the program doesn't crash either.) I can then check $@
to see if the module loaded or not. $@
is the error message that eval sets. If $@
is null, then the module exists and was loaded successfully.
I need to use a package variable (the our $Net_Ldap_Status
instead of my $Net_Ldap_Status
) or the variable will be lost when the program runs. (I'm not even sure if my $Net_Ldap_Status
would work in a BEGIN
statement).
Now, here's where things get funky...
When I need to check $Net_Ldap_Status
, I need to redeclare it:
our $Net_Ldap_Status;
or I tend to get that non-declared variable error. The funny thing is that it doesn't lose its previous value by redeclaring it. Thus, somewhere in my code is:
our $Net_Ldap_Status;
if ($Net_Ldap_Status) {
print "Code if Net::LDAP is loaded.\n";
}
else {
print "Fallback Code if no Net::LDAP\n";
}