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