e410e731117dac3540e13695ec9837c3c025bd4a
[kivitendo-erp.git] / SL / System / TaskServer.pm
1 package SL::System::TaskServer;
2
3 use strict;
4
5 use parent qw(Rose::Object);
6
7 use Rose::Object::MakeMethods::Generic (
8   scalar => [ qw(last_command_output) ],
9 );
10
11 use File::Slurp;
12 use File::Spec::Functions qw(:ALL);
13 use File::Temp;
14
15 use SL::System::Process;
16
17 use constant {
18   OK           =>  0,
19   ERR_PID_FILE => -1,
20   ERR_PROCESS  => -2,
21 };
22
23 use constant PID_BASE => "users/pid";
24
25 sub status {
26   my ($self) = @_;
27
28   my $pid = $self->_read_pid;
29   return ERR_PID_FILE unless $pid;
30
31   return kill(0, $pid) ? OK : ERR_PROCESS;
32 }
33
34 sub is_running {
35   my ($self) = @_;
36
37   return $self->status == OK;
38 }
39
40 sub start {
41   my ($self) = @_;
42
43   return $self->_run_script_command('start');
44 }
45
46 sub start_if_not_running {
47   my ($self) = @_;
48
49   $self->start unless $self->is_running;
50 }
51
52 sub stop {
53   my ($self) = @_;
54
55   return $self->_run_script_command('stop');
56 }
57
58 sub wake_up {
59   my ($self) = @_;
60
61   my $pid = $self->_read_pid;
62   return undef unless $pid;
63   return kill('ALRM', $pid) ? 1 : undef;
64 }
65
66 #
67 # private methods
68 #
69
70 sub _read_pid {
71   my ($self) = @_;
72
73   my $exe_dir = SL::System::Process->exe_dir;
74
75   foreach my $conf (qw(kivitendo.conf lx_office.conf kivitendo.conf.default)) {
76     my $pid_file_path = catfile(catdir($exe_dir, splitdir(PID_BASE())), "config.${conf}.pid");
77
78     return join('', read_file($pid_file_path)) * 1 if -f $pid_file_path;
79   }
80 }
81
82 sub _run_script_command {
83   my ($self, $command) = @_;
84
85   my $exe              = catfile(catdir(SL::System::Process->exe_dir, 'scripts'), 'task_server.pl');
86   my $temp_file        = File::Temp->new;
87   my $file_name        = $temp_file->filename;
88
89   $temp_file->close;
90
91   system "${exe} ${command} >> ${file_name} 2>&1";
92
93   $self->last_command_output(read_file($file_name));
94
95   return $? == 0 ? 1 : undef;
96 }
97
98 1;
99 __END__
100
101 =pod
102
103 =encoding utf8
104
105 =head1 NAME
106
107 SL::System::TaskServer - programmatic interface to the external task server component
108
109 =head1 SYNOPSIS
110
111   # Create interface
112   my $task_server = SL->TaskServer->new;
113
114   # Start the server if it is not running
115   if (!$task_server->is_running) {
116     $task_server->start;
117   }
118
119   # Stop it if it is running
120   if ($task_server->is_running) {
121     $task_server->stop;
122   }
123
124 =head1 FUNCTIONS
125
126 =over 4
127
128 =item C<is_running>
129
130 Returns C<trueish> if the server is running. This is done by using
131 Perl's C<kill> function with a "signal" of C<0> for the process ID
132 which in turn is read from the daemon's PID file.
133
134 If the PID file is not found or if C<kill> returns a non-successful
135 value then a C<falsish> value is returned.
136
137 =item C<last_command_output>
138
139 Returns the output of the last C<system> command executed, e.g. from a
140 call to L<start> or L<stop>.
141
142 =item C<start>
143
144 Starts the task server. Does not check whether or not it is running,
145 neither before not after trying to start it.
146
147 Returns C<1> if the system command C<./scripts/task_server.pl start>
148 exits with an exit code of C<0> and C<undef> otherwise.
149
150 The command's output can be queried with L<last_command_output>.
151
152 =item C<status>
153
154 Queries the task server status. Returns one of these values:
155
156 =over 4
157
158 =item *
159
160 C<OK> or C<0>: the task server is running and signals can be sent to
161 it.
162
163 =item *
164
165 C<ERR_PID_FILE> or C<-1>: the PID file could not be found or read
166
167 =item *
168
169 C<ERR_PROCESS> or C<-2>: the PID file could was found and read, but
170 it's not possible to send signals to the process, e.g. because it is
171 not running or owned by a different user ID.
172
173 =back
174
175 =item C<stop>
176
177 Stops the task server. Does not check whether or not it is running,
178 neither before not after trying to start it.
179
180 Returns C<1> if the system command C<./scripts/task_server.pl stop>
181 exits with an exit code of C<0> and C<undef> otherwise.
182
183 The command's output can be queried with L<last_command_output>.
184
185 =item C<wake_up>
186
187 Sends a signal to the task server process causing it to wake up and
188 process its job queue immediately.
189
190 Returns C<1> if the signal could be sent and C<undef> otherwise.
191
192 =back
193
194 =head1 BUGS
195
196 Nothing here yet.
197
198 =head1 AUTHOR
199
200 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
201
202 =cut