From b2777220d858dc452a402aa1e21a19b5ff64c6a4 Mon Sep 17 00:00:00 2001 From: Andrew Nugged Date: Thu, 14 Nov 2019 17:59:54 +0000 Subject: [PATCH] Bug 24027: Call ModZebra only once after all items have been added Why happened: - call to ModZebra was done after EACH item added, but it was called only with main biblionumber only, so call was the same on each of requests - and also time spent in that ModZebra sub increased with every next hundred items in DB for that element: so adding every next 100 was slower and slower, Solved: - now it's called only once (by adding some extra parameter to "AddItem*" sub set in postponed mode) - and now adding of elements not so heavily depends from how much items was in DB before. Test plan / How to replicate the issue: (test depends from how already populated DB and Zebra/Elasticsearch DBs so might be not so noticeably fast on empty DBs) - go to one of bibliotitems cataloguing/additem.pl?biblionumber=XXX pages - press button "add multiple copies of this item", put 1000 on slower machines, 5000 on faster - start measuring time + submit page/form It takes some amount of time even up to timeout. After applying patch, run the same procedure for same number of items. Note: it goes fast in both variants on empty database so time not so noticeable (also depents how ModZebra-related stuff is configured). Also it slows more linearly when number of items grows. But, again, it heavily depends how database is populated and indexes are rebuild but it's obvious that it will me much more efficient to call "ModZebra" once after 1000 addings, then call it 1000 times on each item created in the loop. --- C4/Items.pm | 25 +++++++++++++++++++------ cataloguing/additem.pl | 6 +++++- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/C4/Items.pm b/C4/Items.pm index b81fb0aa17..9222c7c981 100644 --- a/C4/Items.pm +++ b/C4/Items.pm @@ -144,7 +144,7 @@ sub CartToShelf { =head2 AddItemFromMarc my ($biblionumber, $biblioitemnumber, $itemnumber) - = AddItemFromMarc($source_item_marc, $biblionumber); + = AddItemFromMarc($source_item_marc, $biblionumber[, $hash_params]); Given a MARC::Record object containing an embedded item record and a biblionumber, create a new item record. @@ -152,7 +152,10 @@ record and a biblionumber, create a new item record. =cut sub AddItemFromMarc { - my ( $source_item_marc, $biblionumber ) = @_; + my $source_item_marc = shift; + my $biblionumber = shift; + my $hash_params = @_ ? shift : {}; + my $dbh = C4::Context->dbh; # parse item hash from MARC @@ -163,13 +166,13 @@ sub AddItemFromMarc { $localitemmarc->append_fields( $source_item_marc->field($itemtag) ); my $item = C4::Biblio::TransformMarcToKoha( $localitemmarc, $frameworkcode, 'items' ); my $unlinked_item_subfields = _get_unlinked_item_subfields( $localitemmarc, $frameworkcode ); - return AddItem( $item, $biblionumber, $dbh, $frameworkcode, $unlinked_item_subfields ); + return AddItem( $item, $biblionumber, $dbh, $frameworkcode, $unlinked_item_subfields, $hash_params ); } =head2 AddItem my ($biblionumber, $biblioitemnumber, $itemnumber) - = AddItem($item, $biblionumber[, $dbh, $frameworkcode, $unlinked_item_subfields]); + = AddItem($item, $biblionumber[, $dbh, $frameworkcode, $unlinked_item_subfields, $hash_params]); Given a hash containing item column names as keys, create a new Koha item record. @@ -178,13 +181,21 @@ The first two optional parameters (C<$dbh> and C<$frameworkcode>) do not need to be supplied for general use; they exist simply to allow them to be picked up from AddItemFromMarc. -The final optional parameter, C<$unlinked_item_subfields>, contains +Optional parameter, C<$unlinked_item_subfields>, contains an arrayref containing subfields present in the original MARC representation of the item (e.g., from the item editor) that are not mapped to C columns directly but should instead be stored in C and included in the biblio items tag for display and indexing. +The final optional parameter, C<$hash_params>, for now expected to contain +'postpone_indexes_update' key, which when true prevents calling of ModZebra sub +so this used when adding items in a batch and then ModZebra called in +C after the whole loop. + +$hash_params: + postpone_indexes_update => true / false + =cut sub AddItem { @@ -197,6 +208,7 @@ sub AddItem { if (@_) { $unlinked_item_subfields = shift; } + my $hash_params = @_ ? shift : {}; # needs old biblionumber and biblioitemnumber $item->{'biblionumber'} = $biblionumber; @@ -220,7 +232,8 @@ sub AddItem { $item->{'itemnumber'} = $itemnumber; - C4::Biblio::ModZebra( $item->{biblionumber}, "specialUpdate", "biblioserver" ); + C4::Biblio::ModZebra( $item->{biblionumber}, "specialUpdate", "biblioserver" ) + unless $hash_params->{postpone_indexes_update}; logaction( "CATALOGUING", "ADD", $itemnumber, "item" ) if C4::Context->preference("CataloguingLog"); diff --git a/cataloguing/additem.pl b/cataloguing/additem.pl index 2c371def28..f0fcf33ecc 100755 --- a/cataloguing/additem.pl +++ b/cataloguing/additem.pl @@ -600,7 +600,8 @@ if ($op eq "additem") { # Adding the item if (!$exist_itemnumber) { - my ($oldbiblionumber,$oldbibnum,$oldbibitemnum) = AddItemFromMarc($record,$biblionumber); + my ( $oldbiblionumber, $oldbibnum, $oldbibitemnum ) = + AddItemFromMarc( $record, $biblionumber, { postpone_indexes_update => 1 } ); set_item_default_location($oldbibitemnum); # We count the item only if it was really added @@ -614,6 +615,9 @@ if ($op eq "additem") { # Preparing the next iteration $oldbarcode = $barcodevalue; } + + C4::Biblio::ModZebra( $biblionumber, "specialUpdate", "biblioserver" ); + undef($itemrecord); } } -- 2.17.1