From 895f8bd153b9d98ad0920f85f5b1d2c95d0833b1 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Tue, 7 Feb 2017 13:59:10 -0500 Subject: [PATCH] LP#1596595 Targeter leverages batch AOUS lookups Use the batch-by-org AOUS lookup function to fetch settings with one cstore call across a wide set of org units. This reduces the number of cstore calls required, significantly in some cases, for single-use hold targeter instances (like placement time targeting, checkin retargeting). Specifically, in cases where a hold has targetable copies at multiple circ libs, only one cstore call is needed for each of the circ.holds.org_unit_target_weight and circ.holds.target_when_closed settings, as opposed to one cstore call for each per circ lib. Signed-off-by: Bill Erickson Signed-off-by: Chris Sharp Signed-off-by: Kathy Lussier --- .../lib/OpenILS/Utils/HoldTargeter.pm | 58 ++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm b/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm index 394944f118..f7cc947ca5 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm @@ -272,6 +272,33 @@ sub get_ou_setting { return $c->{$org_id}->{$setting}; } +# Fetches settings for a batch of org units. Useful for pre-caching +# setting values across a wide variety of org units without having to +# make a lookup call for every org unit. +# First checks to see if a value exists in the cache. +# For all non-cached values, looks up in DB, then caches the value. +sub precache_batch_ou_settings { + my ($self, $org_ids, $setting, $e) = @_; + + $e ||= $self->{editor}; + my $c = $self->{ou_setting_cache}; + + my @orgs; + for my $org_id (@$org_ids) { + next if exists $c->{$org_id}->{$setting}; + push (@orgs, $org_id); + } + + return unless @orgs; # value aready cached for all requested orgs. + + my %settings = + $U->ou_ancestor_setting_batch_by_org_insecure(\@orgs, $setting, $e); + + for my $org_id (keys %settings) { + $c->{$org_id}->{$setting} = $settings{$org_id}->{value}; + } +} + # ----------------------------------------------------------------------- # Knows how to target a single hold. # ----------------------------------------------------------------------- @@ -649,6 +676,14 @@ sub update_copy_maps { return $self->exit_targeter("Error creating hold copy maps", 1); } +# unique set of circ lib IDs for all in-progress copy blobs. +sub get_copy_circ_libs { + my $self = shift; + my %orgs = map {$_->{circ_lib} => 1} @{$self->copies}; + return [keys %orgs]; +} + + # Returns a map of proximity values to arrays of copy hashes. # The copy hash arrays are weighted consistent with the org unit hold # target weight, meaning that a given copy may appear more than once @@ -667,6 +702,11 @@ sub compile_weighted_proximity_map { my %copy_prox_map = map {$_->{target_copy} => $_->{proximity}} @$hold_copy_maps; + # Pre-fetch the org setting value for all circ libs so that + # later calls can reference the cached value. + $self->parent->precache_batch_ou_settings($self->get_copy_circ_libs, + 'circ.holds.org_unit_target_weight', $self->editor); + my %prox_map; for my $copy_hash (@{$self->copies}) { my $prox = $copy_prox_map{$copy_hash->{id}}; @@ -687,6 +727,22 @@ sub compile_weighted_proximity_map { sub filter_closed_date_copies { my $self = shift; + # Pre-fetch the org setting value for all represented circ libs that + # are closed, minuse the pickup_lib, since it has its own special setting. + my $circ_libs = $self->get_copy_circ_libs; + $circ_libs = [ + grep { + $self->parent->{closed_orgs}->{$_} && + $_ ne $self->hold->pickup_lib + } @$circ_libs + ]; + + # If none of the represented circ libs are closed, we're done here. + return 1 unless @$circ_libs; + + $self->parent->precache_batch_ou_settings( + $circ_libs, 'circ.holds.target_when_closed', $self->editor); + my @filtered_copies; for my $copy_hash (@{$self->copies}) { my $clib = $copy_hash->{circ_lib}; @@ -703,7 +759,7 @@ sub filter_closed_date_copies { # Targeting not allowed at this circ lib when its closed $self->log_hold("skipping copy ". - $copy_hash->{id}."at closed org $clib"); + $copy_hash->{id}." at closed org $clib"); next; } -- 2.43.2