NAME

IPC::Manager::Role::Service - Role for implementing IPC services with message handling

DESCRIPTION

This role provides the core functionality for IPC services including:

Message handling (requests/responses)
Peer management and delta detection
Signal handling
Worker process management
Main event loop via the run() method

It composes with IPC::Manager::Role::Service::Select and IPC::Manager::Role::Service::Requests for I/O multiplexing and request/response patterns.

SYNOPSIS

package MyService;
use Role::Tiny::With;
with 'IPC::Manager::Role::Service';

sub new { ... }

sub orig_io { ... }

sub name { ... }

sub run { ... }

sub ipcm_info { ... }

sub pid { ... }

sub set_pid { ... }

sub watch_pids { ... }

sub handle_request { ... }

1;

REQUIRED METHODS

These methods must be implemented by the consuming class:

$inst = $class->new(%params)

Constructor. Must accept parameters for initialization.

$io = $self->orig_io()

Returns a hashref with optional stdout, stderr, or stdin filehandles.

$string = $self->name()

Returns the service name.

$exit = $self->run()

Runs the main event loop. Returns when the service is terminated. Should return an exit code.

$info = $self->ipcm_info()

Returns connection information for the IPC system.

$pid = $self->pid()

Returns the process ID the service is supposed to be confined to.

$self->set_pid($pid)

Sets the process ID (used after fork).

$pids_arrayref = $self->watch_pids()

Returns an arrayref of PIDs to watch. If any terminates, the service exits.

($resp) = $self->handle_request($request, $msg)

Handles an incoming request message.

Should return an empty list if the request is being processed, but no response is ready.

Should return a single item (undef, scalar, or reference) for a response.

If this returns multiple items an exception will be thrown.

METHODS

$self->cycle()

Returns the select cycle time (default: 0.2 seconds).

$self->interval()

Returns the interval for run_on_interval callbacks (default: 0.2 seconds).

$self->use_posix_exit()

Returns whether to use POSIX exit codes (default: 0).

$self->intercept_errors()

Returns whether to intercept and log errors (default: 0).

$self->expose_error_details()

Returns whether exception text from handle_request should be included in error responses. When false (the default), a generic "Internal service error" message is sent. When true, the stringified exception is sent as the ipcm_error value.

$val = $self->terminated()

Gets the termination status.

$self->is_terminated()

Returns true if the service is terminated.

$val = $self->terminate()
$val = $self->terminate($val)

Sets the termination status. If no value is provided then 0 is used. Returns the new value.

$class = $self->peer_class()

Returns the class to use for peer connections (default: IPC::Manager::Service::Peer).

$class = $self->handle_class()

Returns the class to use for handles (default: IPC::Manager::Service::Handle).

@signal_names = $self->signals_to_grab()

Returns a list of signals to intercept (default: empty).

$self->redirect()

Override to redirect I/O. Called during startup. Default implementation is a no-op.

$self->pre_fork_hook()

Override to run code before forking workers. Default implementation is a no-op.

$self->post_fork_hook()

Called in the child process after ipcm_service forks but before the service takes over. Override this to implement a double-fork/daemonize pattern: fork inside the hook, have the middle process do its work and exit within the hook, and let the grandchild return from the hook to become the service.

Default implementation is a no-op.

$self->run_on_all($activity)

Called for every iteration of the service's main loop.

See the "ACTIVITY HASH" for a description of the $activity input.

$self->run_on_cleanup()

Called when the service is shutting down.

$self->run_on_general_message($msg)

Called for messages that are not requests or responses.

$self->run_on_interval()

Called at regular intervals (controlled by interval()).

$self->run_on_peer_delta($delta)

Called when peer connections change. $delta is a hashref showing added/removed peers.

The "ACTIVITY HASH" section shows the structure of the peer_delta as well.

$self->run_on_pid($pid, $exit)

Called when a non-worker child process is reaped by reap_children during the service loop. $pid is the process ID and $exit is the raw $? value captured from waitpid. Worker processes registered via register_worker are handled internally and do not reach this callback.

$self->run_on_sig($sig)

Called when a signal is received. May be called multiple times in rapid succession in a single loop iteration if a signal is recieved more than once.

$self->run_on_start()

Called on startup before the main loop.

$self->run_should_end()

Called to determine if the service should exit. Return true to terminate.

$self->run_on_unhandled($activity)

Called when activity remains unhandled after processing. Dies by default.

See the "ACTIVITY HASH" for a description of the $activity input.

$self->clear_service_fields()

Clears all internal state fields.

$self->register_worker($name, $pid)

Registers a worker process.

$self->workers()

Returns a hashref of worker PIDs to names.

$self->reap_workers()

Reaps terminated worker processes by calling waitpid on each registered worker PID. Used by terminate_workers at shutdown; the main service loop uses reap_children instead.

Returns a hashref of results.

$pids = $self->reap_children()

Calls waitpid(-1, WNOHANG) in a loop to reap any ready child process. For each reaped PID that matches a registered worker the worker is removed from the internal workers hash. For any other PID the pair is collected into a hashref mapping $pid => $exit (the raw $? value), which is returned. $? is localized so the caller's value is not disturbed.

This is called once per iteration of the service loop and is what feeds the pids key of the "ACTIVITY HASH".

$self->send_response($peer, $id, $resp)
$self->send_response($peer, $id, $resp, $error)

Sends a response message to a peer. If $error is provided, the response payload includes an ipcm_error key with the error string.

$client = $self->client()

Returns the client connection for this service.

$self->in_correct_pid()

Verifies we're running in the correct process. Dies if not.

$self->debug(@msg)

Outputs debug messages to the appropriate filehandle.

$self->handle(name => $name, %params)

Creates a new handle for connecting to this service.

$self->peer($name, %params)

Creates a peer connection to another service.

$res = $self->try($cb)

Executes a callback with optional error interception.

$res is a hashref:

{
    ok => $bool,
    err => $string,
    out => ...,
}
$delta = $self->peer_delta(%params)

Returns a hashref showing changes in peer connections.

@handles = $self->select_handles()

Returns a list of filehandles for select().

$activity = $self->watch($sig_seen)

Waits for activity and returns an activity hashref.

See the "ACTIVITY HASH" for a description of the $activity output.

$terminated = $self->run()

Runs the main event loop until terminated. Returns the termination value.

ACTIVITY HASH

The methods that take an activity hash get this structure:

Note that all keys that are not applicable may be omitted.

{
    # Set if the time interval has passed since the last iteration
    interval => $bool,

    # An arrayref of messages, if any
    messages => \@messages,

    # A hashref for peers that have been added or removed, -1 means removed, 1 means added.
    peer_delta => {peer1 => -1, peer3 => 1},

    # True if a wtached pid has exited
    pid_watch => $bool,

    # Hashref of non-worker child pids reaped this iteration mapped to their raw $? exit values
    pids => {pid1 => $exit1, pid2 => $exit2},

    # Hashref of all signals intercepted since the last iteration, plus a count of how many times they were recieved
    sigs => {sig => $count, sig2 => $count2},

    # Set if termination has occured, along with the termination value as a key on the hashref.
    terminated => { value => $value },
}

SOURCE

The source code repository for IPC::Manager can be found at https://github.com/exodist/IPC-Manager.

MAINTAINERS

Chad Granum <exodist@cpan.org>

AUTHORS

Chad Granum <exodist@cpan.org>

COPYRIGHT

Copyright Chad Granum <exodist7@gmail.com>.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

See https://dev.perl.org/licenses/