bug 4865: added dependency for using memcached for sessions
[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  # 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
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 undef 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 undef;
257     }
258     my $self = $session->param($prefix);
259     bless $self, $class;
260     return $self;
261 }
262
263 1;
264 __END__
265
266 =head1 AUTHOR
267
268 Koha Development Team <http://koha-community.org/>
269
270 Galen Charlton <galen.charlton@liblime.com>
271
272 =cut