Timeout for resolver interactions
authorArt Rhyno <artrhyno@uwindsor.ca>
Thu, 15 Dec 2011 01:13:30 +0000 (20:13 -0500)
committerArt <artrhyno@uwindsor.ca>
Thu, 5 Jan 2012 15:25:24 +0000 (10:25 -0500)
These changes add some timeout options for using the resolver
setup. For example:

request open-ils.resolver open-ils.resolver.resolve_holdings "issn", \
    "0013-0618", "http://sfx.scholarsportal.info/windsor", 10

where "10" is the number of seconds for a timeout. A default timeout can be
specified in the opensrf.xml file in the ResolverResolver section as well:

<lwp_timeout>30</lwp_timeout>

from TPAC, a request can be also include a timeout option:

[% IF openurl.enabled == 'true';
    FOR issn IN args.resolver_issns;
      resolver = ResolverResolver.resolve_issn(issn, openurl.baseurl,20);
          FOR res IN resolver;
%]

where "20" is the number of seconds for a timeout.

In working through this, I found some bugs in my resolver collection
code in misc_util.tt2 for isbns which I have addressed.

Signed-off-by: Art Rhyno <artrhyno@uwindsor.ca>
Signed-off-by: Dan Scott <dscott@laurentian.ca>
Signed-off-by: Art <artrhyno@uwindsor.ca>

Open-ILS/src/perlmods/lib/OpenILS/Application/ResolverResolver.pm
Open-ILS/src/perlmods/lib/Template/Plugin/ResolverResolver.pm
Open-ILS/src/templates/opac/parts/misc_util.tt2

index 1351a68..df99fac 100644 (file)
@@ -84,6 +84,7 @@ my $cache;
 my $cache_timeout;
 my $default_url_base;              # Default resolver location
 my $resolver_type;              # Default resolver type
+my $default_lwp_timeout;                    # Default browser timeout
 
 our ($ua, $parser);
 
