├── tests
├── routing.yml
├── routing_anno.yml
├── bootstrap.php
├── config_test.yml
├── config_test_with_mysql.yml
├── config_test_anno.yml
├── config_test_with_mysql_optional.yml
├── config_test_lazy.yml
├── config_test_with_redis_optional.yml
├── TestKernel.php
├── config_test_travis.yml
├── config_test_with_redis.yml
└── Ekreative
│ └── HealthCheckBundle
│ └── Controller
│ └── HealthCheckControllerTest.php
├── .gitignore
├── src
└── Ekreative
│ └── HealthCheckBundle
│ ├── EkreativeHealthCheckBundle.php
│ ├── Resources
│ └── config
│ │ └── routes.xml
│ ├── DependencyInjection
│ ├── RedisFactory.php
│ ├── Configuration.php
│ └── EkreativeHealthCheckExtension.php
│ └── Controller
│ └── HealthCheckController.php
├── .php-cs-fixer.dist.php
├── phpunit.xml.dist
├── CHANGELOG.md
├── LICENSE
├── .github
└── workflows
│ └── tests.yaml
├── composer.json
└── README.md
/tests/routing.yml:
--------------------------------------------------------------------------------
1 | ekreative_health_check:
2 | resource: '@EkreativeHealthCheckBundle/Resources/config/routes.xml'
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.php_cs.cache
2 | /.phpunit.result.cache
3 | /tests/cache/*
4 | /tests/logs/*
5 | /vendor/
6 | /var/
7 | /.php-cs-fixer.cache
8 |
--------------------------------------------------------------------------------
/tests/routing_anno.yml:
--------------------------------------------------------------------------------
1 | ekreative_health_check:
2 | resource: "@EkreativeHealthCheckBundle/Controller/"
3 | type: attribute
4 | prefix: /
5 |
--------------------------------------------------------------------------------
/src/Ekreative/HealthCheckBundle/EkreativeHealthCheckBundle.php:
--------------------------------------------------------------------------------
1 | in(['src', 'tests'])
5 | ->exclude(['cache']);
6 |
7 | return (new PhpCsFixer\Config())
8 | ->setRules(['@Symfony' => true, 'array_syntax' => ['syntax' => 'short'], 'ordered_imports' => true])
9 | ->setFinder($finder);
10 |
--------------------------------------------------------------------------------
/tests/bootstrap.php:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/tests/config_test.yml:
--------------------------------------------------------------------------------
1 | framework:
2 | test: ~
3 | router:
4 | resource: "%kernel.project_dir%/tests/routing.yml"
5 | strict_requirements: ~
6 | utf8: true
7 | secret: 'fake_secret'
8 | http_method_override: true
9 | php_errors:
10 | log: true
11 |
12 | monolog:
13 | handlers:
14 | main:
15 | type: console
16 |
17 | doctrine:
18 | dbal:
19 | connections:
20 | default:
21 | driver: pdo_sqlite
22 | path: '%kernel.cache_dir%/db.sqlite'
23 |
--------------------------------------------------------------------------------
/tests/config_test_with_mysql.yml:
--------------------------------------------------------------------------------
1 | framework:
2 | test: ~
3 | router:
4 | resource: "%kernel.project_dir%/tests/routing.yml"
5 | strict_requirements: ~
6 | utf8: true
7 | secret: 'fake_secret'
8 |
9 | monolog:
10 | handlers:
11 | main:
12 | type: console
13 |
14 | doctrine:
15 | dbal:
16 | connections:
17 | default:
18 | driver: pdo_mysql
19 | host: 'example.com'
20 | options:
21 | !php/const PDO::ATTR_TIMEOUT: 1
22 |
--------------------------------------------------------------------------------
/tests/config_test_anno.yml:
--------------------------------------------------------------------------------
1 | framework:
2 | test: ~
3 | router:
4 | resource: "%kernel.project_dir%/tests/routing_anno.yml"
5 | strict_requirements: ~
6 | utf8: true
7 | secret: 'fake_secret'
8 |
9 | monolog:
10 | handlers:
11 | main:
12 | type: console
13 |
14 | doctrine:
15 | dbal:
16 | connections:
17 | default:
18 | driver: pdo_sqlite
19 | path: '%kernel.cache_dir%/db.sqlite'
20 |
21 | ekreative_health_check:
22 | redis:
23 | - 'redis'
24 |
25 | services:
26 | redis:
27 | class: Redis
28 | public: true
29 |
--------------------------------------------------------------------------------
/tests/config_test_with_mysql_optional.yml:
--------------------------------------------------------------------------------
1 | framework:
2 | test: ~
3 | router:
4 | resource: "%kernel.project_dir%/tests/routing.yml"
5 | strict_requirements: ~
6 | utf8: true
7 | secret: 'fake_secret'
8 |
9 | monolog:
10 | handlers:
11 | main:
12 | type: console
13 |
14 | doctrine:
15 | dbal:
16 | connections:
17 | default:
18 | driver: pdo_mysql
19 | host: 'example.com'
20 | options:
21 | !php/const PDO::ATTR_TIMEOUT: 1
22 |
23 | ekreative_health_check:
24 | optional_doctrine:
25 | - 'default'
26 |
--------------------------------------------------------------------------------
/tests/config_test_lazy.yml:
--------------------------------------------------------------------------------
1 | framework:
2 | test: ~
3 | router:
4 | resource: "%kernel.project_dir%/tests/routing.yml"
5 | strict_requirements: ~
6 | utf8: true
7 | secret: 'fake_secret'
8 |
9 | monolog:
10 | handlers:
11 | main:
12 | type: console
13 |
14 | doctrine:
15 | dbal:
16 | connections:
17 | default:
18 | driver: pdo_sqlite
19 | path: '%kernel.cache_dir%/db.sqlite'
20 |
21 | ekreative_health_check:
22 | redis:
23 | - 'redis'
24 |
25 | services:
26 | redis:
27 | class: Redis
28 | factory: Ekreative\HealthCheckBundle\Controller\HealthCheckControllerTest::getLazyRedis
29 |
30 |
--------------------------------------------------------------------------------
/tests/config_test_with_redis_optional.yml:
--------------------------------------------------------------------------------
1 | framework:
2 | test: ~
3 | router:
4 | resource: "%kernel.project_dir%/tests/routing.yml"
5 | strict_requirements: ~
6 | utf8: true
7 | secret: 'fake_secret'
8 |
9 | monolog:
10 | handlers:
11 | main:
12 | type: console
13 |
14 | doctrine:
15 | dbal:
16 | connections:
17 | default:
18 | driver: pdo_sqlite
19 | path: '%kernel.cache_dir%/db.sqlite'
20 |
21 | ekreative_health_check:
22 | optional_redis:
23 | - 'redis'
24 |
25 | services:
26 | redis:
27 | class: Redis
28 | factory: Ekreative\HealthCheckBundle\DependencyInjection\RedisFactory::get
29 | arguments:
30 | $host: 'example.com'
31 |
--------------------------------------------------------------------------------
/tests/TestKernel.php:
--------------------------------------------------------------------------------
1 | load($this->getProjectDir().'/tests/config_'.$this->getEnvironment().'.yml');
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/config_test_travis.yml:
--------------------------------------------------------------------------------
1 | framework:
2 | test: ~
3 | router:
4 | resource: "%kernel.project_dir%/tests/routing.yml"
5 | strict_requirements: ~
6 | utf8: true
7 | secret: 'fake_secret'
8 |
9 | monolog:
10 | handlers:
11 | main:
12 | type: console
13 |
14 | doctrine:
15 | dbal:
16 | connections:
17 | default:
18 | driver: pdo_mysql
19 | host: '127.0.0.1'
20 | user: root
21 | options:
22 | !php/const PDO::ATTR_TIMEOUT: 1
23 |
24 | ekreative_health_check:
25 | redis:
26 | - 'redis'
27 |
28 | services:
29 | redis:
30 | class: Redis
31 | factory: Ekreative\HealthCheckBundle\DependencyInjection\RedisFactory::get
32 | arguments:
33 | $host: '127.0.0.1'
34 |
--------------------------------------------------------------------------------
/tests/config_test_with_redis.yml:
--------------------------------------------------------------------------------
1 | framework:
2 | test: ~
3 | router:
4 | resource: "%kernel.project_dir%/tests/routing.yml"
5 | strict_requirements: ~
6 | utf8: true
7 | secret: 'fake_secret'
8 | http_method_override: true
9 | php_errors:
10 | log: true
11 |
12 | monolog:
13 | handlers:
14 | main:
15 | type: console
16 |
17 | doctrine:
18 | dbal:
19 | connections:
20 | default:
21 | driver: pdo_sqlite
22 | path: '%kernel.cache_dir%/db.sqlite'
23 |
24 | ekreative_health_check:
25 | redis:
26 | - 'redis'
27 |
28 | services:
29 | redis:
30 | class: Redis
31 | public: true
32 | factory: Ekreative\HealthCheckBundle\DependencyInjection\RedisFactory::get
33 | arguments:
34 | $host: 'example.com'
35 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | tests/*/*Bundle
16 |
17 |
18 |
19 |
20 | src
21 |
22 |
23 | src/*/*Bundle/Resources
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/Ekreative/HealthCheckBundle/DependencyInjection/RedisFactory.php:
--------------------------------------------------------------------------------
1 | connect($host, $port, $timeout);
21 | if ($prefix) {
22 | $redis->setOption(\Redis::OPT_PREFIX, $prefix);
23 | }
24 | } catch (\RedisException|\ErrorException $e) {
25 | }
26 |
27 | restore_error_handler();
28 |
29 | return $redis;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## 1.12.0
4 |
5 | - Support for Symfony 7
6 |
7 | # 1.11.0
8 |
9 | - Using annotations for routes
10 |
11 | # 1.10.0
12 |
13 | - Allow different Redis classes to be used
14 |
15 | # 1.9.0
16 |
17 | - Support for Symfony 6
18 |
19 | # 1.8.0
20 |
21 | - Dependency updates
22 |
23 | ## 1.7.0
24 |
25 | - Fix default redis port
26 |
27 | This is potentially breaking change, but given its very unlikely someone is
28 | using this wrong default port, I'm going to make it a minor fix.
29 |
30 | ## 1.6.1
31 |
32 | - Fix travis tests
33 |
34 | ## 1.6.0
35 |
36 | - Enable Symfony 5
37 |
38 | ## 1.5.0
39 |
40 | - Change to XML routes file.
41 |
42 | ## 1.4.0
43 |
44 | - Symfony 4.1 deprecations.
45 |
46 | ## 1.3.0
47 |
48 | - Remove dependency on framework-extra-bundle.
49 |
50 | ## 1.2.1
51 |
52 | - Catch all Redis errors.
53 |
54 | ## 1.2.0
55 |
56 | - Inject services into the controller instead of using `container->get`.
57 | - Add redis factory helper class.
58 | - Support for Symfony 4.
59 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017 eKreative
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/.github/workflows/tests.yaml:
--------------------------------------------------------------------------------
1 | name: Tests
2 |
3 | on:
4 | push:
5 | pull_request:
6 |
7 | jobs:
8 | tests:
9 | runs-on: ubuntu-22.04
10 | strategy:
11 | fail-fast: false
12 | matrix:
13 | php: ["8.3"]
14 | symfony: ["5.4", "6.4", "7.0"]
15 | enable-redis: [true, false]
16 | name: PHP ${{ matrix.php }} Symfony ${{ matrix.symfony }} Redis ${{ matrix.enable-redis && 'enabled' || 'disabled' }}
17 | steps:
18 | - uses: actions/checkout@v4
19 | - uses: shivammathur/setup-php@v2
20 | with:
21 | php-version: ${{ matrix.php }}
22 | tools: phpunit-bridge, flex
23 | extensions: "pdo_sqlite ${{ matrix.enable-redis && ', redis' || '' }}"
24 | coverage: none
25 | - run: |
26 | composer config extra.symfony.require ${{ matrix.symfony }}
27 | composer update
28 | - run: vendor/bin/php-cs-fixer fix --dry-run --diff
29 | - run: vendor/bin/phpunit --exclude-group not-${{ matrix.symfony }} ${{ !matrix.enable-redis && '--exclude-group redis' || '' }}
30 | env:
31 | SYMFONY_DEPRECATIONS_HELPER: "disabled=1"
32 |
--------------------------------------------------------------------------------
/src/Ekreative/HealthCheckBundle/DependencyInjection/Configuration.php:
--------------------------------------------------------------------------------
1 | getRootNode();
16 | } else {
17 | // BC layer for symfony/config 4.1 and older
18 | $rootNode = $treeBuilder->root('ekreative_health_check');
19 | }
20 |
21 | $rootNode->children()
22 | ->arrayNode('redis')
23 | ->prototype('scalar')->end()
24 | ->end()
25 | ->arrayNode('optional_redis')
26 | ->prototype('scalar')->end()
27 | ->end()
28 | ->arrayNode('doctrine')
29 | ->prototype('scalar')->end()
30 | ->end()
31 | ->arrayNode('optional_doctrine')
32 | ->prototype('scalar')->end()
33 | ->end()
34 | ->booleanNode('doctrine_enabled')
35 | ->defaultTrue()
36 | ->end()
37 | ->end()
38 | ;
39 |
40 | return $treeBuilder;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ekreative/health-check-bundle",
3 | "license": "MIT",
4 | "type": "symfony-bundle",
5 | "description": "A bundle that provides a simple /healthcheck route",
6 | "keywords": ["healthcheck", "doctrine", "redis"],
7 | "autoload": {
8 | "psr-4": {
9 | "Ekreative\\HealthCheckBundle\\": "src/Ekreative/HealthCheckBundle/"
10 | }
11 | },
12 | "autoload-dev": {
13 | "psr-4": {
14 | "Ekreative\\HealthCheckBundle\\": "tests/Ekreative/HealthCheckBundle/"
15 | },
16 | "classmap": [
17 | "tests/TestKernel.php"
18 | ]
19 | },
20 | "require": {
21 | "php": ">=8.0",
22 | "symfony/framework-bundle": "^5.0|^6.0|^7.0"
23 | },
24 | "suggest": {
25 | "ext-redis": "To use the Redis health check"
26 | },
27 | "require-dev": {
28 | "symfony/phpunit-bridge": "^5.0|^6.0|^7.0",
29 | "doctrine/doctrine-bundle": "^2",
30 | "phpunit/phpunit": "^11",
31 | "friendsofphp/php-cs-fixer": "^3.0",
32 | "symfony/monolog-bundle": "^3.0|^4.0",
33 | "symfony/browser-kit": "^5.0|^6.0|^7.0",
34 | "symfony/yaml": "^5.0|^6.0|^7.0"
35 | },
36 | "authors": [
37 | {
38 | "name": "Fred Cox",
39 | "email": "mcfedr@gmail.com"
40 | }
41 | ],
42 | "config": {
43 | "allow-plugins": {
44 | "composer/package-versions-deprecated": true
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/Ekreative/HealthCheckBundle/DependencyInjection/EkreativeHealthCheckExtension.php:
--------------------------------------------------------------------------------
1 | processConfiguration($configuration, $configs);
18 |
19 | $args = [];
20 | if ($config['doctrine_enabled']) {
21 | $args[] = new Reference('doctrine', ContainerInterface::NULL_ON_INVALID_REFERENCE);
22 | } else {
23 | $args[] = null;
24 | }
25 |
26 | $args[] = $config['doctrine'];
27 | $args[] = $config['optional_doctrine'];
28 |
29 | $args[] = array_map(function ($service) {
30 | return new Reference($service);
31 | }, $config['redis']);
32 |
33 | $args[] = array_map(function ($service) {
34 | return new Reference($service);
35 | }, $config['optional_redis']);
36 |
37 | $def = new Definition(HealthCheckController::class, $args);
38 | $def->addTag('controller.service_arguments');
39 |
40 | $container->addDefinitions([HealthCheckController::class => $def]);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Health Check Bundle
2 |
3 | A bundle that provides a simple `/healthcheck` route
4 |
5 | [](https://packagist.org/packages/ekreative/health-check-bundle)
6 | [](https://packagist.org/packages/ekreative/health-check-bundle)
7 | [](https://travis-ci.org/ekreative/health-check-bundle)
8 |
9 | ## Install
10 |
11 | ### Composer
12 |
13 | ```bash
14 | composer require ekreative/health-check-bundle
15 | ```
16 |
17 | ### AppKernel
18 |
19 | Include the bundle in your AppKernel
20 |
21 | ```php
22 | public function registerBundles()
23 | {
24 | $bundles = [
25 | ...
26 | new Ekreative\HealthCheckBundle\EkreativeHealthCheckBundle(),
27 | ```
28 |
29 | ### Routing
30 |
31 | ```yaml
32 | ekreative_health_check:
33 | resource: '@EkreativeHealthCheckBundle/Resources/config/routes.xml'
34 | ```
35 |
36 | ### Security
37 |
38 | You should make sure `/healthcheck` does not require authentication
39 |
40 | ```yaml
41 | security:
42 | firewalls:
43 | healthcheck:
44 | pattern: ^/healthcheck
45 | security: false
46 | ```
47 |
48 | ## Configuration
49 |
50 | By default healthcheck will check that your default doctrine connection is working.
51 |
52 | ### Doctrine
53 |
54 | To check more than one doctrine connection you should add the configuration, listing
55 | the names of the connections
56 |
57 | ```yaml
58 | ekreative_health_check:
59 | doctrine:
60 | - 'default'
61 | - 'alternative'
62 | ```
63 |
64 | You can also list doctrine connections that should be checked, but don't cause a failure
65 |
66 | ```yaml
67 | ekreative_health_check:
68 | optional_doctrine:
69 | - 'another.optional'
70 | ```
71 |
72 | Its possible to disable the doctrine check
73 |
74 | ```yaml
75 | ekreative_health_check:
76 | doctrine_enabled: false
77 | ```
78 |
79 | #### Timeout
80 |
81 | Its recommended to change the default PDO connection timeout so that your health
82 | check will fail faster
83 |
84 | Add this under connection setting
85 |
86 | ```yaml
87 | doctrine:
88 | dbal:
89 | connections:
90 | default:
91 | driver: pdo_mysql
92 | host: '%database_host%'
93 | options:
94 | !php/const PDO::ATTR_TIMEOUT: 5
95 | ```
96 |
97 | ### Redis
98 |
99 | The bundle can also check that redis connections are working. You should add a list of
100 | service names to check
101 |
102 | This will require the PHP Redis extension enabled.
103 |
104 | ```yaml
105 | ekreative_health_check:
106 | redis:
107 | - 'redis'
108 | ```
109 |
110 | You can also list redis connections that should be checked, but don't cause a failure
111 |
112 | ```yaml
113 | ekreative_health_check:
114 | optional_redis:
115 | - 'redis.optional'
116 | ```
117 |
118 | #### Timeout
119 |
120 | Its recommended to change the default Redis connection timeout so that your health
121 | check will fail faster. Its the third argument to `connect` call for `\Redis`.
122 |
123 | ```yaml
124 | services:
125 | redis:
126 | class: Redis
127 | calls:
128 | - [ connect, ['%redis_host%', '%redis_port%', 5]]
129 | ```
130 |
131 | #### Redis
132 |
133 | When you want redis to be optional, you might want to use the provided `RedisFactory`
134 | (or your own) that catches any exceptions on connect. Without this a Redis failure will
135 | cause the container to fail, resulting in a 500 error.
136 |
137 | ```yaml
138 | services:
139 | redis:
140 | class: Redis
141 | factory: Ekreative\HealthCheckBundle\DependencyInjection\RedisFactory::get
142 | arguments:
143 | $host: 'example.com'
144 | ```
145 |
--------------------------------------------------------------------------------
/src/Ekreative/HealthCheckBundle/Controller/HealthCheckController.php:
--------------------------------------------------------------------------------
1 | doctrine = $doctrine;
42 | $this->connections = $connections;
43 | $this->optionalConnections = $optionalConnections;
44 | $this->redis = $redis;
45 | $this->optionalRedis = $optionalRedis;
46 | }
47 |
48 | #[Route(path: '/healthcheck', name: 'health-check', methods: ['GET'])]
49 | public function healthCheckAction(): Response
50 | {
51 | $data = [
52 | 'app' => true,
53 | ];
54 |
55 | $required = [
56 | 'app' => true,
57 | ];
58 |
59 | if ($this->doctrine) {
60 | $i = 0;
61 | $key = 'database';
62 | if ((count($this->connections) + count($this->optionalConnections)) > 1) {
63 | $key .= "{$i}";
64 | }
65 |
66 | foreach ($this->connections as $name) {
67 | $data[$key] = $required[$key] = $this->checkDoctrineConnection($this->doctrine->getConnection($name));
68 | ++$i;
69 | $key = "database{$i}";
70 | }
71 |
72 | foreach ($this->optionalConnections as $name) {
73 | $data[$key] = $this->checkDoctrineConnection($this->doctrine->getConnection($name));
74 | ++$i;
75 | $key = "database{$i}";
76 | }
77 |
78 | if (!count($this->connections) && !count($this->optionalConnections)) {
79 | $data[$key] = $required[$key] = $this->checkDoctrineConnection($this->doctrine->getConnection());
80 | }
81 | }
82 |
83 | set_error_handler(function ($errno, $errstr, $errfile, $errline) {
84 | // error was suppressed with the @-operator
85 | if (0 === error_reporting()) {
86 | return false;
87 | }
88 |
89 | throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
90 | });
91 |
92 | $i = 0;
93 | $key = 'redis';
94 | if ((count($this->redis) + count($this->optionalRedis)) > 1) {
95 | $key .= "{$i}";
96 | }
97 | foreach ($this->redis as $redis) {
98 | $data[$key] = $required[$key] = $this->checkRedisConnection($redis);
99 | ++$i;
100 | $key = "redis{$i}";
101 | }
102 | foreach ($this->optionalRedis as $redis) {
103 | $data[$key] = $this->checkRedisConnection($redis);
104 | ++$i;
105 | $key = "redis{$i}";
106 | }
107 |
108 | restore_error_handler();
109 |
110 | $ok = array_reduce($required, function ($m, $v) {
111 | return $m && $v;
112 | }, true);
113 |
114 | return new JsonResponse($data, $ok ? 200 : 503);
115 | }
116 |
117 | private function checkDoctrineConnection(Connection $connection): bool
118 | {
119 | try {
120 | return (bool) $connection->executeQuery('SELECT 1');
121 | } catch (\Exception $e) {
122 | return false;
123 | }
124 | }
125 |
126 | private function checkRedisConnection(\Redis|\RedisArray|RedisProxy|\Predis\ClientInterface $redis): bool
127 | {
128 | try {
129 | $redis->ping();
130 |
131 | return true;
132 | } catch (\Exception $e) {
133 | return false;
134 | }
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/tests/Ekreative/HealthCheckBundle/Controller/HealthCheckControllerTest.php:
--------------------------------------------------------------------------------
1 | 'test_travis']);
20 | } else {
21 | // This env uses a sqlite connection
22 | $client = static::createClient();
23 | }
24 |
25 | $client->request('GET', '/healthcheck');
26 |
27 | $this->assertEquals(200, $client->getResponse()->getStatusCode());
28 | $this->assertEquals('application/json', $client->getResponse()->headers->get('content-type'));
29 |
30 | $data = json_decode($client->getResponse()->getContent(), true);
31 |
32 | $this->assertIsArray($data);
33 | $this->assertCount(2, $data);
34 |
35 | $this->assertIsBool($data['app']);
36 | $this->assertTrue($data['app']);
37 |
38 | $this->assertIsBool($data['database']);
39 | $this->assertTrue($data['database']);
40 | }
41 |
42 | #[Group('redis')]
43 | public function testActionWithRedis()
44 | {
45 | if (isset($_ENV['travis'])) {
46 | // This env connects to real redis and mysql servers
47 | $client = static::createClient(['environment' => 'test_travis']);
48 | } else {
49 | // This env uses a sqlite connection and fakes the redis server
50 | $client = static::createClient(['environment' => 'test_with_redis']);
51 |
52 | $redis = $this->getMockBuilder(\Redis::class)
53 | ->onlyMethods(['ping'])
54 | ->getMock();
55 | $redis->method('ping')->willReturn(true);
56 |
57 | $client->getKernel()->getContainer()->set('redis', $redis);
58 | }
59 |
60 | $client->request('GET', '/healthcheck');
61 |
62 | $this->assertEquals(200, $client->getResponse()->getStatusCode());
63 | $this->assertEquals('application/json', $client->getResponse()->headers->get('content-type'));
64 |
65 | $data = json_decode($client->getResponse()->getContent(), true);
66 |
67 | $this->assertIsArray($data);
68 | $this->assertCount(3, $data);
69 |
70 | $this->assertIsBool($data['app']);
71 | $this->assertTrue($data['app']);
72 |
73 | $this->assertIsBool($data['database']);
74 | $this->assertTrue($data['database']);
75 |
76 | $this->assertIsBool($data['redis']);
77 | $this->assertTrue($data['redis']);
78 | }
79 |
80 | public function testMySQLFailAction()
81 | {
82 | $client = static::createClient(['environment' => 'test_with_mysql']);
83 |
84 | $client->request('GET', '/healthcheck');
85 |
86 | $this->assertEquals(503, $client->getResponse()->getStatusCode());
87 | $this->assertEquals('application/json', $client->getResponse()->headers->get('content-type'));
88 |
89 | $data = json_decode($client->getResponse()->getContent(), true);
90 |
91 | $this->assertIsArray($data);
92 | $this->assertCount(2, $data);
93 |
94 | $this->assertIsBool($data['database']);
95 | $this->assertFalse($data['database']);
96 | }
97 |
98 | public function testOptionalMySQLFailAction()
99 | {
100 | $client = static::createClient(['environment' => 'test_with_mysql_optional']);
101 |
102 | $client->request('GET', '/healthcheck');
103 |
104 | $this->assertEquals(200, $client->getResponse()->getStatusCode());
105 | $this->assertEquals('application/json', $client->getResponse()->headers->get('content-type'));
106 |
107 | $data = json_decode($client->getResponse()->getContent(), true);
108 |
109 | $this->assertIsArray($data);
110 | $this->assertCount(2, $data);
111 |
112 | $this->assertIsBool($data['database']);
113 | $this->assertFalse($data['database']);
114 | }
115 |
116 | #[Group('redis')]
117 | public function testRedisFailAction()
118 | {
119 | $client = static::createClient(['environment' => 'test_with_redis']);
120 |
121 | $client->request('GET', '/healthcheck');
122 |
123 | $this->assertEquals(503, $client->getResponse()->getStatusCode());
124 | $this->assertEquals('application/json', $client->getResponse()->headers->get('content-type'));
125 |
126 | $data = json_decode($client->getResponse()->getContent(), true);
127 |
128 | $this->assertIsArray($data);
129 | $this->assertCount(3, $data);
130 |
131 | $this->assertIsBool($data['redis']);
132 | $this->assertFalse($data['redis']);
133 | }
134 |
135 | #[Group('redis')]
136 | public function testOptionalRedisFailAction()
137 | {
138 | $client = static::createClient(['environment' => 'test_with_redis_optional']);
139 |
140 | $client->request('GET', '/healthcheck');
141 |
142 | $this->assertEquals(200, $client->getResponse()->getStatusCode());
143 | $this->assertEquals('application/json', $client->getResponse()->headers->get('content-type'));
144 |
145 | $data = json_decode($client->getResponse()->getContent(), true);
146 |
147 | $this->assertIsArray($data);
148 | $this->assertCount(3, $data);
149 |
150 | $this->assertIsBool($data['redis']);
151 | $this->assertFalse($data['redis']);
152 | }
153 |
154 | public function testLazyAction()
155 | {
156 | $client = static::createClient(['environment' => 'test_lazy']);
157 | $client->request('GET', '/');
158 | $this->assertEquals(404, $client->getResponse()->getStatusCode());
159 | }
160 |
161 | public static function getLazyRedis()
162 | {
163 | throw new \Exception('Should not be called');
164 | }
165 |
166 | #[Group('not-5.4', 'redis')]
167 | public function testAnnoRoutes()
168 | {
169 | // This env uses a sqlite connection and fakes the redis server
170 | $client = static::createClient(['environment' => 'test_anno']);
171 |
172 | $redis = $this->getMockBuilder(\Redis::class)
173 | ->onlyMethods(['ping'])
174 | ->getMock();
175 | $redis->method('ping')->willReturn(true);
176 |
177 | $client->getKernel()->getContainer()->set('redis', $redis);
178 |
179 | $client->request('GET', '/healthcheck');
180 |
181 | $this->assertEquals(200, $client->getResponse()->getStatusCode());
182 | $this->assertEquals('application/json', $client->getResponse()->headers->get('content-type'));
183 | }
184 | }
185 |
--------------------------------------------------------------------------------