LP 1904737: Expand Hold Targeter Current Copy Statuses
authorJason Stephenson <jason@sigio.com>
Tue, 16 Feb 2021 20:49:00 +0000 (15:49 -0500)
committerJason Stephenson <jason@sigio.com>
Tue, 30 May 2023 21:45:28 +0000 (17:45 -0400)
The open-ils.hold-targeter service would previously limit the current
copy for a hold to those copies with a status of 0 or 7.  This commit
changes this behavior to retrieve the copy statuses that have the
holdable and is_available fields both set to true.  This is required
for such copies to appear on the holds pull list.

In order to limit the number of queries to retrieve the list of copy
statuses, an app_setting is added to the open-ils.hold-targeter
configuration in the opensrf.xml file, status_cache_time.  This field
can be set to the number of seconds that a hold targeter drone should
wait before checking for changes to the copy statuses in the database.
If you don't make changes or additions to the copy statuses very
often, this should be a large number.  If the setting is missing or
set to zero, then a default value of 300 (5 minutes) is used.

Signed-off-by: Jason Stephenson <jason@sigio.com>
Open-ILS/examples/opensrf.xml.example
Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm

index 05d945f..a67bd46 100644 (file)
@@ -1362,6 +1362,9 @@ vim:et:ts=4:sw=4:
                     <max_spare_children>5</max_spare_children>
                 </unix_config>
                 <app_settings>
+                    <!-- Number of seconds to cache the targetable
+                         copy statuses before looking them up. -->
+                    <status_cache_time>300</status_cache_time>
                 </app_settings>
             </open-ils.hold-targeter>
 
index 31b8852..dabd9d5 100644 (file)
@@ -19,6 +19,7 @@ use DateTime;
 use OpenSRF::AppSession;
 use OpenSRF::Utils::Logger qw(:logger);
 use OpenSRF::Utils::JSON;
+use OpenSRF::Utils::SettingsClient;
 use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenILS::Application::AppUtils;
 use OpenILS::Utils::CStoreEditor qw/:funcs/;
@@ -32,6 +33,9 @@ sub new {
     my $self = {
         editor => new_editor(),
         ou_setting_cache => {},
+        status_cache_time => 0,
+        status_check_time => 0,
+        targetable_statuses => [0,7],
         %args,
     };
     return bless($self, $class);
@@ -208,6 +212,11 @@ sub init {
         hopeless_prone => 't'
     });
     $self->{hopeless_prone_status_ids} = { map { $_->id => 1} @{ $hopeless_prone } };
+
+    my $sc = OpenSRF::Utils::SettingsClient->new;
+    my $timeout = $sc->config_value(apps => "open-ils.hold-targeter" => app_settings => "status_cache_time") || 300;
+    $self->{status_cache_time} = $timeout;
+    $self->{targetable_statuses} = $self->get_targetable_statuses();
 }
 
 
@@ -255,6 +264,22 @@ sub precache_batch_ou_settings {
     }
 }
 
+# Get the list of statuses able to target a hold, i.e. allowed for the
+# current_copy.  Default to 0 and 7 if there ia a failure.
+sub get_targetable_statuses {
+    my $self = shift;
+    if (time() > $self->{status_check_time}) {
+        my $e = $self->{editor};
+        $self->{targetable_statuses} = $e->search_config_copy_status({holdable => 't', is_available => 't'},
+                                                                     {idlist => 1});
+        unless (ref($self->{targetable_statuses}) eq 'ARRAY' && @{$self->{targetable_statuses}}) {
+            $self->{targetable_statuses} = [0,7];
+        }
+        $self->{status_check_time} = $self->{status_cache_time} + time();
+    }
+    return $self->{targetable_statuses};
+}
+
 # -----------------------------------------------------------------------
 # Knows how to target a single hold.
 # -----------------------------------------------------------------------
@@ -843,8 +868,12 @@ sub filter_copies_by_status {
     # Track checked out copies for later recall
     $self->recall_copies([grep {$_->{status} == 1} @{$self->copies}]);
 
+    my $targetable_statuses = $self->parent->get_targetable_statuses();
     $self->copies([
-        grep {$_->{status} == 0 || $_->{status} == 7} @{$self->copies}
+        grep {
+            my $c = $_;
+            grep {$c->{status} == $_} @{$targetable_statuses}
+        } @{$self->copies}
     ]);
 
     return 1;