Skip to content

Commit

Permalink
Failover if supervision is not possible
Browse files Browse the repository at this point in the history
  • Loading branch information
Toflar committed Feb 21, 2024
1 parent 53867a5 commit 01c66cf
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 19 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"php": "^8.1",
"symfony/process": "^6.0 || ^7.0",
"symfony/lock": "^6.0 || ^7.0",
"symfony/filesystem": "^6.0 || ^7.0"
"symfony/filesystem": "^6.0 || ^7.0",
"psr/log": "^3.0"
},
"require-dev": {
"phpunit/phpunit": "^10.2",
Expand Down
44 changes: 26 additions & 18 deletions src/Supervisor.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

namespace Toflar\CronjobSupervisor;

use Psr\Log\LoggerInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Lock\LockFactory;
use Symfony\Component\Lock\Store\FlockStore;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;

class Supervisor
Expand All @@ -32,8 +34,10 @@ class Supervisor
*/
private array $childProcesses = [];

public function __construct(private readonly string $storageDirectory)
{
public function __construct(
private readonly string $storageDirectory,
public readonly LoggerInterface|null $logger,
) {
$this->lockFactory = new LockFactory(new FlockStore($storageDirectory));
$this->filesystem = new Filesystem();

Expand Down Expand Up @@ -169,25 +173,29 @@ private function executeLocked(\Closure $closure): void

private function isRunningPid(int $pid): bool
{
if ('\\' === \DIRECTORY_SEPARATOR) {
$process = new Process(['tasklist', '/FI', "PID eq $pid"]);
$process->run();

// Symfony Process starts Windows processes via cmd.exe
return str_contains($process->getOutput(), 'cmd.exe');
}
try {
if ('\\' === \DIRECTORY_SEPARATOR) {
$process = new Process(['tasklist', '/FI', "PID eq $pid"]);
$process->mustRun();

// Symfony Process starts Windows processes via cmd.exe
return str_contains($process->getOutput(), 'cmd.exe');
}

$process = new Process(['ps', '-p', $pid]);
$exitCode = $process->run();
$process = new Process(['ps', '-p', $pid]);
$process->mustRun();

if (0 !== $exitCode) {
return false;
}
// Check for defunct output. If the process was started within this very process,
// it will still be listed, although it's actually finished.
if (str_contains($process->getOutput(), '<defunct>')) {
return false;
}
} catch (ProcessFailedException $e) {
$this->logger?->critical('Could not run supervisor because there are no means to check if a PID is already running: '.$e->getMessage());

// Check for defunct output. If the process was started within this very process,
// it will still be listed, although it's actually finished.
if (str_contains($process->getOutput(), '<defunct>')) {
return false;
// If supervision doesn't work, we simulate a running process -> no new processes
// are started
return true;
}

return true;
Expand Down

0 comments on commit 01c66cf

Please sign in to comment.