## @file
# (Enter your file info here)
#
# $Id: Client.pm 462 2008-05-09 15:34:28Z damjan $
## @class RWDE::Gearman::Client
# (Enter RWDE::Gearman::Client info here)
package RWDE::Gearman::Client;
use strict;
use Error qw(:try);
use Gearman::Client;
use Storable qw( thaw nfreeze );
use RWDE::Configuration;
use RWDE::Exceptions;
use vars qw($VERSION);
$VERSION = sprintf "%d", q$Revision: 560 $ =~ /(\d+)/;
## @cmethod object new()
# Construct a new Gearman clients
# @return initialized object
sub new {
my ($proto, $params) = @_;
my $class = ref($proto) || $proto;
my $gear = Gearman::Client->new();
my $self = { gear => $gear };
bless $self, $class;
$gear->job_servers(@{ RWDE::Configuration->GearHost });
$self->initialize();
return $self;
}
## @method object get_gear()
# (Enter get_gear info here)
# @return (Enter explanation for return value----here)
sub get_gear {
my ($self, $params) = @_;
throw RWDE::DevelException({ info => 'No worker present' })
unless defined $self->{gear};
return $self->{gear};
}
## @method void initialize()
# Use this method to define initial behavior of the class. It should be overriden in subclasses
sub initialize {
my ($self, $params) = @_;
return;
}
## @cmethod object Do_task()
# Call the method do_task on the instance
# @return The value/reference produced by the RPC
sub Do_task {
my ($self, $params) = @_;
my $client = $self->new;
return $client->do_task($params);
}
## @method object do_task($method)
# (Enter do_task info here)
# @param method (Enter explanation for param here)
# @return The value/reference produced by the RPC
sub do_task {
my ($self, $params) = @_;
my $client = $self->get_gear();
my $result_ref;
try {
local $SIG{ALRM} = sub { $self->alarm() };
#waiting for longer than 5 seconds raises an exception
alarm 5;
#issue job
$result_ref = $client->do_task($$params{method}, nfreeze($params));
alarm 0;
throw RWDE::DevelException({ info => 'Undefined error trying to execute ' })
unless defined $result_ref;
}
catch Error with {
my $ex = shift;
if ($ex =~ m/Can't call method "syswrite" on an undefined value/) {
throw RWDE::DevelException({ info => "Couldn't connect to Gearman server/worker pair\n" });
}
else {
$ex->throw();
}
};
my $result = thaw $$result_ref;
$result = $$result;
#temporarily support multi-element returns as the default case
#special case the single element returns
if ((ref $result eq 'ARRAY') && scalar @{$result} == 1) {
$result = @{$result}[0];
}
#check for error
if ((ref $result) =~ m/Exception/i || (ref $result) =~ m/Error::Simple/i) {
#result is an exception :/
$result->throw();
}
return $result;
}
## @method void alarm()
# Handle the timeout fromt the server by throwing an exception (devel)
sub alarm {
my ($self, $params) = @_;
throw RWDE::DevelException({ info => 'Haven\'t received response within allotted time' });
return ();
}
1;