Bug 7607: (follow-up) Address OPAC and limits
[koha.git] / C4 / BackgroundJob.pm
blob48683f97659a1aea1e48b15bc8e345e4db944c35
1 package C4::BackgroundJob;
3 # Copyright (C) 2007 LibLime
4 # Galen Charlton <galen.charlton@liblime.com>
6 # This file is part of Koha.
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.
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.
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>.
21 use Modern::Perl;
22 use C4::Context;
23 use C4::Auth qw/get_session/;
24 use Digest::MD5;
28 =head1 NAME
30 C4::BackgroundJob - manage long-running jobs
31 initiated from the web staff interface
33 =head1 SYNOPSIS
35 # start tracking a job
36 my $job = C4::BackgroundJob->new($sessionID, $job_name, $job_invoker, $num_work_units);
37 my $jobID = $job->id();
38 $job->progress($work_units_processed);
39 $job->finish($job_result_hashref);
41 # get status and results of a job
42 my $job = C4::BackgroundJob->fetch($sessionID, $jobID);
43 my $max_work_units = $job->size();
44 my $work_units_processed = $job->progress();
45 my $job_status = $job->status();
46 my $job_name = $job->name();
47 my $job_invoker = $job->invoker();
48 my $results_hashref = $job->results();
50 This module manages tracking the progress and results
51 of (potentially) long-running jobs initiated from
52 the staff user interface. Such jobs can include
53 batch MARC and patron record imports.
55 =head1 METHODS
57 =head2 new
59 my $job = C4::BackgroundJob->new($sessionID, $job_name, $job_invoker, $num_work_units);
61 Create a new job object and set its status to 'running'. C<$num_work_units>
62 should be a number representing the size of the job; the units of the
63 job size are up to the caller and could be number of records,
64 number of bytes, etc.
66 =cut
68 sub new {
69 my $class = shift;
70 my ($sessionID, $job_name, $job_invoker, $num_work_units) = @_;
72 my $self = {};
73 $self->{'sessionID'} = $sessionID;
74 $self->{'name'} = $job_name;
75 $self->{'invoker'} = $job_invoker;
76 $self->{'size'} = $num_work_units;
77 $self->{'progress'} = 0;
78 $self->{'status'} = "running";
79 $self->{'jobID'} = Digest::MD5::md5_hex(Digest::MD5::md5_hex(time().{}.rand().{}.$$));
80 $self->{'extra_values'} = {};
82 bless $self, $class;
83 $self->_serialize();
85 return $self;
88 # store object in CGI session
89 sub _serialize {
90 my $self = shift;
92 my $prefix = "job_" . $self->{'jobID'};
93 my $session = get_session($self->{'sessionID'});
94 $session->param($prefix, $self);
95 $session->flush();
98 =head2 id
100 my $jobID = $job->id();
102 Read-only accessor for job ID.
104 =cut
106 sub id {
107 my $self = shift;
108 return $self->{'jobID'};
111 =head2 name
113 my $name = $job->name();
114 $job->name($name);
116 Read/write accessor for job name.
118 =cut
120 sub name {
121 my $self = shift;
122 if (@_) {
123 $self->{'name'} = shift;
124 $self->_serialize();
125 } else {
126 return $self->{'name'};
130 =head2 invoker
132 my $invoker = $job->invoker();
133 i $job->invoker($invoker);
135 Read/write accessor for job invoker.
137 =cut
139 sub invoker {
140 my $self = shift;
141 if (@_) {
142 $self->{'invoker'} = shift;
143 $self->_serialize();
144 } else {
145 return $self->{'invoker'};
149 =head2 progress
151 my $progress = $job->progress();
152 $job->progress($progress);
154 Read/write accessor for job progress.
156 =cut
158 sub progress {
159 my $self = shift;
160 if (@_) {
161 $self->{'progress'} = shift;
162 $self->_serialize();
163 } else {
164 return $self->{'progress'};
168 =head2 status
170 my $status = $job->status();
172 Read-only accessor for job status.
174 =cut
176 sub status {
177 my $self = shift;
178 return $self->{'status'};
181 =head2 size
183 my $size = $job->size();
184 $job->size($size);
186 Read/write accessor for job size.
188 =cut
190 sub size {
191 my $self = shift;
192 if (@_) {
193 $self->{'size'} = shift;
194 $self->_serialize();
195 } else {
196 return $self->{'size'};
200 =head2 finish
202 $job->finish($results_hashref);
204 Mark the job as finished, setting its status to 'completed'.
205 C<$results_hashref> should be a reference to a hash containing
206 the results of the job.
208 =cut
210 sub finish {
211 my $self = shift;
212 my $results_hashref = shift;
213 $self->{'status'} = 'completed';
214 $self->{'results'} = $results_hashref;
215 $self->_serialize();
218 =head2 results
220 my $results_hashref = $job->results();
222 Retrieve the results of the current job. Returns undef
223 if the job status is not 'completed'.
225 =cut
227 sub results {
228 my $self = shift;
229 return unless $self->{'status'} eq 'completed';
230 return $self->{'results'};
233 =head2 fetch
235 my $job = C4::BackgroundJob->fetch($sessionID, $jobID);
237 Retrieve a job that has been serialized to the database.
238 Returns C<undef> if the job does not exist in the current
239 session.
241 =cut
243 sub fetch {
244 my $class = shift;
245 my $sessionID = shift;
246 my $jobID = shift;
248 my $session = get_session($sessionID);
249 my $prefix = "job_$jobID";
250 unless (defined $session->param($prefix)) {
251 return;
253 my $self = $session->param($prefix);
254 bless $self, $class;
255 return $self;
258 =head2 set
260 =over 4
262 =item $job->set($hashref);
264 =back
266 Set some variables into the hashref.
267 These variables can be retrieved using the get method.
269 =cut
271 sub set {
272 my ($self, $hashref) = @_;
273 while ( my ($k, $v) = each %$hashref ) {
274 $self->{extra_values}->{$k} = $v;
276 $self->_serialize();
277 return;
280 =head2 get
282 =over 4
284 =item $value = $job->get($key);
286 =back
288 Get a variable which has been previously stored with the set method.
290 =cut
292 sub get {
293 my ($self, $key) = @_;
294 return $self->{extra_values}->{$key};
298 =head2 clear
300 =over 4
302 =item $job->clear();
304 =back
306 Clear the job from the current session.
308 =cut
310 sub clear {
311 my $self = shift;
312 get_session($self->{sessionID})->clear('job_' . $self->{jobID});
317 __END__
319 =head1 AUTHOR
321 Koha Development Team <http://koha-community.org/>
323 Galen Charlton <galen.charlton@liblime.com>
325 =cut