Passed
Pull Request — master (#3697)
by
unknown
65:37
created

PingCommand::ping()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 8
c 1
b 0
f 0
dl 0
loc 14
rs 10
cc 3
nc 4
nop 2
1
<?php
2
3
namespace Doctrine\DBAL\Tools\Console\Command;
4
5
use Doctrine\DBAL\Connection;
6
use RuntimeException;
7
use Symfony\Component\Console\Command\Command;
8
use Symfony\Component\Console\Input\InputInterface;
9
use Symfony\Component\Console\Input\InputOption;
10
use Symfony\Component\Console\Output\OutputInterface;
11
use Throwable;
12
use function is_numeric;
13
use function sleep;
14
use function sprintf;
15
16
class PingCommand extends Command
17
{
18
    /**
19
     * {@inheritdoc}
20
     */
21
    protected static $defaultName = 'dbal:ping';
22
23
    protected function configure()
24
    {
25
        $this
26
            ->setDescription('Check db is available')
27
            ->addOption('limit', null, InputOption::VALUE_REQUIRED, 'Max number of pings to try', '1')
28
            ->addOption('sleep', null, InputOption::VALUE_REQUIRED, 'Length of time (seconds) to sleep between pings', '1')
29
            ->setHelp(<<<EOT
30
Connects to the database to check if it is accessible.
31
32
The exit code will be non-zero when the connection fails.
33
EOT
34
            );
35
    }
36
37
    protected function execute(InputInterface $input, OutputInterface $output) : int
38
    {
39
        $limit = $input->getOption('limit');
40
        if (! is_numeric($limit) || $limit < 0) {
41
            throw new RuntimeException('Option "limit" must contain a positive integer value');
42
        }
43
        $sleep = $input->getOption('sleep');
44
        if (! is_numeric($sleep) || $sleep < 0) {
45
            throw new RuntimeException('Option "sleep" must contain a positive integer value');
46
        }
47
48
        return $this->waitForPing($this->getHelper('db')->getConnection(), (int) $limit, (int) $sleep, $output);
49
    }
50
51
    /**
52
     * @return int > 0 for error
53
     */
54
    private function waitForPing(Connection $conn, int $limit, int $sleep, OutputInterface $output) : int
55
    {
56
        while (true) {
57
            $last = $this->ping($conn, $output);
58
            if ($last === 0 || --$limit <= 0) {
59
                break;
60
            }
61
            sleep($sleep);
62
        }
63
64
        return $last;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $last does not seem to be defined for all execution paths leading up to this point.
Loading history...
65
    }
66
67
    /**
68
     * @return int > 0 for error
69
     */
70
    private function ping(Connection $conn, OutputInterface $output) : int
71
    {
72
        try {
73
            if ($conn->ping()) {
74
                return 0;
75
            }
76
77
            $output->writeln('Ping failed');
78
79
            return 1;
80
        } catch (Throwable $e) {
81
            $output->writeln(sprintf('Ping failed: <error>%s</error>', $e->getMessage()));
82
83
            return 2;
84
        }
85
    }
86
}
87