View | Details | Raw Unified | Return to bug 27344
Collapse All | Expand All

(-)a/Koha/BackgroundJob.pm (+3 lines)
Lines 26-31 use Koha::DateUtils qw( dt_from_string ); Link Here
26
use Koha::Exceptions;
26
use Koha::Exceptions;
27
use Koha::BackgroundJob::BatchUpdateBiblio;
27
use Koha::BackgroundJob::BatchUpdateBiblio;
28
use Koha::BackgroundJob::BatchUpdateAuthority;
28
use Koha::BackgroundJob::BatchUpdateAuthority;
29
use Koha::BackgroundJob::UpdateElasticIndex;
29
30
30
use base qw( Koha::Object );
31
use base qw( Koha::Object );
31
32
Lines 141-146 sub process { Link Here
141
      ? Koha::BackgroundJob::BatchUpdateBiblio->process($args)
142
      ? Koha::BackgroundJob::BatchUpdateBiblio->process($args)
142
      : $job_type eq 'batch_authority_record_modification'
143
      : $job_type eq 'batch_authority_record_modification'
143
      ? Koha::BackgroundJob::BatchUpdateAuthority->process($args)
144
      ? Koha::BackgroundJob::BatchUpdateAuthority->process($args)
145
      : $job_type eq 'update_elastic_index'
146
      ? Koha::BackgroundJob::UpdateElasticIndex->process($args)
144
      : Koha::Exceptions::Exception->throw('->process called without valid job_type');
147
      : Koha::Exceptions::Exception->throw('->process called without valid job_type');
145
}
148
}
146
149
(-)a/Koha/BackgroundJob/UpdateElasticIndex.pm (+132 lines)
Line 0 Link Here
1
package Koha::BackgroundJob::UpdateElasticIndex;
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
use JSON qw( encode_json decode_json );
20
21
use Koha::BackgroundJobs;
22
use Koha::DateUtils qw( dt_from_string );
23
use C4::Biblio;
24
use C4::MarcModificationTemplates;
25
26
use base 'Koha::BackgroundJob';
27
28
=head1 NAME
29
30
Koha::BackgroundJob::UpdateElasticIndex - Update Elastic index
31
32
This is a subclass of Koha::BackgroundJob.
33
34
=head1 API
35
36
=head2 Class methods
37
38
=head3 job_type
39
40
Define the job type of this job: update_elastic_index
41
42
=cut
43
44
sub job_type {
45
    return 'update_elastic_index';
46
}
47
48
=head3 process
49
50
Process the modification.
51
52
=cut
53
54
sub process {
55
    my ( $self, $args ) = @_;
56
57
    my $job = Koha::BackgroundJobs->find( $args->{job_id} );
58
59
    if ( !exists $args->{job_id} || !$job || $job->status eq 'cancelled' ) {
60
        return;
61
    }
62
63
    # FIXME If the job has already been started, but started again (worker has been restart for instance)
64
    # Then we will start from scratch and so double process the same records
65
66
    my $job_progress = 0;
67
    $job->started_on(dt_from_string)
68
        ->progress($job_progress)
69
        ->status('started')
70
        ->store;
71
72
    my @record_ids = @{ $args->{record_ids} };
73
    my $record_server = $args->{record_server};
74
75
    my $report = {
76
        total_records => scalar @record_ids,
77
        total_success => 0,
78
    };
79
80
    my @messages;
81
    eval {
82
        my $es_index =
83
            $record_server eq "authorityserver"
84
          ? $Koha::SearchEngine::AUTHORITIES_INDEX
85
          : $Koha::SearchEngine::BIBLIOS_INDEX;
86
        my $indexer = Koha::SearchEngine::Indexer->new({ index => $es_index });
87
        $indexer->update_index(\@record_ids);
88
    };
89
    if ( $@ ) {
90
        push @messages, {
91
            type => 'error',
92
            code => 'index_error',
93
            error => $@,
94
95
        }
96
    } else {
97
        # FIXME This is not correct if some record_ids have been skipped
98
        $report->{total_success} = scalar @record_ids;
99
    }
100
101
    my $job_data = decode_json $job->data;
102
    $job_data->{messages} = \@messages;
103
    $job_data->{report} = $report;
104
105
    $job->ended_on(dt_from_string)
106
        ->data(encode_json $job_data);
107
    $job->status('finished') if $job->status ne 'cancelled';
108
    $job->store;
109
}
110
111
=head3 enqueue
112
113
Enqueue the new job
114
115
=cut
116
117
sub enqueue {
118
    my ( $self, $args) = @_;
119
120
    return unless exists $args->{record_server};
121
    return unless exists $args->{record_ids};
122
123
    my $record_server = $args->{record_server};
124
    my @record_ids = @{ $args->{record_ids} };
125
126
    $self->SUPER::enqueue({
127
        job_size => scalar @record_ids,
128
        job_args => {record_server => $record_server, record_ids => \@record_ids,}
129
    });
130
}
131
132
1;
(-)a/Koha/SearchEngine/Elasticsearch/Indexer.pm (-22 / +30 lines)
Lines 26-31 use Data::Dumper; Link Here
26
26
27
use Koha::Exceptions;
27
use Koha::Exceptions;
28
use Koha::SearchEngine::Zebra::Indexer;
28
use Koha::SearchEngine::Zebra::Indexer;
29
use Koha::BackgroundJob::UpdateElasticIndex;
29
use C4::AuthoritiesMarc qw//;
30
use C4::AuthoritiesMarc qw//;
30
use C4::Biblio;
31
use C4::Biblio;
31
use C4::Context;
32
use C4::Context;
Lines 97-108 Arrayref of C<MARC::Record>s. Link Here
97
=cut
98
=cut
98
99
99
sub update_index {
100
sub update_index {
100
    my ($self, $biblionums, $records) = @_;
101
    my ($self, $record_ids, $records) = @_;
102
103
    my $index_record_ids;
104
    unless ( $records && @$records ) {
105
        for my $record_id ( sort { $a <=> $b } @$record_ids ) {
106
107
            next unless $record_id;
108
109
            my $record = $self->_get_record( $record_id );
110
            if( $record ){
111
                push @$records, $record;
112
                push @$index_record_ids, $record_id;
113
            }
114
        }
115
    } else {
116
        $index_record_ids = $record_ids;
117
    }
101
118
102
    my $documents = $self->marc_records_to_documents($records);
119
    my $documents = $self->marc_records_to_documents($records);
103
    my @body;
120
    my @body;
104
    for (my $i = 0; $i < scalar @$biblionums; $i++) {
121
    for (my $i = 0; $i < scalar @$index_record_ids; $i++) {
105
        my $id = $biblionums->[$i];
122
        my $id = $index_record_ids->[$i];
106
        my $document = $documents->[$i];
123
        my $document = $documents->[$i];
107
        push @body, {
124
        push @body, {
108
            index => {
125
            index => {
Lines 264-270 sub update_mappings { Link Here
264
    $self->set_index_status_ok();
281
    $self->set_index_status_ok();
265
}
282
}
266
283
267
=head2 update_index_background($biblionums, $records)
284
=head2 update_index_background($record_numbers, $server)
268
285
269
This has exactly the same API as C<update_index> however it'll
286
This has exactly the same API as C<update_index> however it'll
270
return immediately. It'll start a background process that does the adding.
287
return immediately. It'll start a background process that does the adding.
Lines 274-285 it to be updated by a regular index cron job in the future. Link Here
274
291
275
=cut
292
=cut
276
293
277
# TODO implement in the future - I don't know the best way of doing this yet.
278
# If fork: make sure process group is changed so apache doesn't wait for us.
279
280
sub update_index_background {
294
sub update_index_background {
281
    my $self = shift;
295
    my ( $self, $record_numbers, $server ) = @_;
282
    $self->update_index(@_);
296
297
    Koha::BackgroundJob::UpdateElasticIndex->new->enqueue({ record_ids => $record_numbers, record_server => $server });
283
}
298
}
284
299
285
=head2 index_records
300
=head2 index_records
Lines 302-318 sub index_records { Link Here
302
    if ( $op eq 'specialUpdate' ) {
317
    if ( $op eq 'specialUpdate' ) {
303
        my $index_record_numbers;
318
        my $index_record_numbers;
304
        if ($records){
319
        if ($records){
305
            $index_record_numbers = $record_numbers;
320
            $self->update_index( $record_numbers, $records );
306
        } else {
321
        } else {
307
            foreach my $record_number ( @$record_numbers ){
322
            $self->update_index_background( $record_numbers, $server );
308
                my $record = _get_record( $record_number, $server );
309
                if( $record ){
310
                    push @$records, $record;
311
                    push @$index_record_numbers, $record_number;
312
                }
313
            }
314
        }
323
        }
315
        $self->update_index_background( $index_record_numbers, $records ) if $index_record_numbers && $records;
316
    }
324
    }
317
    elsif ( $op eq 'recordDelete' ) {
325
    elsif ( $op eq 'recordDelete' ) {
318
        $self->delete_index_background( $record_numbers );
326
        $self->delete_index_background( $record_numbers );
Lines 322-331 sub index_records { Link Here
322
}
330
}
323
331
324
sub _get_record {
332
sub _get_record {
325
    my ( $id, $server ) = @_;
333
    my ( $self, $record_id ) = @_;
326
    return $server eq 'biblioserver'
334
    return $self->index eq $Koha::SearchEngine::BIBLIOS_INDEX
327
        ? C4::Biblio::GetMarcBiblio({ biblionumber => $id, embed_items  => 1 })
335
        ? C4::Biblio::GetMarcBiblio({ biblionumber => $record_id, embed_items  => 1 })
328
        : C4::AuthoritiesMarc::GetAuthority($id);
336
        : C4::AuthoritiesMarc::GetAuthority($record_id);
329
}
337
}
330
338
331
=head2 delete_index($biblionums)
339
=head2 delete_index($biblionums)
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/background_jobs.tt (+16 lines)
Lines 85-90 Link Here
85
                            </div>
85
                            </div>
86
                        [% END %]
86
                        [% END %]
87
                    [% END %]
87
                    [% END %]
88
                [% CASE 'update_elastic_index' %]
89
                    [% SET report = job.report %]
90
                    [% IF report %]
91
                        [% IF report.total_records == 1 %]
92
                            [% IF report.total_success == 1 %]
93
                                <div class="dialog message">The records have successfully been reindexed!</div>
94
                            [% END %]
95
                        [% ELSE %]
96
                            <div class="dialog message">
97
                                [% report.total_success | html %] / [% report.total_records | html %] records have successfully been reindexed. Some errors occurred.
98
                                [% IF job.status == 'cancelled' %]The job has been cancelled before it finished.[% END %]
99
                            </div>
100
                        [% END %]
101
                    [% END %]
88
                [% CASE %]Job type "[% job.type | html %]" not handled in the template
102
                [% CASE %]Job type "[% job.type | html %]" not handled in the template
89
                [% END %]
103
                [% END %]
90
            </li>
104
            </li>
Lines 126-131 Link Here
126
                            [% END %]
140
                            [% END %]
127
                        </div>
141
                        </div>
128
                    [% END %]
142
                    [% END %]
143
                [% CASE 'update_elastic_index' %]
129
                [% CASE %]Job type "[% job.type | html %]" not handled in the template
144
                [% CASE %]Job type "[% job.type | html %]" not handled in the template
130
                [% END %]
145
                [% END %]
131
            </li>
146
            </li>
Lines 165-170 Link Here
165
                        [% SWITCH job.type %]
180
                        [% SWITCH job.type %]
166
                        [% CASE 'batch_biblio_record_modification' %]Batch bibliographic record modification
181
                        [% CASE 'batch_biblio_record_modification' %]Batch bibliographic record modification
167
                        [% CASE 'batch_authority_record_modification' %]Batch authority record modification
182
                        [% CASE 'batch_authority_record_modification' %]Batch authority record modification
183
                        [% CASE 'update_elastic_index' %]Update Elasticsearch index
168
                        [% CASE %][% job.type | html %]
184
                        [% CASE %][% job.type | html %]
169
                        [% END %]
185
                        [% END %]
170
                    </td>
186
                    </td>
(-)a/misc/background_jobs_worker.pl (-2 / +5 lines)
Lines 28-34 try { Link Here
28
    warn sprintf "Cannot connect to the message broker, the jobs will be processed anyway (%s)", $_;
28
    warn sprintf "Cannot connect to the message broker, the jobs will be processed anyway (%s)", $_;
29
};
29
};
30
30
31
my @job_types = qw( batch_biblio_record_modification batch_authority_record_modification );
31
my @job_types = qw(
32
    batch_biblio_record_modification
33
    batch_authority_record_modification
34
    update_elastic_index
35
);
32
36
33
if ( $conn ) {
37
if ( $conn ) {
34
    # FIXME cf note in Koha::BackgroundJob about $namespace
38
    # FIXME cf note in Koha::BackgroundJob about $namespace
35
- 

Return to bug 27344