From 41e3fd285b461758f839e90ddc88e26a657718d3 Mon Sep 17 00:00:00 2001 From: Martin Renvoize Date: Thu, 26 May 2022 16:31:30 +0100 Subject: [PATCH] Bug 30920: Add caching to GetAuthorizedValueDesc This patch adds caching to C4::Biblio::GetAuthorisedValueDesc for performance. We cache each hash involved in the method use for description lookup and we're careful to clear said caches appropraitely on changes. Signed-off-by: Nick Clemens Signed-off-by: Martin Renvoize Signed-off-by: Tomas Cohen Arazi (cherry picked from commit ab866f040dc72da28ed59f3bf16505bfba47ed21) Signed-off-by: Matt Blenkinsop --- C4/Biblio.pm | 67 +++++++++++++++++++++++++++++++++++------ Koha/AuthorisedValue.pm | 33 +++++++++++++++++++- Koha/ClassSource.pm | 29 +++++++++++++++++- Koha/ItemType.pm | 31 +++++++++++++++++++ Koha/Library.pm | 30 ++++++++++++++++++ Koha/Localization.pm | 29 ++++++++++++++++++ 6 files changed, 207 insertions(+), 12 deletions(-) diff --git a/C4/Biblio.pm b/C4/Biblio.pm index 9790febdaa..ee0578bb79 100644 --- a/C4/Biblio.pm +++ b/C4/Biblio.pm @@ -94,6 +94,7 @@ use C4::Charset qw( SetMarcUnicodeFlag SetUTF8Flag ); +use C4::Languages; use C4::Linker; use C4::OAI::Sets; use C4::Items qw( GetMarcItem ); @@ -1373,25 +1374,56 @@ descriptions rather than normal ones when they exist. sub GetAuthorisedValueDesc { my ( $tag, $subfield, $value, $framework, $tagslib, $category, $opac ) = @_; + my $cache = Koha::Caches->get_instance(); + my $cache_key; if ( !$category ) { return $value unless defined $tagslib->{$tag}->{$subfield}->{'authorised_value'}; #---- branch if ( $tagslib->{$tag}->{$subfield}->{'authorised_value'} eq "branches" ) { - my $branch = Koha::Libraries->find($value); - return $branch? $branch->branchname: q{}; + $cache_key = "LibraryNames"; + my $libraries = $cache->get_from_cache( $cache_key, { unsafe => 1 } ); + if ( !$libraries ) { + $libraries = { + map { $_->branchcode => $_->branchname } + Koha::Libraries->search( {}, + { columns => [ 'branchcode', 'branchname' ] } ) + ->as_list + }; + $cache->set_in_cache($cache_key, $libraries); + } + return $libraries->{$value}; } #---- itemtypes if ( $tagslib->{$tag}->{$subfield}->{'authorised_value'} eq "itemtypes" ) { - my $itemtype = Koha::ItemTypes->find( $value ); - return $itemtype ? $itemtype->translated_description : q||; + my $lang = C4::Languages::getlanguage; + $lang //= 'en'; + $cache_key = $lang . 'ItemTypeDescriptions'; + my $itypes = $cache->get_from_cache( $cache_key, { unsafe => 1 } ); + if ( !$itypes ) { + $itypes = + { map { $_->itemtype => $_->translated_description } + Koha::ItemTypes->search()->as_list }; + $cache->set_in_cache( $cache_key, $itypes ); + } + return $itypes->{$value}; } if ( $tagslib->{$tag}->{$subfield}->{'authorised_value'} eq "cn_source" ) { - my $source = GetClassSource($value); - return $source ? $source->{description} : q||; + $cache_key = "ClassSources"; + my $cn_sources = $cache->get_from_cache( $cache_key, { unsafe => 1 } ); + if ( !$cn_sources ) { + $cn_sources = { + map { $_->cn_source => $_->description } + Koha::ClassSources->search( {}, + { columns => [ 'cn_source', 'description' ] } ) + ->as_list + }; + $cache->set_in_cache($cache_key, $cn_sources); + } + return $cn_sources->{$value}; } #---- "true" authorized value @@ -1400,10 +1432,25 @@ sub GetAuthorisedValueDesc { my $dbh = C4::Context->dbh; if ( $category ne "" ) { - my $sth = $dbh->prepare( "SELECT lib, lib_opac FROM authorised_values WHERE category = ? AND authorised_value = ?" ); - $sth->execute( $category, $value ); - my $data = $sth->fetchrow_hashref; - return ( $opac && $data->{'lib_opac'} ) ? $data->{'lib_opac'} : $data->{'lib'}; + $cache_key = "AVDescriptions-" . $category; + my $av_descriptions = $cache->get_from_cache( $cache_key, { unsafe => 1 } ); + if ( !$av_descriptions ) { + $av_descriptions = { + map { + $_->authorised_value => + { lib => $_->lib, lib_opac => $_->lib_opac } + } Koha::AuthorisedValues->search( + { category => $category }, + { + columns => [ 'authorised_value', 'lib_opac', 'lib' ] + } + )->as_list + }; + $cache->set_in_cache($cache_key, $av_descriptions); + } + return ( $opac && $av_descriptions->{$value}->{'lib_opac'} ) + ? $av_descriptions->{$value}->{'lib_opac'} + : $av_descriptions->{$value}->{'lib'}; } else { return $value; # if nothing is found return the original value } diff --git a/Koha/AuthorisedValue.pm b/Koha/AuthorisedValue.pm index 06de1fe743..a1bdb31e2a 100644 --- a/Koha/AuthorisedValue.pm +++ b/Koha/AuthorisedValue.pm @@ -19,7 +19,7 @@ package Koha::AuthorisedValue; use Modern::Perl; - +use Koha::Caches; use Koha::Database; use base qw(Koha::Object Koha::Object::Limit::Library); @@ -34,6 +34,37 @@ Koha::AuthorisedValue - Koha Authorised value Object class =cut +=head3 store + +AuthorisedValue specific store to ensure relevant caches are flushed on change + +=cut + +sub store { + my ($self) = @_; + + my $flush = 0; + + if ( !$self->in_storage ) { + $flush = 1; + } + else { + my $self_from_storage = $self->get_from_storage; + $flush = 1 if ( $self_from_storage->lib ne $self->lib ); + $flush = 1 if ( $self_from_storage->lib_opac ne $self->lib_opac ); + } + + $self = $self->SUPER::store; + + if ($flush) { + my $cache = Koha::Caches->get_instance(); + my $key = "AVDescriptions-".$self->category; + $cache->clear_from_cache($key); + } + + return $self; +} + =head3 opac_description my $description = $av->opac_description(); diff --git a/Koha/ClassSource.pm b/Koha/ClassSource.pm index 3b192ee124..5a2011a65f 100644 --- a/Koha/ClassSource.pm +++ b/Koha/ClassSource.pm @@ -17,7 +17,7 @@ package Koha::ClassSource; use Modern::Perl; - +use Koha::Caches; use Koha::Database; use base qw(Koha::Object); @@ -30,8 +30,35 @@ Koha::ClassSource - Koha Classfication Source Object class =head2 Class Methods +=head3 store + +ClassSource specific store to ensure relevant caches are flushed on change + =cut +sub store { + my ($self) = @_; + + my $flush = 0; + + if ( !$self->in_storage ) { + $flush = 1; + } + else { + my $self_from_storage = $self->get_from_storage; + $flush = 1 if ( $self_from_storage->description ne $self->description ); + } + + $self = $self->SUPER::store; + + if ($flush) { + my $cache = Koha::Caches->get_instance(); + $cache->clear_from_cache('ClassSources'); + } + + return $self; +} + =head3 _type Returns name of corresponding DBIC resultset diff --git a/Koha/ItemType.pm b/Koha/ItemType.pm index 4b77433e8e..754acc97d1 100644 --- a/Koha/ItemType.pm +++ b/Koha/ItemType.pm @@ -20,6 +20,7 @@ use Modern::Perl; use C4::Koha qw( getitemtypeimagelocation ); use C4::Languages; +use Koha::Caches; use Koha::Database; use Koha::CirculationRules; use Koha::Localizations; @@ -36,6 +37,36 @@ Koha::ItemType - Koha Item type Object class =cut +=head3 store + +ItemType specific store to ensure relevant caches are flushed on change + +=cut + +sub store { + my ($self) = @_; + + my $flush = 0; + + if ( !$self->in_storage ) { + $flush = 1; + } + else { + my $self_from_storage = $self->get_from_storage; + $flush = 1 if ( $self_from_storage->description ne $self->description ); + } + + $self = $self->SUPER::store; + + if ($flush) { + my $cache = Koha::Caches->get_instance(); + my $key = "enItemTypeDescriptions"; + $cache->clear_from_cache($key); + } + + return $self; +} + =head3 image_location =cut diff --git a/Koha/Library.pm b/Koha/Library.pm index 20db2ca632..a68cd8da8e 100644 --- a/Koha/Library.pm +++ b/Koha/Library.pm @@ -22,6 +22,7 @@ use Modern::Perl; use C4::Context; +use Koha::Caches; use Koha::Database; use Koha::StockRotationStages; use Koha::SMTP::Servers; @@ -36,6 +37,35 @@ Koha::Library - Koha Library Object class =head2 Class methods +=head3 store + +Library specific store to ensure relevant caches are flushed on change + +=cut + +sub store { + my ($self) = @_; + + my $flush = 0; + + if ( !$self->in_storage ) { + $flush = 1; + } + else { + my $self_from_storage = $self->get_from_storage; + $flush = 1 if ( $self_from_storage->branchname ne $self->branchname ); + } + + $self = $self->SUPER::store; + + if ($flush) { + my $cache = Koha::Caches->get_instance(); + $cache->clear_from_cache('LibraryNames'); + } + + return $self; +} + =head3 stockrotationstages my $stages = Koha::Library->stockrotationstages; diff --git a/Koha/Localization.pm b/Koha/Localization.pm index 3f698303c4..c700c42d6e 100644 --- a/Koha/Localization.pm +++ b/Koha/Localization.pm @@ -21,6 +21,35 @@ use Koha::Database; use base qw(Koha::Object); +=head1 NAME + +Koha::Localization - Koha Localization type Object class + +=head1 API + +=head2 Class methods + +=cut + +=head3 store + +Localization specific store to ensure relevant caches are flushed on change + +=cut + +sub store { + my ($self) = @_; + $self = $self->SUPER::store; + + if ($self->entity eq 'itemtypes') { + my $cache = Koha::Caches->get_instance(); + my $key = $self->lang."ItemTypeDescriptions"; + $cache->clear_from_cache($key); + } + + return $self; +} + sub _type { return 'Localization'; } -- 2.39.5