Bug 23086: Search for collection is broken
[koha.git] / C4 / BackgroundJob.pm
1 package C4::BackgroundJob;
2
3 # Copyright (C) 2007 LibLime
4 # Galen Charlton <galen.charlton@liblime.com>
5 #
6 # This file is part of Koha.
7 #
8 # Koha is free software; you can redistribute it and/or modify it
9 # under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # Koha is distributed in the hope that it will be useful, but
14 # WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with Koha; if not, see <http://www.gnu.org/licenses>.
20
21 use Modern::Perl;
22 use C4::Context;
23 use C4::Auth qw/get_session/;
24 use Digest::MD5;
25
26
27
28 =head1 NAME
29
30 C4::BackgroundJob - manage long-running jobs
31 initiated from the web staff interface
32
33 =head1 SYNOPSIS
34
35  # start tracking a job
36  my $job = C4::BackgroundJob->new($sessionID, $job_name, $job_invoker, $num_work_units);
37  my $jobID = $job->id();
38  $job->progress($work_units_processed);
39  $job->finish($job_result_hashref);
40
41  # get status and results of a job
42  my $job = C4::BackgroundJob->fetch($sessionID, $jobID);
43  my $max_work_units = $job->size();
44  my $work_units_processed = $job->progress();
45  my $job_status = $job->status();
46  my $job_name = $job->name();
47  my $job_invoker = $job->invoker();
48  my $results_hashref = $job->results();
49
50 This module manages tracking the progress and results
51 of (potentially) long-running jobs initiated from 
52 the staff user interface.  Such jobs can include
53 batch MARC and patron record imports.
54
55 =head1 METHODS
56
57 =head2 new
58
59  my $job = C4::BackgroundJob->new($sessionID, $job_name, $job_invoker, $num_work_units);
60
61 Create a new job object and set its status to 'running'.  C<$num_work_units>
62 should be a number representing the size of the job; the units of the
63 job size are up to the caller and could be number of records, 
64 number of bytes, etc.
65
66 =cut
67
68 sub new {
69     my $class = shift;
70     my ($sessionID, $job_name, $job_invoker, $num_work_units) = @_;
71
72     my $self = {};
73     $self->{'sessionID'} = $sessionID;
74     $self->{'name'} = $job_name;
75     $self->{'invoker'} = $job_invoker;
76     $self->{'size'} = $num_work_units;
77     $self->{'progress'} = 0;
78     $self->{'status'} = "running";
79     $self->{'jobID'} = Digest::MD5::md5_hex(Digest::MD5::md5_hex(time().{}.rand().{}.$$));
80     $self->{'extra_values'} = {};
81
82     bless $self, $class;
83     $self->_serialize();
84
85     return $self;
86 }
87
88 # store object in CGI session
89 sub _serialize {
90     my $self = shift;
91
92     my $prefix = "job_" . $self->{'jobID'};
93     my $session = get_session($self->{'sessionID'});
94     $session->param($prefix, $self);
95     $session->flush();
96 }
97
98 =head2 id
99
100  my $jobID = $job->id();
101
102 Read-only accessor for job ID.
103
104 =cut
105
106 sub id {
107     my $self = shift;
108     return $self->{'jobID'};
109 }
110
111 =head2 name
112
113  my $name = $job->name();
114  $job->name($name);
115
116 Read/write accessor for job name.
117
118 =cut
119
120 sub name {
121     my $self = shift;
122     if (@_) {
123         $self->{'name'} = shift;
124         $self->_serialize();
125     } else {
126         return $self->{'name'};
127     }
128 }
129
130 =head2 invoker
131
132  my $invoker = $job->invoker();
133 i $job->invoker($invoker);
134
135 Read/write accessor for job invoker.
136
137 =cut
138
139 sub invoker {
140     my $self = shift;
141     if (@_) {
142         $self->{'invoker'} = shift;
143         $self->_serialize();
144     } else {
145         return $self->{'invoker'};
146     }
147 }
148
149 =head2 progress
150
151  my $progress = $job->progress();
152  $job->progress($progress);
153
154 Read/write accessor for job progress.
155
156 =cut
157
158 sub progress {
159     my $self = shift;
160     if (@_) {
161         $self->{'progress'} = shift;
162         $self->_serialize();
163     } else {
164         return $self->{'progress'};
165     }
166 }
167
168 =head2 status
169
170  my $status = $job->status();
171
172 Read-only accessor for job status.
173
174 =cut
175
176 sub status {
177     my $self = shift;
178     return $self->{'status'};
179 }
180
181 =head2 size
182
183  my $size = $job->size();
184  $job->size($size);
185
186 Read/write accessor for job size.
187
188 =cut
189
190 sub size {
191     my $self = shift;
192     if (@_) {
193         $self->{'size'} = shift;
194         $self->_serialize();
195     } else {
196         return $self->{'size'};
197     }
198 }
199
200 =head2 finish
201
202  $job->finish($results_hashref);
203
204 Mark the job as finished, setting its status to 'completed'.
205 C<$results_hashref> should be a reference to a hash containing
206 the results of the job.
207
208 =cut
209
210 sub finish {
211     my $self = shift;
212     my $results_hashref = shift;
213     $self->{'status'} = 'completed';
214     $self->{'results'} = $results_hashref;
215     $self->_serialize();
216 }
217
218 =head2 results
219
220  my $results_hashref = $job->results();
221
222 Retrieve the results of the current job.  Returns undef 
223 if the job status is not 'completed'.
224
225 =cut
226
227 sub results {
228     my $self = shift;
229     return unless $self->{'status'} eq 'completed';
230     return $self->{'results'};
231 }
232
233 =head2 fetch
234
235  my $job = C4::BackgroundJob->fetch($sessionID, $jobID);
236
237 Retrieve a job that has been serialized to the database. 
238 Returns C<undef> if the job does not exist in the current 
239 session.
240
241 =cut
242
243 sub fetch {
244     my $class = shift;
245     my $sessionID = shift;
246     my $jobID = shift;
247
248     my $session = get_session($sessionID);
249     my $prefix = "job_$jobID";
250     unless (defined $session->param($prefix)) {
251         return;
252     }
253     my $self = $session->param($prefix);
254     bless $self, $class;
255     return $self;
256 }
257
258 =head2 set
259
260 =over 4
261
262 =item $job->set($hashref);
263
264 =back
265
266 Set some variables into the hashref.
267 These variables can be retrieved using the get method.
268
269 =cut
270
271 sub set {
272     my ($self, $hashref) = @_;
273     while ( my ($k, $v) = each %$hashref ) {
274         $self->{extra_values}->{$k} = $v;
275     }
276     $self->_serialize();
277     return;
278 }
279
280 =head2 get
281
282 =over 4
283
284 =item $value = $job->get($key);
285
286 =back
287
288 Get a variable which has been previously stored with the set method.
289
290 =cut
291
292 sub get {
293     my ($self, $key) = @_;
294     return $self->{extra_values}->{$key};
295 }
296
297
298 =head2 clear
299
300 =over 4
301
302 =item $job->clear();
303
304 =back
305
306 Clear the job from the current session.
307
308 =cut
309
310 sub clear {
311     my $self = shift;
312     get_session($self->{sessionID})->clear('job_' . $self->{jobID});
313 }
314
315
316 1;
317 __END__
318
319 =head1 AUTHOR
320
321 Koha Development Team <http://koha-community.org/>
322
323 Galen Charlton <galen.charlton@liblime.com>
324
325 =cut