Implement graceful shutdown for background task runner #2451

This commit is contained in:
Kijin Sung 2025-05-21 19:04:45 +09:00
parent 8014413163
commit bacf067f87
2 changed files with 58 additions and 1 deletions

View file

@ -11,6 +11,7 @@ class Queue
* Static properties.
*/
protected static $_drivers = [];
protected static $_signal = 0;
/**
* Priority constants.
@ -346,6 +347,11 @@ class Queue
foreach ($tasks as $task)
{
self::_executeTask($task);
if (self::signalReceived())
{
return;
}
}
}
if ($index === 1 || $count < 2)
@ -356,6 +362,11 @@ class Queue
{
$db_driver->updateLastRunTimestamp($task);
self::_executeTask($task);
if (self::signalReceived())
{
return;
}
}
}
@ -368,6 +379,11 @@ class Queue
if ($task)
{
self::_executeTask($task);
if (self::signalReceived())
{
return;
}
}
// If the timeout is imminent, break the loop.
@ -383,6 +399,12 @@ class Queue
{
usleep(intval((1 - $loop_elapsed_time) * 1000000));
}
// Check for a signal again after the sleep.
if (self::signalReceived())
{
break;
}
}
}
@ -488,4 +510,26 @@ class Queue
]));
}
}
/**
* Signal handler.
*
* @param int $signal
* @param mixed $siginfo
* @return void
*/
public static function signalHandler(int $signal, $siginfo): void
{
self::$_signal = $signal;
}
/**
* Has a signal been received?
*
* @return int
*/
public static function signalReceived(): int
{
return self::$_signal;
}
}

View file

@ -52,6 +52,19 @@ if (PHP_SAPI !== 'cli')
}
}
// Set up a signal handler.
if (PHP_SAPI === 'cli' && function_exists('pcntl_signal'))
{
if (function_exists('pcntl_async_signals'))
{
pcntl_async_signals(true);
}
foreach ([SIGINT, SIGHUP, SIGTERM, SIGQUIT, SIGUSR1, SIGUSR2] as $signal)
{
pcntl_signal($signal, [Rhymix\Framework\Queue::class, 'signalHandler']);
}
}
// Create multiple processes if configured.
if (PHP_SAPI === 'cli' && $process_count > 1 && function_exists('pcntl_fork') && function_exists('pcntl_waitpid'))
{
@ -84,7 +97,7 @@ if (PHP_SAPI === 'cli' && $process_count > 1 && function_exists('pcntl_fork') &&
}
// The parent process waits for its children to finish.
while (count($pids))
while (count($pids) && !Rhymix\Framework\Queue::signalReceived())
{
$pid = pcntl_waitpid(-1, $status, \WNOHANG);
if ($pid)