@@ -96,10 +97,14 @@ sub initialize {
     $default_url_base = $sclient->config_value(
         "apps", "open-ils.resolver", "app_settings", "default_url_base");
     $resolver_type = $sclient->config_value(
-        "apps", "open-ils.resolver", "app_settings", "resolver_type");
+        "apps", "open-ils.resolver", "app_settings", "resolver_type") || 'sfx';
+    # We set a browser timeout
+    $default_lwp_timeout = $sclient->config_value(
+        "apps", "open-ils.resolver", "app_settings", "lwp_timeout" ) || 60;
 }
 
 sub child_init {
+
     # We need a User Agent to speak to the SFX beast
     $ua = new LWP::UserAgent;
     $ua->agent('SameOrigin/1.0');
@@ -114,6 +119,19 @@ sub resolve_holdings {
     my $id_type = shift;      # keep it simple for now, either 'issn' or 'isbn'
     my $id_value = shift;     # the normalized ISSN or ISBN
     my $url_base = shift || $default_url_base; 
+    my $lwp_timeout = shift || $default_lwp_timeout; 
+
+    if (!$id_type) {
+        $logger->warn("Resolver was not given an ID type to resolve");
+        return;
+    }
+    if (!$id_value) {
+        $logger->warn("Resolver was not given an ID value to resolve");
+        return;
+    }
+
+    # Need some sort of timeout in case resolver is unreachable
+    $ua->timeout($lwp_timeout);
 
     if ($resolver_type eq 'cufts') {
         return cufts_holdings($self,$conn,$id_type,$id_value,$url_base);
@@ -158,13 +176,25 @@ sub cufts_holdings{
         return $result;
     }
 
-    # Otherwise, let's go and grab the info from the CUFTS server
-    my $req = HTTP::Request->new('GET', "$url_base$url_args");
+    my $res = undef;
 
     # Let's see what we we're trying to request
     $logger->info("Resolving the following request: $url_base$url_args");
 
-    my $res = $ua->request($req);
+    # We attempt to deal with potential problems in request
+    eval {
+        $res = $ua->get("$url_base$url_args"); 
+    } or do {
+        $logger->info("execution error");    
+        return bow_out_gracefully("$url_base?ctx_ver=Z39.88-2004&rft.$id_type=$id_value",
+            'Check link for additional holdings information.');
+    };
+
+    if ($res->status_line =~ /timeout/) {
+        $logger->info("timeout error");    
+        return bow_out_gracefully("$url_base?ctx_ver=Z39.88-2004&rft.$id_type=$id_value",
+            'Check link for additional holdings information.');
+    }
 
     my $xml = $res->content;
     my $parsed_cufts = $parser->parse_string($xml);
@@ -264,14 +294,27 @@ sub sfx_holdings{
         return $result;
     }
 
-    # Otherwise, let's go and grab the info from the SFX server
-    my $req = HTTP::Request->new('GET', "$url_base$url_args");
+    my $res = undef;
 
     # Let's see what we we're trying to request
     $logger->info("Resolving the following request: $url_base$url_args");
 
-    my $res = $ua->request($req);
+    # We attempt to deal with potential problems in request
+    eval {
+        $res = $ua->get("$url_base$url_args"); 
+    } or do {
+        $logger->info("execution error");    
+        return bow_out_gracefully("$url_base?ctx_ver=Z39.88-2004&rft.$id_type=$id_value",
+            'Check link for additional holdings information.');
+    };
+
+    if ($res->status_line =~ /timeout/) {
+        $logger->info("timeout error");    
+        return bow_out_gracefully("$url_base?ctx_ver=Z39.88-2004&rft.$id_type=$id_value",
+            'Check link for additional holdings information.');
+    }
 
+    # All clear
     my $xml = $res->content;
     my $parsed_sfx = $parser->parse_string($xml);
 
@@ -315,6 +358,23 @@ sub sfx_holdings{
     return undef;
 }
 
+# This uses the resolver structure for passing back a link directly to the resolver
+sub bow_out_gracefully {
+    my $alt_url = $_[0];
+    my $reason = $_[1];
+
+    my @sfx_result;
+                
+    push @sfx_result, {
+        public_name => "Online holdings",
+        target_url => $alt_url,
+        target_coverage => $reason,
+        target_embargo => "",
+    };
+   
+    return \@sfx_result;
+}
+
 __PACKAGE__->register_method(
     method    => 'resolve_holdings',
     api_name  => 'open-ils.resolver.resolve_holdings',
@@ -336,6 +396,10 @@ Returns a list of "rhr" objects representing the full-text holdings for a given
                  name => 'url_base',
                  desc => 'The base URL for the resolver and instance',
                  type => 'string'
+            }, {
+                 name => 'lwp_timeout',
+                 desc => 'The timeout for the LWP request',
+                 type => 'string'
             },
         ],
         'return' => {
@@ -366,6 +430,10 @@ Returns a list of raw JSON objects representing the full-text holdings for a giv
                  name => 'url_base',
                  desc => 'The base URL for the resolver and instance',
                  type => 'string'
+            }, {
+                 name => 'lwp_timeout',
+                 desc => 'The timeout for the LWP request',
+                 type => 'string'
             },
         ],
         'return' => {
@@ -420,6 +488,10 @@ Deletes the cached value of the full-text holdings for a given ISBN or ISSN
                  name => 'url_base',
                  desc => 'The base URL for the resolver and instance',
                  type => 'string'
+            }, {
+                 name => 'lwp_timeout',
+                 desc => 'The timeout for the LWP request',
+                 type => 'string'
             },
         ],
         'return' => {
index 88109c2..b81b77f 100644 (file)
@@ -62,12 +62,12 @@ sub ResolverResolver::params {
 
 sub resolve_issn
 {
-    my ($class, $c, $baseurl) = @_;
+    my ($class, $issn, $baseurl, $timeout) = @_;
 
-    if (length($c) <= 9) {
+    if (length($issn) <= 9) {
            my $session = OpenSRF::AppSession->create("open-ils.resolver");
        
-           my $request = $session->request("open-ils.resolver.resolve_holdings.raw", "issn", $c, $baseurl)->gather();
+           my $request = $session->request("open-ils.resolver.resolve_holdings.raw", "issn", $issn, $baseurl, $timeout)->gather();
            if ($request) {
                  return $request;
            }
@@ -79,11 +79,11 @@ sub resolve_issn
 
 sub resolve_isbn
 {
-    my ($class, $c, $baseurl) = @_;
+    my ($class, $isbn, $baseurl, $timeout) = @_;
 
     my $session = OpenSRF::AppSession->create("open-ils.resolver");
        
-    my $request = $session->request("open-ils.resolver.resolve_holdings.raw", "isbn", $c, $baseurl)->gather();
+    my $request = $session->request("open-ils.resolver.resolve_holdings.raw", "isbn", $isbn, $baseurl, $timeout)->gather();
        
     if ($request) {
             return $request;
index b18e678..70c4f43 100644 (file)
         args.holdings = [];
         args.uris = [];
         args.issns = [];
+        args.resolver_isbns = [];
+        args.resolver_issns = [];
 
         # we use $9 of ISBN and ISSN as a flag for e-version
-        sfx_isbn = xml.findnodes('//*[@tag="020"]/*[@code="9"]');
-        IF sfx_isbn;
-            IF sfx_isbn.textContent == "SFX";
-                my_parent = sfx_isbn.parentNode();
-                sfx_isbn = my_parent.findnodes('./*[@code="a"]').textContent;
-                sfx_isbn = sfx_isbn.replace('-', '');
-                args.resolver_isbn = sfx_isbn.replace('\ .*', '');
+        FOR resolver_isbn IN xml.findnodes('//*[@tag="020"]/*[@code="9"]');
+            IF resolver_isbn.textContent == "SFX" || resolver_isbn.textContent == "CUFTS";
+                my_parent = resolver_isbn.parentNode();
+                FOR resolver_isbn_val IN my_parent.findnodes('./*[@code="a"]');
+                    args.resolver_isbns.push(
+                        resolver_isbn_val.textContent.replace('-', '').replace('\ .*', '')
+                    );
+                END;
             END;
         END;
 
-        sfx_issn = xml.findnodes('//*[@tag="022"]/*[@code="9"]');
-        IF sfx_issn;
-            IF sfx_issn.textContent == "SFX";
-                my_parent = sfx_issn.parentNode();
-                sfx_issn = my_parent.findnodes('./*[@code="a"]');
-                args.issns.push(
-                    sfx_issn.textContent.replace('[^\d\-X]', '')
-                );
+        FOR resolver_issn IN xml.findnodes('//*[@tag="022"]/*[@code="9"]');
+            IF resolver_issn.textContent == "SFX" || resolver_issn.textContent == "CUFTS";
+                my_parent = resolver_issn.parentNode();
+                FOR resolver_issn_val IN my_parent.findnodes('./*[@code="a"]');
+                    args.resolver_issns.push(
+                        resolver_issn_val.textContent.replace('[^\d\-X]', '')
+                    );
+                END;
             END;
         END;
 
-        # we snag all issns if no SFX available
-        IF args.issns.size == 0;
-            FOR rawissn IN xml.findnodes('//*[@tag="022"]/*[@code="a"]');
-                args.issns.push(
-                    rawissn.textContent.replace('[^\d\-X]', '')
-                );
-            END;
+        # now snag all issns 
+        FOR rawissn IN xml.findnodes('//*[@tag="022"]/*[@code="a"]');
+            args.issns.push(
+                rawissn.textContent.replace('[^\d\-X]', '')
+            );
         END;
 
         FOR volume IN xml.findnodes('//*[local-name()="volumes"]/*[local-name()="volume"]');