4 use vars qw( $DEBUG $kids $max_kids %kids );
5 use POSIX qw(:sys_wait_h);
7 use FS::UID qw(adminsuidsetup forksuidsetup driver_name dbh myconnect);
8 use FS::Daemon qw(daemonize1 drop_root logfile daemonize2 sigint sigterm);
9 use FS::Record qw(qsearch qsearchs);
13 # no autoloading for non-FS classes...
18 $max_kids = '10'; #guess it should be a config file...
21 my $user = shift or die &usage;
23 warn "starting daemonization (forking)\n" if $DEBUG;
24 #daemonize1('freeside-queued',$user); #to keep pid files unique w/multi installs
25 daemonize1('freeside-queued');
27 warn "dropping privledges\n" if $DEBUG;
31 $ENV{HOME} = (getpwuid($>))[7]; #for ssh
33 warn "connecting to database\n" if $DEBUG;
36 eval { adminsuidsetup $user; };
39 warn "sleeping for reconnect...\n";
44 logfile( "%%%FREESIDE_LOG%%%/queuelog.". $FS::UID::datasrc );
46 warn "completing daemonization (detaching))\n" if $DEBUG;
55 #prevent runaway forking
56 if ( $kids >= $max_kids ) {
57 warn "WARNING: maximum $kids children reached\n" unless $warnkids++;
59 sleep 1; #waiting for signals is cheap
64 unless ( dbh && dbh->ping ) {
65 warn "WARNING: connection to database lost, reconnecting...\n";
67 eval { $FS::UID::dbh = myconnect; };
69 unless ( !$@ && dbh && dbh->ping ) {
70 warn "WARNING: still no connection to database, sleeping for retry...\n";
74 warn "WARNING: reconnected to database\n";
80 # my $oldAutoCommit = $FS::UID::AutoCommit;
81 # local $FS::UID::AutoCommit = 0;
82 $FS::UID::AutoCommit = 0;
84 my $nodepend = 'AND 0 = ( SELECT COUNT(*) FROM queue_depend'.
85 ' WHERE queue_depend.jobnum = queue.jobnum )';
87 my $order_by = "ORDER BY jobnum ". ( driver_name eq 'mysql'
88 ? 'LIMIT 1 FOR UPDATE'
89 : 'FOR UPDATE LIMIT 1' );
93 'hashref' => { 'status' => 'new' },
94 'extra_sql' => $nodepend,
95 'order_by' => $order_by,
99 warn "WARNING: database error, closing connection: ". dbh->errstr;
108 my %hash = $job->hash;
109 $hash{'status'} = 'locked';
110 my $ljob = new FS::queue ( \%hash );
111 my $error = $ljob->replace($job);
113 warn "WARNING: database error locking job, closing connection: ".
119 # if $oldAutoCommit {
121 warn "WARNING: database error, closing connection: ". dbh->errstr;
127 $FS::UID::AutoCommit = 1;
130 my @args = $ljob->args;
131 splice @args, 0, 1, $ljob if $args[0] eq '_JOB';
133 defined( my $pid = fork ) or do {
134 warn "WARNING: can't fork: $!\n";
135 my %hash = $job->hash;
136 $hash{'status'} = 'failed';
137 $hash{'statustext'} = "[freeside-queued] can't fork: $!";
138 my $ljob = new FS::queue ( \%hash );
139 my $error = $ljob->replace($job);
140 die $error if $error;
141 next; #don't increment the kid counter
150 $FS::UID::dbh->{InactiveDestroy} = 1;
152 forksuidsetup($user);
155 #if ( $ljob->job =~ /(FS::part_export::\w+)::/ ) {
156 if ( $ljob->job =~ /(FS::(part_export|cust_main)::\w+)::/
157 || $ljob->job =~ /(FS::\w+)::/
163 warn "job use $class failed";
164 my %hash = $ljob->hash;
165 $hash{'status'} = 'failed';
166 $hash{'statustext'} = $@;
167 my $fjob = new FS::queue( \%hash );
168 my $error = $fjob->replace($ljob);
169 die $error if $error;
174 my $eval = "&". $ljob->job. '(@args);';
175 warn 'running "&'. $ljob->job. '('. join(', ', @args). ")\n" if $DEBUG;
176 eval $eval; #throw away return value? suppose so
178 warn "job $eval failed";
179 my %hash = $ljob->hash;
180 $hash{'status'} = 'failed';
181 $hash{'statustext'} = $@;
182 my $fjob = new FS::queue( \%hash );
183 my $error = $fjob->replace($ljob);
184 die $error if $error;
195 warn "received TERM signal; exiting\n";
199 warn "received INT signal; exiting\n";
205 die "Usage:\n\n freeside-queued user\n";
209 foreach my $pid ( keys %kids ) {
210 my $kid = waitpid($pid, WNOHANG);
220 freeside-queued - Job queue daemon
228 Job queue daemon. Should be running at all times.
230 user: from the mapsecrets file - see config.html from the base documentation