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