use Net::SSH::ssh_cmd for all job queueing rather than local duplicated ssh subs
[freeside.git] / FS / FS / queue.pm
1 package FS::queue;
2
3 use strict;
4 use vars qw( @ISA @EXPORT_OK );
5 use Exporter;
6 use FS::Record qw( qsearch qsearchs dbh );
7 #use FS::queue;
8 use FS::queue_arg;
9 use FS::cust_svc;
10
11 @ISA = qw(FS::Record);
12 @EXPORT_OK = qw( joblisting );
13
14 =head1 NAME
15
16 FS::queue - Object methods for queue records
17
18 =head1 SYNOPSIS
19
20   use FS::queue;
21
22   $record = new FS::queue \%hash;
23   $record = new FS::queue { 'column' => 'value' };
24
25   $error = $record->insert;
26
27   $error = $new_record->replace($old_record);
28
29   $error = $record->delete;
30
31   $error = $record->check;
32
33 =head1 DESCRIPTION
34
35 An FS::queue object represents an queued job.  FS::queue inherits from
36 FS::Record.  The following fields are currently supported:
37
38 =over 4
39
40 =item jobnum - primary key
41
42 =item job - fully-qualified subroutine name
43
44 =item status - job status
45
46 =item statustext - freeform text status message
47
48 =item _date - UNIX timestamp
49
50 =item svcnum - optional link to service (see L<FS::cust_svc>)
51
52 =back
53
54 =head1 METHODS
55
56 =over 4
57
58 =item new HASHREF
59
60 Creates a new job.  To add the example to the database, see L<"insert">.
61
62 Note that this stores the hash reference, not a distinct copy of the hash it
63 points to.  You can ask the object for a copy with the I<hash> method.
64
65 =cut
66
67 # the new method can be inherited from FS::Record, if a table method is defined
68
69 sub table { 'queue'; }
70
71 =item insert [ ARGUMENT, ARGUMENT... ]
72
73 Adds this record to the database.  If there is an error, returns the error,
74 otherwise returns false.
75
76 If any arguments are supplied, a queue_arg record for each argument is also
77 created (see L<FS::queue_arg>).
78
79 =cut
80
81 sub insert {
82   my $self = shift;
83
84   local $SIG{HUP} = 'IGNORE';
85   local $SIG{INT} = 'IGNORE';
86   local $SIG{QUIT} = 'IGNORE';
87   local $SIG{TERM} = 'IGNORE';
88   local $SIG{TSTP} = 'IGNORE';
89   local $SIG{PIPE} = 'IGNORE';
90
91   my $oldAutoCommit = $FS::UID::AutoCommit;
92   local $FS::UID::AutoCommit = 0;
93   my $dbh = dbh;
94
95   my $error = $self->SUPER::insert;
96   if ( $error ) {
97     $dbh->rollback if $oldAutoCommit;
98     return $error;
99   }
100
101   foreach my $arg ( @_ ) {
102     my $queue_arg = new FS::queue_arg ( {
103       'jobnum' => $self->jobnum,
104       'arg'    => $arg,
105     } );
106     $error = $queue_arg->insert;
107     if ( $error ) {
108       $dbh->rollback if $oldAutoCommit;
109       return $error;
110     }
111   }
112
113   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
114
115   '';
116
117 }
118
119 =item delete
120
121 Delete this record from the database.  Any corresponding queue_arg records are
122 deleted as well
123
124 =cut
125
126 sub delete {
127   my $self = shift;
128
129   local $SIG{HUP} = 'IGNORE';
130   local $SIG{INT} = 'IGNORE';
131   local $SIG{QUIT} = 'IGNORE';
132   local $SIG{TERM} = 'IGNORE';
133   local $SIG{TSTP} = 'IGNORE';
134   local $SIG{PIPE} = 'IGNORE';
135
136   my $oldAutoCommit = $FS::UID::AutoCommit;
137   local $FS::UID::AutoCommit = 0;
138   my $dbh = dbh;
139
140   my @args = qsearch( 'queue_arg', { 'jobnum' => $self->jobnum } );
141
142   my $error = $self->SUPER::delete;
143   if ( $error ) {
144     $dbh->rollback if $oldAutoCommit;
145     return $error;
146   }
147
148   foreach my $arg ( @args ) {
149     $error = $arg->delete;
150     if ( $error ) {
151       $dbh->rollback if $oldAutoCommit;
152       return $error;
153     }
154   }
155
156   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
157
158   '';
159
160 }
161
162 =item replace OLD_RECORD
163
164 Replaces the OLD_RECORD with this one in the database.  If there is an error,
165 returns the error, otherwise returns false.
166
167 =cut
168
169 # the replace method can be inherited from FS::Record
170
171 =item check
172
173 Checks all fields to make sure this is a valid job.  If there is
174 an error, returns the error, otherwise returns false.  Called by the insert
175 and replace methods.
176
177 =cut
178
179 sub check {
180   my $self = shift;
181   my $error =
182     $self->ut_numbern('jobnum')
183     || $self->ut_anything('job')
184     || $self->ut_numbern('_date')
185     || $self->ut_enum('status',['', qw( new locked failed )])
186     || $self->ut_textn('statustext')
187     || $self->ut_numbern('svcnum')
188     || $self->ut_foreign_keyn('svcnum', 'cust_svc', 'svcnum')
189   ;
190   return $error if $error;
191
192   $self->status('new') unless $self->status;
193   $self->_date(time) unless $self->_date;
194
195   ''; #no error
196 }
197
198 =item args
199
200 =cut
201
202 sub args {
203   my $self = shift;
204   map $_->arg, qsearch( 'queue_arg',
205                         { 'jobnum' => $self->jobnum },
206                         '',
207                         'ORDER BY argnum'
208                       );
209 }
210
211 =item cust_svc
212
213 Returns the FS::cust_svc object associated with this job, if any.
214
215 =cut
216
217 sub cust_svc {
218   my $self = shift;
219   qsearchs('cust_svc', { 'svcnum' => $self->svcnum } );
220 }
221
222 =item joblisting HASHREF
223
224 =cut
225
226 sub joblisting {
227   my($hashref, $noactions) = @_;
228
229   use Date::Format;
230   use FS::CGI;
231
232   my $html = FS::CGI::table(). <<END;
233       <TR>
234         <TH COLSPAN=2>Job</TH>
235         <TH>Args</TH>
236         <TH>Date</TH>
237         <TH>Status</TH>
238         <TH>Account</TH>
239       </TR>
240 END
241
242   my $p = FS::CGI::popurl(2);
243   foreach my $queue ( sort { 
244     $a->getfield('jobnum') <=> $b->getfield('jobnum')
245   } qsearch( 'queue', $hashref ) ) {
246     my $hashref = $queue->hashref;
247     my $jobnum = $queue->jobnum;
248     my $args = join(' ', $queue->args);
249     my $date = time2str( "%a %b %e %T %Y", $queue->_date );
250     my $status = $queue->status;
251     $status .= ': '. $queue->statustext if $queue->statustext;
252     if ( ! $noactions && $status =~ /^failed/ || $status =~ /^locked/ ) {
253       $status .=
254         qq! ( <A HREF="$p/misc/queue.cgi?jobnum=$jobnum&action=new">retry</A> |!.
255         qq! <A HREF="$p/misc/queue.cgi?jobnum=$jobnum&action=del">remove </A> )!;
256     }
257     my $cust_svc = $queue->cust_svc;
258     my $account;
259     if ( $cust_svc ) {
260       my $table = $cust_svc->part_svc->svcdb;
261       my $label = ( $cust_svc->label )[1];
262       $account = qq!<A HREF="../view/$table.cgi?!. $queue->svcnum.
263                  qq!">$label</A>!;
264     } else {
265       $account = '';
266     }
267     $html .= <<END;
268       <TR>
269         <TD>$jobnum</TD>
270         <TD>$hashref->{job}</TD>
271         <TD>$args</TD>
272         <TD>$date</TD>
273         <TD>$status</TD>
274         <TD>$account</TD>
275       </TR>
276 END
277
278 }
279
280   $html .= '</TABLE>';
281
282   $html;
283
284 }
285
286 =back
287
288 =head1 VERSION
289
290 $Id: queue.pm,v 1.4 2002-02-20 01:03:09 ivan Exp $
291
292 =head1 BUGS
293
294 =head1 SEE ALSO
295
296 L<FS::Record>, schema.html from the base documentation.
297
298 =cut
299
300 1;
301