LP#1596595 Find parallel holds in main query
authorBill Erickson <berickxx@gmail.com>
Mon, 5 Dec 2016 20:46:41 +0000 (15:46 -0500)
committerKathy Lussier <klussier@masslnc.org>
Fri, 17 Feb 2017 05:58:53 +0000 (00:58 -0500)
Identify holds to process by which metarecord the hold is (ultimately)
linked to within the main holds query instead of via a secondary filter.
This avoids the overhead of starting a new batch of hold targeters,
where each process has to fetch all possible holds, then filter down to
those targetable within the current parallel slot.  In thise case, each
process only retrieves the holds it plans to process.

Signed-off-by: Bill Erickson <berickxx@gmail.com>
Signed-off-by: Chris Sharp <csharp@georgialibraries.org>
Signed-off-by: Kathy Lussier <klussier@masslnc.org>
Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm

index 2a87180..5555c86 100644 (file)
@@ -143,7 +143,6 @@ sub find_holds_to_target {
 
     if ($parallel) {
         # In parallel mode, we need to also grab the metarecord for each hold.
-        $query->{select}->{mmrsm} = ['metarecord'];
         $query->{from} = {
             ahr => {
                 rhrr => {
@@ -158,6 +157,28 @@ sub find_holds_to_target {
                 }
             }
         };
+
+        # In parallel mode, only process holds within the current process
+        # whose metarecord ID modulo the parallel targeter count matches
+        # our paralell targeting slot.  This ensures that no 2 processes
+        # will be operating on the same potential copy sets.
+        #
+        # E.g. Running 5 parallel and we are slot 3 (0-based slot 2) of 5, 
+        # process holds whose metarecord ID's are 2, 7, 12, 17, ...
+        # WHERE MOD(mmrsm.id, 5) = 2
+
+        # Slots are 1-based at the API level, but 0-based for modulo.
+        my $slot = $self->{parallel_slot} - 1;
+
+        $query->{where}->{'+mmrsm'} = {
+            id => {
+                '=' => {
+                    transform => 'mod',
+                    value => $slot,
+                    params => [$parallel]
+                }
+            }
+        };
     }
 
     # Newest-first sorting cares only about hold create_time.
@@ -167,30 +188,6 @@ sub find_holds_to_target {
 
     my $holds = $self->editor->json_query($query, {substream => 1});
 
-    # In parallel mode, only process holds within the current process
-    # whose metarecord ID modulo the parallel targeter count matches
-    # our paralell targeting slot.  This ensures that no 2 processes
-    # will be operating on the same potential copy sets.
-    #
-    # E.g. Running 5 parallel and we are slot 3 (0-based slot 2) of 5, 
-    # process holds whose metarecord ID's are 2, 7, 12, 17, ...
-    if ($parallel) {
-
-        # Slots are 1-based at the API level, but 0-based for modulo.
-        my $slot = $self->{parallel_slot} - 1;
-
-        my @slot_holds = 
-            grep { ($_->{metarecord} % $parallel) == $slot } @$holds;
-
-        $logger->info(sprintf(
-            "targeter: parallel targeter (slot %d of %d) trimmed ".
-            "targetable holds set down to %d from %d holds",
-            $slot + 1, $parallel, scalar(@slot_holds), scalar(@$holds)
-        ));
-
-        $holds = \@slot_holds;
-    }
-
     return map {$_->{id}} @$holds;
 }