App-aep
view release on metacpan or search on metacpan
lib/App/aep.pm view on Meta::CPAN
sub lock_trigger_fire
{
my $debug = poe->heap->{ '_' }->{ 'debug' };
my $opt = poe->heap->{ '_' }->{ 'opt' };
# Only fire once
if ( poe->heap->{ 'command' }->{ 'trigger_ok' } )
{
return;
}
poe->heap->{ 'command' }->{ 'trigger_ok' } = 1;
$debug->( 'STDERR', __LINE__, "Lock trigger fired, reporting success to server." );
# Send trigger_ok directly via the wheel (not via yield, to avoid cross-session issues)
if ( poe->heap->{ 'afunixcli' }->{ 'server' }->{ 'wheel' } )
{
my $msg = { 'event' => 'trigger_ok', 'lock_id' => $opt->lock_id };
poe->heap->{ 'afunixcli' }->{ 'server' }->{ 'wheel' }->put( $msg );
$debug->( 'STDERR', __LINE__, "Sent trigger_ok to server." );
}
# If the command has already exited, schedule shutdown after a brief delay
# to allow the trigger_ok message to flush to the server
if ( !poe->heap->{ 'command' }->{ 'running' } )
{
$debug->( 'STDERR', __LINE__, "Trigger fired and command already exited, shutting down shortly." );
poe->heap->{ '_' }->{ 'set_exit' }->( '0', 'trigger-ok-command-exited' );
poe->kernel->delay( 'scheduler' => 0.5 );
}
return;
}
# Attempt a TCP connect for the connect trigger type
sub lock_trigger_connect
{
my $debug = poe->heap->{ '_' }->{ 'debug' };
my $trigger = poe->heap->{ 'command' }->{ 'trigger' };
my $spec = $trigger->{ 'spec' } || '';
# Already triggered
return if poe->heap->{ 'command' }->{ 'trigger_ok' };
# Parse host:port from spec
my ( $host, $port ) = split( /:/, $spec, 2 );
if ( !$host || !$port )
{
$debug->( 'STDERR', __LINE__, "Connect trigger: invalid spec '$spec', expected host:port." );
return;
}
$debug->( 'STDERR', __LINE__, "Connect trigger: trying $host:$port." );
my $ok = try {
my $sock = IO::Socket::INET->new(
PeerAddr => $host,
PeerPort => $port,
Proto => 'tcp',
Timeout => 2,
);
if ( $sock )
{
close( $sock );
return 1;
}
return 0;
}
catch {
return 0;
};
if ( $ok )
{
$debug->( 'STDERR', __LINE__, "Connect trigger: connection to $host:$port succeeded." );
poe->kernel->yield( 'lock_trigger_fire' );
}
else
{
# Retry after 1 second
poe->kernel->delay( 'lock_trigger_connect' => 1 );
}
return;
}
# Run an external script for the script trigger type
sub lock_trigger_script
{
my $debug = poe->heap->{ '_' }->{ 'debug' };
my $trigger = poe->heap->{ 'command' }->{ 'trigger' };
my $spec = $trigger->{ 'spec' } || '';
# Already triggered
return if poe->heap->{ 'command' }->{ 'trigger_ok' };
$debug->( 'STDERR', __LINE__, "Script trigger: running '$spec'." );
# WARNING: system() blocks the event loop. Using alarm() to cap execution time.
my $exit_code;
eval {
local $SIG{ 'ALRM' } = sub { die "script_timeout\n" };
alarm( 30 );
$exit_code = system( $spec );
alarm( 0 );
};
if ( $@ )
{
$debug->( 'STDERR', __LINE__, "Script trigger: '$spec' timed out after 30s." );
$exit_code = -1;
}
if ( $exit_code == 0 )
{
$debug->( 'STDERR', __LINE__, "Script trigger: '$spec' exited 0 (success)." );
poe->kernel->yield( 'lock_trigger_fire' );
}
else
{
$debug->( 'STDERR', __LINE__, "Script trigger: '$spec' exited non-zero, retrying." );
( run in 1.896 second using v1.01-cache-2.11-cpan-39bf76dae61 )