Skip to content
Snippets Groups Projects
Commit 1bbf49d7 authored by Reiter, Christoph's avatar Reiter, Christoph :snake:
Browse files

Add a health check which initializes all services

In some cases where services can't be instantiated, either because the implementation
is missing, or some dependency is missing, or there is a cyclic dep then things would
fail only at the time the service is needed, for example in one specific request.

To avoid missing such errors and catch them early add a health check which tries to
build all services.

This allows us to abort a deployment in case a service is broken.
parent 34440be8
No related branches found
No related tags found
No related merge requests found
Pipeline #98728 passed
...@@ -7,15 +7,20 @@ namespace Dbp\Relay\CoreBundle\HealthCheck\Checks; ...@@ -7,15 +7,20 @@ namespace Dbp\Relay\CoreBundle\HealthCheck\Checks;
use Dbp\Relay\CoreBundle\HealthCheck\CheckInterface; use Dbp\Relay\CoreBundle\HealthCheck\CheckInterface;
use Dbp\Relay\CoreBundle\HealthCheck\CheckOptions; use Dbp\Relay\CoreBundle\HealthCheck\CheckOptions;
use Dbp\Relay\CoreBundle\HealthCheck\CheckResult; use Dbp\Relay\CoreBundle\HealthCheck\CheckResult;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
class SymfonyCheck implements CheckInterface class SymfonyCheck implements CheckInterface
{ {
private $parameters; private $parameters;
/** @var ContainerInterface */
private $container;
public function __construct(ParameterBagInterface $parameters) public function __construct(ParameterBagInterface $parameters, ContainerInterface $container)
{ {
$this->parameters = $parameters; $this->parameters = $parameters;
$this->container = $container;
} }
public function getName(): string public function getName(): string
...@@ -23,6 +28,28 @@ class SymfonyCheck implements CheckInterface ...@@ -23,6 +28,28 @@ class SymfonyCheck implements CheckInterface
return 'core.symfony'; return 'core.symfony';
} }
private function checkAllServices(): CheckResult
{
$result = new CheckResult('Check if all Symfony services can be initialized');
$result->set(CheckResult::STATUS_SUCCESS);
// This catches errors like unimplemented interfaces, cyclic dependencies and so on.
// Otherwise we would only get those errors when the services are actually needed,
// on specific requests/tasks at runtime.
$container = $this->container;
assert($container instanceof Container);
foreach ($container->getServiceIds() as $id) {
try {
$container->get($id);
} catch (\Throwable $e) {
$result->set(CheckResult::STATUS_FAILURE, $e->getMessage(), ['exception' => $e]);
break;
}
}
return $result;
}
private function checkAppSecret(): CheckResult private function checkAppSecret(): CheckResult
{ {
$result = new CheckResult('APP_SECRET should be set'); $result = new CheckResult('APP_SECRET should be set');
...@@ -54,6 +81,7 @@ class SymfonyCheck implements CheckInterface ...@@ -54,6 +81,7 @@ class SymfonyCheck implements CheckInterface
$results = []; $results = [];
$results[] = $this->checkAppSecret(); $results[] = $this->checkAppSecret();
$results[] = $this->checkAppDebug(); $results[] = $this->checkAppDebug();
$results[] = $this->checkAllServices();
return $results; return $results;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment