LP#1971745: work around issue that can cause large hold shelf lists to fail
authorGalen Charlton <gmc@equinoxOLI.org>
Thu, 5 May 2022 16:44:26 +0000 (12:44 -0400)
committerJason Stephenson <jstephenson@cwmars.org>
Mon, 28 Nov 2022 19:53:26 +0000 (14:53 -0500)
This patch addresses an issue where hold shelf lists with
more than ~350 rows can fail to be retrieved. It works by
making the open-ils.circ.hold.wide_hash.stream method fetch
the holds from an open-ils.storage method in one fell swoop,
rather than both streaming the list from open-ils.storage and
streaming it back to the client that invoked the open-ils.circ
method.

I suspect that this is working around a subtle OpenSRF bug when
bidirectional streaming is in play, but I'm not positive.

To test
-------
[1] Set up an environment with hundreds or thousands of holds on
    a shelf at an OU.
[2] Attempt to display the holds shelf list.
[3] It may fail; if it doesn't, try with even larger number of holds
    or by setting up a test system that has ejabberd s2s going on
    to service requests.
[4] Apply the patch and repeat step 2. This time, the holds shelf
    list should be consistently retrieved. There will also be a
    user-visible change: the spinner on the AngularJS holds shelf page
    will pause for a few seconds, then start advancing.

Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
Signed-off-by: Josh Stompro <stompro@stompro.org>
Signed-off-by: Jason Stephenson <jstephenson@cwmars.org>
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm

index a11d0ab..565fe21 100644 (file)
@@ -3644,29 +3644,29 @@ sub stream_wide_holds {
 
     my $st = OpenSRF::AppSession->create('open-ils.storage');
     my $req = $st->request(
-        'open-ils.storage.action.live_holds.wide_hash',
+        'open-ils.storage.action.live_holds.wide_hash.atomic',
         $restrictions, $order_by, $limit, $offset
     );
 
-    my $count = $req->recv;
-    if(!$count) {
+    my $results = $req->recv;
+    if(!$results) {
         return 0;
     }
 
-    if(UNIVERSAL::isa($count,"Error")) {
-        throw $count ($count->stringify);
+    if(UNIVERSAL::isa($results,"Error")) {
+        throw OpenSRF::EX::ERROR ("Error fetch hold shelf list");
     }
 
-    $count = $count->content;
+    my @rows = @{ $results->content };
 
     # Force immediate send of count response
     my $mbc = $client->max_bundle_count;
     $client->max_bundle_count(1);
-    $client->respond($count);
+    $client->respond(shift @rows);
     $client->max_bundle_count($mbc);
 
-    while (my $hold = $req->recv) {
-        $client->respond($hold->content) if $hold->content;
+    foreach my $hold (@rows) {
+        $client->respond($hold) if $hold;
     }
 
     $client->respond_complete;