DecisionManager::setLogger()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 0
cts 3
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 2
1
<?php
2
3
namespace Innmind\ProvisionerBundle;
4
5
use Innmind\ProvisionerBundle\Server\ServerInterface;
6
use Innmind\ProvisionerBundle\Event\ProvisionEvents;
7
use Innmind\ProvisionerBundle\Event\ProvisionRequirementEvent;
8
use Innmind\ProvisionerBundle\Event\ProvisionEvent;
9
use Innmind\ProvisionerBundle\Event\ProvisionAlertEvent;
10
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
11
use Symfony\Component\Filesystem\LockHandler;
12
use Symfony\Component\Console\Input\InputInterface;
13
use Psr\Log\LoggerInterface;
14
15
/**
16
 * Class acting how many processes can be launched on the server
17
 */
18
class DecisionManager
19
{
20
    protected $server;
21
    protected $cpuThreshold;
22
    protected $processStatus;
23
    protected $dispatcher;
24
    protected $logger;
25
26
    /**
27
     * Set the server helper
28
     *
29
     * @param ServerInterface $server
30
     */
31 3
    public function setServer(ServerInterface $server)
32
    {
33 3
        $this->server = $server;
34 3
    }
35
36
    /**
37
     * Set the CPU top threshold
38
     *
39
     * @param float $threshold
40
     */
41 3
    public function setCpuThreshold($threshold)
42
    {
43 3
        $this->cpuThreshold = (float) $threshold;
44 3
    }
45
46
    /**
47
     * Set the process status handler
48
     *
49
     * @param ProcessStatusHandler $handler
50
     */
51 3
    public function setProcessStatusHandler(ProcessStatusHandler $handler)
52
    {
53 3
        $this->processStatus = $handler;
54 3
    }
55
56
    /**
57
     * Set the event dispatcher
58
     *
59
     * @param EventDispatcherInterface $dispatcher
60
     */
61
    public function setDispatcher(EventDispatcherInterface $dispatcher)
62
    {
63
        $this->dispatcher = $dispatcher;
64
    }
65
66
    /**
67
     * Set the logger
68
     *
69
     * @param LoggerInterface $logger
70
     */
71
    public function setLogger(LoggerInterface $logger)
72
    {
73
        $this->logger = $logger;
74
    }
75
76
    /**
77
     * Return the number of processes that can be launched on the server
78
     *
79
     * @param string $command Command name to analyze
80
     *
81
     * @return int
82
     */
83 3
    public function getAllowedProcesses($command)
84
    {
85 3
        $cpuUsage = $this->server->getCpuUsage();
86
87 3
        $averageProcessUsage = $this->processStatus->getProcessUsage($command);
88 3
        $averageProcessNumber = $this->processStatus->getProcessCount($command);
89
90 3
        if ($cpuUsage >= $this->cpuThreshold) {
91
            return 0;
92
        }
93
94 3
        if ((int) $averageProcessNumber === 0) {
95
            return 1;
96
        }
97
98 3
        $availableCpu = $this->cpuThreshold - $cpuUsage;
99 3
        $processUsage = $averageProcessUsage / $averageProcessNumber;
100
101 3
        return (int) floor($availableCpu / $processUsage);
102
    }
103
104
    /**
105
     * Instruct the bundle to run all the process it can
106
     * and dispatch alerts if necessary
107
     *
108
     * @param string $name Symfony command name being run
109
     * @param InputInterface $input Command input arguments
110
     */
111
    public function provision($name, InputInterface $input)
112
    {
113
        $lockHandler = new LockHandler(sprintf(
114
            'provision.%s.lock',
115
            preg_replace('/[:\/]/', '-', $name)
116
        ));
117
118
        if (!$lockHandler->lock()) {
119
            return;
120
        }
121
122
        if ($this->logger) {
123
            $this->logger->info(
124
                'Starting provisioning',
125
                ['command' => $name, 'input' => (string) $input]
126
            );
127
        }
128
129
        $event = new ProvisionRequirementEvent($name, $input);
130
        $this->dispatcher->dispatch(
131
            ProvisionEvents::COMPUTE_REQUIREMENTS,
132
            $event
133
        );
134
135
        $required = $event->getRequiredProcesses();
136
137
        $command = sprintf(
138
            'console %s',
139
            (string) $input
140
        );
141
142
        $allowed = $this->getAllowedProcesses($command);
143
144
        if ($required > $allowed) {
145
            $toRun = $allowed;
146
            $leftOver = $required - $allowed;
147
        } else {
148
            $toRun = $required;
149
            $leftOver = 0;
150
        }
151
152
        $this->dispatcher->dispatch(
153
            ProvisionEvents::PROVISION,
154
            new ProvisionEvent($name, $input, $toRun)
155
        );
156
        $this->dispatcher->dispatch(
157
            ProvisionEvents::ALERT,
158
            new ProvisionAlertEvent($name, $input, $leftOver)
159
        );
160
161
        if ($this->logger) {
162
            $this->logger->info(
163
                'Finished provisioning',
164
                [
165
                    'command' => $name,
166
                    'input' => (string) $input,
167
                    'processes_spawned' => $toRun,
168
                    'left_overs' => $leftOver,
169
                ]
170
            );
171
        }
172
173
        $lockHandler->release();
174
    }
175
}
176