LP#1631522: Dispatch mode for method_lookup subrequests
authorMike Rylander <mrylander@gmail.com>
Thu, 25 Aug 2016 21:42:31 +0000 (17:42 -0400)
committerGalen Charlton <gmc@esilibrary.com>
Tue, 1 Nov 2016 21:14:02 +0000 (17:14 -0400)
There is a pattern in the wild of using OpenSRF's method_lookup() facility
to decide between one of several local methods when delegating to pre-existing
logic.  Often times, we want to simply hand control over to another method,
but the output of a subrequest's run() is an array of results.  The caller has
to know if, and how, to restructure the result for the client.

Instead, we can now call dispatch() instead of run() and have OpenSRF session
control completely passed to the delegate code.  This way, the delegate code
need not know anything about its caller, and vice versa.

Signed-off-by: Mike Rylander <mrylander@gmail.com>
Signed-off-by: Galen Charlton <gmc@esilibrary.com>

src/perl/lib/OpenSRF/AppSession.pm
src/perl/lib/OpenSRF/Application.pm

index ba3aa54..158513b 100644 (file)
@@ -1135,29 +1135,54 @@ sub gather {
 
 
 package OpenSRF::AppSubrequest;
+use base 'OpenSRF::AppRequest';
 
 sub respond {
        my $self = shift;
        return if $self->complete;
 
        my $resp = shift;
+    return $self->SUPER::respond($resp) if $self->respond_directly;
+
        push @{$$self{resp}}, $resp if (defined $resp);
 }
 
 sub respond_complete {
        my $self = shift;
+    return $self->SUPER::respond_complete(@_) if $self->respond_directly;
        $self->respond(@_);
        $self->complete(1);
 }
 
 sub new {
-       my $class = shift;
-       $class = ref($class) || $class;
-       return bless({complete => 0, resp => [], @_}, $class);
+    my $class = shift;
+    $class = ref($class) || $class;
+    my $self = bless({
+        complete        => 0,
+        respond_directly=> 0,  # use the passed session directly (RD mode)
+        resp            => [],
+        threadTrace     => 0,  # needed for respond in RD mode
+        max_chunk_count => 0,  # needed for respond in RD mode
+        max_chunk_size  => 0,  # needed for respond in RD mode
+        current_chunk   => [], # needed for respond_complete in RD mode
+        @_
+    }, $class);
+    if ($self->session) {
+        # steal the thread trace from the parent session for RD mode
+        $self->{threadTrace} = $self->session->session_threadTrace || $self->session->last_threadTrace;
+    }
+    return $self;
 }
 
 sub responses { @{$_[0]->{resp}} }
 
+sub respond_directly {
+       my $x = shift;
+       my $s = shift;
+       $x->{respond_directly} = $s if (defined $s);
+       return $x->session && $x->{respond_directly};
+}
+
 sub session {
        my $x = shift;
        my $s = shift;
index 9a958e0..5d01cb5 100644 (file)
@@ -576,6 +576,13 @@ sub method_lookup {
        return $meth;
 }
 
+sub dispatch {
+       my $self = shift;
+       $log->debug("Creating a dispatching SubRequest object", DEBUG);
+    my $req = OpenSRF::AppSubrequest->new( session => $self->session, respond_directly => 1 );
+    return $self->run($req,@_);
+}
+
 sub run {
        my $self = shift;
        my $req = shift;
@@ -627,7 +634,7 @@ sub run {
 
                $log->debug("Coderef for [$$self{package}::$$self{method}] has been run", DEBUG);
 
-               if ( ref($req) and UNIVERSAL::isa($req, 'OpenSRF::AppSubrequest') ) {
+               if ( ref($req) and UNIVERSAL::isa($req, 'OpenSRF::AppSubrequest') and !$req->respond_directly ) {
                        $req->respond($resp) if (defined $resp);
                        $log->debug("SubRequest object is responding with : " . join(" ",$req->responses), DEBUG);
                        return $req->responses;