Added pidfile parameter and refactored DaemonCommand

- Introduced a new 'pidfile' parameter in the services configuration
- Refactored DaemonCommand to use ContainerBagInterface instead of KernelInterface for better flexibility
- Updated file operations in DaemonCommand to use the newly introduced 'pidfile' parameter
- Added a new HealthCommand class with functionality to check the health of the application
- Removed redundant health check logic from SiteController, now using HealthCommand for this purpose
- Enhanced DaemonHelpers service by adding constructor dependencies and integrating it with ParameterBagInterface and ManagerRegistry
This commit is contained in:
Jeroen De Meerleer 2024-12-12 16:27:31 +01:00
parent d1056ae897
commit 121baa44e6
Signed by: JeroenED
GPG Key ID: 28CCCB8F62BFADD6
7 changed files with 79 additions and 18 deletions

View File

@ -1,4 +1,8 @@
# Changelog
## NEXT
### Changed
* Added new health command for daemon-only instances
## Version 1.2
### New
* Added timed scheduled runs

View File

@ -4,6 +4,7 @@
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
parameters:
pidfile: '%kernel.cache_dir%/webcron.pid'
enabled_locales:
en: 'English'
nl: 'Nederlands'

View File

@ -11,17 +11,18 @@ use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface;
use Symfony\Component\HttpKernel\KernelInterface;
#[AsCommand(name: 'webcron:daemon', description: 'The master script of Webcron Management')]
class DaemonCommand extends Command
{
protected KernelInterface $kernel;
protected ContainerBagInterface $containerBag;
protected ManagerRegistry $doctrine;
public function __construct(KernelInterface $kernel, ManagerRegistry $doctrine)
public function __construct(ContainerBagInterface $containerBag, ManagerRegistry $doctrine)
{
$this->kernel = $kernel;
$this->containerBag = $containerBag;
$this->doctrine = $doctrine;
parent::__construct();
@ -49,7 +50,7 @@ class DaemonCommand extends Command
throw new \InvalidArgumentException('Time limit has incorrect value');
}
$jobRepo->unlockJob();
file_put_contents($this->kernel->getCacheDir() . '/daemon-running.lock', time());
file_put_contents($this->containerBag->get('pidfile'), time());
while(1) {
if($endofscript !== false && time() > $endofscript) break;
@ -89,7 +90,7 @@ class DaemonCommand extends Command
}
}
$this->doctrine->getManager()->clear();
file_put_contents($this->kernel->getCacheDir() . '/daemon-running.lock', time());
file_put_contents($this->containerBag->get('pidfile'), time());
$maxwait = time() + 30;
$nextrun = max($jobRepo->getTimeOfNextRun(), time() + 1);
@ -100,7 +101,7 @@ class DaemonCommand extends Command
$output->writeln('Ended after ' . $timelimit . ' seconds');
pcntl_wait($status);
unlink($this->kernel->getCacheDir() . '/daemon-running.lock');
unlink($this->containerBag->get('pidfile'));
return Command::SUCCESS;
}
}

View File

@ -10,7 +10,6 @@ use Doctrine\DBAL\Connection;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\HttpKernel\KernelInterface;

View File

@ -0,0 +1,40 @@
<?php
namespace App\Command;
use App\Service\DaemonHelpers;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
#[AsCommand(name: 'webcron:health', description: 'Gets the health of the app')]
class HealthCommand extends Command
{
private DaemonHelpers $daemonHelpers;
public function __construct(DaemonHelpers $daemonHelpers)
{
$this->daemonHelpers = $daemonHelpers;
parent::__construct();
}
protected function configure(): void
{
$this
->addOption('human-readable', 'H', InputOption::VALUE_NEGATABLE, 'Provide output in human readable style')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$return = $this->daemonHelpers->healthCheck();
if ($input->getOption('human-readable')) {
$io = new SymfonyStyle($input, $output);
$io->table(['name', 'value'], $return);
} else {
$output->writeln(json_encode($return));
}
return $return['DaemonRunning'] ? Command::SUCCESS : Command::FAILURE;
}
}

View File

@ -16,18 +16,10 @@ class SiteController extends AbstractController
{
#[Route('/health', name: 'health')]
public function healthAction(Request $request, ManagerRegistry $doctrine, KernelInterface $kernel)
public function healthAction(DaemonHelpers $daemonHelpers)
{
$em = $doctrine->getManager();
$jobRepo = $em->getRepository(Job::class);
$return = [
"DaemonRunning" => DaemonHelpers::isProcessRunning($kernel->getCacheDir() . '/daemon-running.lock'),
"JobsTotal" => count($jobRepo->getAllJobs()),
"JobsDue" => count($jobRepo->getJobsDue()),
"JobsRunning" => count($jobRepo->getRunningJobs()),
"JobsFailing" => count($jobRepo->getFailingJobs()),
];
return new JsonResponse($return, $return['DaemonRunning'] ? 200 : 500);
$return = $daemonHelpers->healthCheck();
return $this->json($return, $return['DaemonRunning'] ? Response::HTTP_OK : Response::HTTP_INTERNAL_SERVER_ERROR);
}
#[Route('/favicon.ico', name: 'favicon')]

View File

@ -2,8 +2,18 @@
namespace App\Service;
use App\Entity\Job;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpKernel\KernelInterface;
class DaemonHelpers
{
public function __construct(
private ParameterBagInterface $parameterBag,
private ManagerRegistry $doctrine,
) {}
/**
* https://stackoverflow.com/a/3111757
*
@ -19,4 +29,18 @@ class DaemonHelpers
if (!$return) unlink($pidFile);
return $return;
}
public function healthCheck(): array
{
$em = $this->doctrine->getManager();
$jobRepo = $em->getRepository(Job::class);
$return = [
"DaemonRunning" => DaemonHelpers::isProcessRunning($this->parameterBag->get('pidfile')),
"JobsTotal" => count($jobRepo->getAllJobs()),
"JobsDue" => count($jobRepo->getJobsDue()),
"JobsRunning" => count($jobRepo->getRunningJobs()),
"JobsFailing" => count($jobRepo->getFailingJobs()),
];
return $return;
}
}