Clio

 view release on metacpan or  search on metacpan

lib/Clio/ProcessManager.pm  view on Meta::CPAN


package Clio::ProcessManager;
BEGIN {
  $Clio::ProcessManager::AUTHORITY = 'cpan:AJGB';
}
{
  $Clio::ProcessManager::VERSION = '0.02';
}
# ABSTRACT: Process manager

use strict;
use Moo;

use AnyEvent;
use Clio::Process;
use Carp qw( croak );

with 'Clio::Role::HasContext';
with 'Clio::Role::UUIDMaker';


has 'processes' => (
    is => 'ro',
    default => sub { +{} },
);

has '_check_idle_loop' => (
    is => 'ro',
    init_arg => undef,
    lazy => 1,
    default => sub {
        my $self = shift;
        AnyEvent->timer(
            after    => 2,
            interval => 1,
            cb       => sub {
                $self->_idle_processes_maintenance();
            },
        );
    },
);


sub start {
    my $self = shift;

    my $config = $self->c->config->CommandConfig;
    my $log = $self->c->log;

    $self->_start_num_processes(
        $config->{StartCommands},
        $config->{Exec},
    );
    $self->_check_idle_loop;
}

sub _start_num_processes {
    my ($self, $number, $cmd) = @_;

    return unless $number >= 1;

    my $cv = AnyEvent->condvar;
    $cv->begin;
    for ( 1 .. $number ) {
        $cv->begin;
        my $s; $s = AnyEvent->timer(
            after => 0,
            cb => sub {
                undef $s;
                $self->create_process( $cmd )->start;
                $cv->end;
            }
        );
    }
    $cv->end;
}


sub create_process {
    my ($self, $cmd) = @_;

    my $uuid = $self->create_uuid;
    $self->c->log->debug("Creating process $uuid");

    return $self->processes->{ $uuid } = Clio::Process->new(
        manager => $self,
        id => $uuid,
        command => $cmd,
    );
}


sub get_first_available {
    my ($self, %args) = @_;

    my $config = $self->c->config->CommandConfig;
    my $log = $self->c->log;

    if ( my $client_id = $args{client_id} ) {
        my $clients_manager = $self->c->server->clients_manager;
        if ( my $client = $clients_manager->clients->{ $client_id } ) {
            if ( my $proc = $client->_process ) {
                if ( exists $proc->_clients->{ $client_id } ) {
                    $log->trace("Restored connection from client $client_id");
                    return $proc;
                }
            }
        }
    }

    while ( my ($uuid, $proc) =  each %{ $self->processes } ) {
        if ( ! $config->{MaxClientsPerCommand} ) {
            return $proc;
        }
        elsif ( $proc->clients_count < $config->{MaxClientsPerCommand} ) {
            return $proc;
        }
    }
    if ( $self->total_count < $config->{MaxCommands} ) {
        my $proc = $self->create_process( $config->{Exec} );
        $proc->start;
        return $proc;
    }

    return;
}



( run in 0.518 second using v1.01-cache-2.11-cpan-39bf76dae61 )