NAME
Proc::tored::Manager - OO interface to creating a proctored service
VERSION
version 0.07
SYNOPSIS
my $proctor = Proc::tored::Manager->new(dir => '/tmp', name => 'my-service');
# Call do_stuff while the service is running or until do_stuff returns false
$proctor->service(\&do_stuff)
or die sprintf('process %d is already running this service!', $proctor->running_pid);
# Signal another process running this service to quit gracefully, throwing an
# error if it does not self-terminate after 15 seconds.
if (my $pid = $proctor->stop_running_process(15)) {
die "process $pid is being stubborn!";
}
DESCRIPTION
Objective interface for creating and managing a proctored service.
METHODS
new
Creates a new service object, which can be used to run the service and/or signal another process to quit. The pid file is not created or accessed by this method.
- name
-
The file name to be used when creating or accessing the service's associated pid file.
- dir
-
A valid directory path where the pid file is to be created or an existing pid file is to be found.
- term_file
-
A touch file is used to signal a process to self-terminate. The path to this file is automatically constructed from "name" in "dir" unless manually specified.
- lock_file
-
Before writing the pid file, a lock is secured through the atomic creation of a lock file. If the file fails to be created (with O_EXCL), the lock fails.
- pid_file
-
Unless manually specified, the pid file's
pid_file
is constructed from "name" in "dir".
is_running
See "is_running" in Proc::tored::Role::Running.
service
Accepts a code ref which will be called repeatedly until it or "is_running" return false.
Example using a pool of forked workers, an imaginary task queue, and a secondary condition that decides whether to stop running (aside from the built-in signal handlers):
$proctor->service(sub {
# Wait for an available worker, but with a timeout
my $worker = $worker_pool->next_available(0.1);
if ($worker) {
# Pull next task from the queue with a 0.1s timeout
my $task = poll_queue_with_timeout(0.1);
if ($task) {
$worker->assign($task);
}
}
return unless touch_file_exists();
return 1;
});
read_pid
Returns the pid identified in the pid file. Returns 0 if the pid file does not exist or is empty.
running_pid
Returns the pid of an already-running process or 0 if the pid file does not exist, is empty, or the process identified by the pid does not exist or is not visible.
stop_running_process
Signals a running instance to self-terminate. Returns 0 immediately if the pid file does not exist or is empty. Otherwise, polls the running process until the OS reports that it is no longer able to receive signals (with `kill(0, $pid)`).
Optional parameter $timeout
may be specified in fractional seconds, causing stop_running_process
to block up to (around) $timeout
seconds waiting for the signaled process to exit. Optional parameter $sleep
specifies the interval between polls in fractional seconds.
Returns the pid of the completed process otherwise.
$service->stop_running_process; # signal running process and return
$service->stop_running_process(10, 0.5); # signal, then poll every 0.5s for 10s
run_lock
Attempts to atomically acquire the run lock. Once held, the pid file is created (if needed) and the current process' pid is written to it, "is_running" will return true and a signal handlers will be active. Existing handlers will be executed after the one assigned for the run lock.
If the lock is acquired, a Guard object is returned that will release the lock once out of scope. Returns undef otherwise.
"service" is preferred to this method for most uses.
AUTHOR
Jeff Ober <jeffober@gmail.com>
COPYRIGHT AND LICENSE
This software is copyright (c) 2017 by Jeff Ober.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.