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