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