JBAS-769 Clear holds shelf cache poll
authorBill Erickson <berickxx@gmail.com>
Fri, 19 Jun 2015 18:33:50 +0000 (14:33 -0400)
committerBill Erickson <berickxx@gmail.com>
Thu, 21 Mar 2019 19:46:23 +0000 (15:46 -0400)
When called with a new API name, the clear-shelf process returns the
cache key first thing to the caller (via respond_complete).  Instead
of waiting for the clear-shelf API call to complete, which often times
out, the client polls the server with the cache key at regular intervals
to see if the print data has been cached.  Once found, printing is
initiated.

Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm
Open-ILS/web/opac/extras/circ/alt_holds_print.js

index 0f9cf3d..7414d93 100644 (file)
@@ -3573,6 +3573,18 @@ __PACKAGE__->register_method(
     }
 );
 
+__PACKAGE__->register_method(
+    method    => 'clear_shelf_cache',
+    api_name  => 'open-ils.circ.hold.clear_shelf.get_cache.test',
+    stream    => 1,
+    signature => {
+        desc => q/
+            Returns 1 if cache data exists, undef otherwise.
+        /
+    }
+);
+
+
 sub clear_shelf_cache {
     my($self, $client, $auth, $cache_key, $chunk_size) = @_;
     my $e = new_editor(authtoken => $auth, xact => 1);
@@ -3587,6 +3599,9 @@ sub clear_shelf_cache {
         $logger->info("no hold data found in cache"); # XXX TODO return event
         $e->rollback;
         return undef;
+    } elsif ($self->api_name =~ /test/) {
+        # inform the caller that cache data is present and exit.
+        return 1;
     }
 
     my $maximum = 0;
@@ -3669,16 +3684,29 @@ __PACKAGE__->register_method(
     }
 );
 
+__PACKAGE__->register_method(
+    method    => 'clear_shelf_process',
+    stream    => 1,
+    api_name  => 'open-ils.circ.hold.clear_shelf.process.fire',
+);
+
+
 sub clear_shelf_process {
     my($self, $client, $auth, $org_id, $match_copy, $chunk_size) = @_;
 
     my $e = new_editor(authtoken=>$auth);
     $e->checkauth or return $e->die_event;
     my $cache = OpenSRF::Utils::Cache->new('global');
+    my $cache_key = md5_hex(time . $$ . rand());
 
     $org_id ||= $e->requestor->ws_ou;
     $e->allowed('UPDATE_HOLD', $org_id) or return $e->die_event;
 
+    # return the cache key first thing so that the client
+    # can poll for results instead of waiting on the API to complete.
+    $client->respond_complete({cache_key => $cache_key}) 
+        if $self->api_name =~ /fire/;
+
     my $copy_status = $U->ou_ancestor_setting_value($org_id, 'circ.holds.clear_shelf.copy_status');
 
     my @hold_ids = $self->method_lookup(
@@ -3753,7 +3781,6 @@ sub clear_shelf_process {
             }
         }
 
-        my $cache_key = md5_hex(time . $$ . rand());
         $logger->info("clear_shelf_cache: storing under $cache_key");
         $cache->put_cache($cache_key, \%cache_data, 7200); # TODO: 2 hours.  configurable?
 
index 8a8a6ae..06a6c48 100644 (file)
@@ -126,31 +126,68 @@ function hashify_fields(fields) {
 function do_clear_holds() {
     progress_dialog.show(true);
 
-    var launcher;
     fieldmapper.standardRequest(
-        ["open-ils.circ", "open-ils.circ.hold.clear_shelf.process"], {
+        ["open-ils.circ", "open-ils.circ.hold.clear_shelf.process.fire"], {
             "async": true,
             "params": [authtoken, cgi.param("o")],
             "onresponse": function(r) {
                 if (r = openils.Util.readResponse(r)) {
-                    if (r.cache_key) { /* complete */
-                        launcher = dojo.byId("clear_holds_launcher");
+                    launch_cache_poll(r.cache_key);
+                }
+            }
+        }
+    );
+}
+
+// Poll for the existence of cached clear-shelf data.
+// Once found, kick off the print process.
+function launch_cache_poll(cache_key) {
+
+    var poll_timeout;
+    var poll_interval = 10000; // poll every 10 seconds
+    var poll_count = 0;
+
+    function poll_cache() {
+
+        if (poll_count++ > 180) return; // poll 30 minutes max
+
+        console.log("Clear shelf polling cache with key " + cache_key);
+
+        fieldmapper.standardRequest(
+            [   "open-ils.circ",
+                "open-ils.circ.hold.clear_shelf.get_cache.test"], {
+                async: true,
+                params: [authtoken, cache_key, cgi.param("chunk_size")],
+                oncomplete: function(r) {
+                    if (openils.Util.readResponse(r) == 1) {
+                        // found cached data.
+                        // kill the progress dialog and kick off
+                        // the from-cache printer
+                        console.log("Clear shelf poll found data");
+                        progress_dialog.hide();
+
+                        // wire up the re-print link
+                        var launcher = dojo.byId("clear_holds_launcher");
                         launcher.innerHTML = "Re-fetch for Printing"; /* XXX i18n */
+                        launcher.disabled = true;
                         launcher.onclick =
-                            function() { do_clear_holds_from_cache(r.cache_key); };
-                        dojo.byId("clear_holds_set_label").innerHTML = r.cache_key;
-                    } else if (r.maximum) {
-                        progress_dialog.update(r);
+                            function() { do_clear_holds_from_cache(cache_key); };
+                        dojo.byId("clear_holds_set_label").innerHTML = cache_key;
+
+                        do_clear_holds_from_cache(cache_key);
+                    } else {
+                        // kick off another poll 'thread'
+                        console.log("Clear shelf poll found no data");
+                        setTimeout(poll_cache, poll_interval);
                     }
                 }
-            },
-            "oncomplete": function() {
-                progress_dialog.hide();
-                if (launcher) launcher.onclick();
-                else alert(dojo.byId("no_results").innerHTML);
             }
-        }
-    );
+        );
+    }
+
+    // start the initial poll 'thread'
+    // give it a shorter wait time in case the initial calls ends quickly
+    setTimeout(poll_cache, poll_interval / 2);
 }
 
 function do_clear_holds_from_cache(cache_key) {
@@ -177,11 +214,11 @@ function do_clear_holds_from_cache(cache_key) {
                         var hold = hashify_fields(resp.hold_details);
                         hold.action = resp.action;
 
-                       if(resp.hold_details.hold_type) {
-                               hold.hold_type = resp.hold_details.hold_type;
-                       } else {
-                               hold.hold_type = "";
-                       }
+                        if(resp.hold_details.hold_type) {
+                            hold.hold_type = resp.hold_details.hold_type;
+                        } else {
+                            hold.hold_type = "";
+                        }
 
                         var tr = dojo.clone(template);
                         any++;