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