faster (cached) fuzzy searches
[freeside.git] / FS / bin / freeside-queued
1 #!/usr/bin/perl -w
2
3 use strict;
4 use Fcntl qw(:flock);
5 use POSIX qw(setsid);
6 use FS::UID qw(adminsuidsetup);
7 use FS::Record qw(qsearchs);
8 use FS::queue;
9
10 # no autoloading just yet
11 use FS::cust_main;
12
13 my $pid_file = '/var/run/freeside-queued.pid';
14
15 $SIG{CHLD} = sub { wait }; #zombie prevention
16
17 my $sigterm = 0;
18 my $sigint = 0;
19 $SIG{INT} = sub { warn "SIGINT received; shutting down\n"; $sigint++; };
20 $SIG{TERM} = sub { warn "SIGTERM received; shutting down\n"; $sigterm++; };
21
22 my $user = shift or die &usage;
23
24 &daemonize;
25
26 my $log_file = "/usr/local/etc/freeside/queuelog.";
27
28 $> = $FS::UID::freeside_uid unless $>;
29 adminsuidsetup $user;
30
31 $log_file = "/usr/local/etc/freeside/queuelog.". $FS::UID::datasrc;
32
33 $SIG{__DIE__} = \&_die;
34 $SIG{__WARN__} = \&_logmsg;
35
36
37 while (1) {
38
39   my $job = qsearchs(
40     'queue',
41     { 'status' => 'new' },
42     '',
43     'ORDER BY jobnum FOR UPDATE LIMIT 1'
44   ) or do {
45     sleep 5;
46     next;
47   };
48
49   my %hash = $job->hash;
50   $hash{'status'} = 'locked';
51   my $ljob = new FS::queue ( \%hash );
52   my $error = $ljob->replace($job);
53   die $error if $error;
54
55   my @args = $ljob->args;
56
57   #fork a child for each job (up to some maximum perhaps?)
58   #single-threaded for now.
59
60   my $eval = "&". $ljob->job. '(@args);';
61   warn "running $eval";
62   eval $eval;
63   if ( $@ ) {
64     warn "job $eval failed";
65     my $hash = $ljob->hash;
66     $hash{'status'} = 'failed';
67     my $fjob = new FS::queue( \%hash );
68     my $error = $fjob->replace($ljob);
69     die $error if $error;
70   } else {
71     $ljob->delete;
72   }
73
74 } continue {
75   if ( $sigterm ) {
76     warn "received TERM signal; exiting\n";
77     exit;
78   }
79   if ( $sigint ) {
80     warn "received INT signal; exiting\n";
81     exit;
82   }
83 }
84
85
86 sub datestamp {
87   time2str("%m%d%Y", time);
88 }
89
90 sub _die {
91   my $msg = shift;
92   unlink $pid_file if -e $pid_file;
93   _logmsg($msg);
94 }
95
96 sub _logmsg {
97   chomp( my $msg = shift );
98   my $log = new IO::File ">>$log_file";
99   flock($log, LOCK_EX);
100   seek($log, 0, 2);
101   print $log "[". time2str("%a %b %e %T %Y",time). "] [$$] $msg\n";
102   flock($log, LOCK_UN);
103 }
104
105 sub daemonize {
106
107   chdir "/" or die "Can't chdir to /: $!";
108   open STDIN, '/dev/null'   or die "Can't read /dev/null: $!";
109   defined(my $pid = fork) or die "Can't fork: $!";
110   if ( $pid ) {
111     print "freeside-queued started with pid $pid\n"; #logging to $log_file\n";
112     exit unless $pid_file;
113     my $pidfh = new IO::File ">$pid_file" or exit;
114     print $pidfh "$pid\n";
115     exit;
116   }
117   open STDOUT, '>/dev/null'
118                             or die "Can't write to /dev/null: $!";
119   setsid                  or die "Can't start a new session: $!";
120   open STDERR, '>&STDOUT' or die "Can't dup stdout: $!";
121
122 }
123
124 =head1 NAME
125
126 freeside-queued - Job queue daemon
127
128 =head1 SYNOPSIS
129
130   freeside-queued user
131
132 =head1 DESCRIPTION
133
134 Job queue daemon.  Should be running at all times.
135
136 user: from the mapsecrets file - see config.html from the base documentation
137
138 =head1 VERSION
139
140 =head1 BUGS
141
142 =head1 SEE ALSO
143
144 =cut
145