From 68c92b49d12f4e16fb6679835cc04eeda8c51633 Mon Sep 17 00:00:00 2001 From: Nick Clemens Date: Mon, 15 Nov 2021 13:54:00 +0000 Subject: [PATCH] Bug 29483: Check ItemsAnyAvailableAndNotRestricted once per patron ItemsAnyAvailableAndNotRestricted can take a long time and create nested loops. We can check it once per patron, however, this requires us to flip the loops. Since an item can only be used once, we now add a check to see if this item has already been assigned to a borrower. To test: 1 - Find or create a biblio with 100 items 2 - Place ten 'Next available' holds on a biblio 3 - Set preference 'AllowRenewalIfOtherItemsAvailable' to 'Allow' Set circ rules 'On shelf holds allowed' to 'If any unavailable' 4 - Checkout one of the items to a patron, backdated to be overdue 5 - Note a long loading time for the patron's checkouts 6 - Apply patch, restart_all 7 - Patron loads much faster Signed-off-by: Andrew Fuerste-Henry Signed-off-by: Martin Renvoize Signed-off-by: Fridolin Somers --- C4/Circulation.pm | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/C4/Circulation.pm b/C4/Circulation.pm index 4f2e359b55..a653893d5b 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -27,7 +27,7 @@ use Encode; use Koha::DateUtils qw( dt_from_string output_pref ); use C4::Context; use C4::Stats qw( UpdateStats ); -use C4::Reserves qw( CheckReserves CanItemBeReserved MoveReserve ModReserve ModReserveMinusPriority RevertWaitingStatus IsItemOnHoldAndFound IsAvailableForItemLevelRequest ); +use C4::Reserves qw( CheckReserves CanItemBeReserved MoveReserve ModReserve ModReserveMinusPriority RevertWaitingStatus IsItemOnHoldAndFound IsAvailableForItemLevelRequest ItemsAnyAvailableAndNotRestricted ); use C4::Biblio qw( UpdateTotalIssues ); use C4::Items qw( ModItemTransfer ModDateLastSeen CartToShelf ); use C4::Accounts; @@ -2958,19 +2958,23 @@ sub CanBookBeRenewed { # can be filled with available items. We can get the union of the sets simply # by pushing all the elements onto an array and removing the duplicates. my @reservable; - ITEM: while ( my $item = $items->next ) { - next if IsItemOnHoldAndFound( $item->itemnumber ); - while ( my $patron = $patrons->next ) { - next unless IsAvailableForItemLevelRequest($item, $patron); - next unless CanItemBeReserved($patron,$item,undef,{ignore_hold_counts=>1})->{status} eq 'OK'; - push @reservable, $item->itemnumber; + my %matched_items; + PATRON: while ( my $patron = $patrons->next ) { + my $items_any_available = ItemsAnyAvailableAndNotRestricted( { biblionumber => $item->biblionumber, patron => $patron }); + while ( my $other_item = $items->next ) { + next if $matched_items{$other_item->itemnumber} == 1; + next if IsItemOnHoldAndFound( $other_item->itemnumber ); + next unless IsAvailableForItemLevelRequest($other_item, $patron, undef, $items_any_available); + next unless CanItemBeReserved($patron,$other_item,undef,{ignore_hold_counts=>1})->{status} eq 'OK'; + push @reservable, $other_item->itemnumber; if (@reservable >= @borrowernumbers) { $resfound = 0; - last ITEM; + last PATRON; } + $matched_items{$other_item->itemnumber} = 1; last; } - $patrons->reset; + $items->reset; } } } -- 2.39.5