Passed
Push — develop ( b7c00c...da1f69 )
by Nikolay
08:07 queued 01:43
created

WorkerBase::signalHandler()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 1
1
<?php
2
/*
3
 * Copyright © MIKO LLC - All Rights Reserved
4
 * Unauthorized copying of this file, via any medium is strictly prohibited
5
 * Proprietary and confidential
6
 * Written by Alexey Portnov, 9 2020
7
 */
8
9
namespace MikoPBX\Core\Workers;
10
11
use MikoPBX\Core\Asterisk\AsteriskManager;
12
use MikoPBX\Core\System\BeanstalkClient;
13
use MikoPBX\Core\System\Util;
14
use MikoPBX\Core\System\Processes;
15
use Phalcon\Di;
16
use Phalcon\Text;
17
18
abstract class WorkerBase extends Di\Injectable implements WorkerInterface
19
{
20
    public int $currentProcId = 1;
21
    protected AsteriskManager $am;
22
    protected int $maxProc = 1;
23
    protected bool $needRestart = false;
24
25
    /**
26
     * Workers shared constructor
27
     */
28
    public function __construct()
29
    {
30
        pcntl_async_signals(true);
31
        pcntl_signal(
32
            SIGUSR1,
33
            [$this, 'signalHandler']
34
        );
35
36
        $this->checkCountProcesses();
37
        $this->savePidFile();
38
    }
39
40
    /**
41
     * Calculates how many processes have started already and kill excess or old processes
42
     */
43
    private function checkCountProcesses(): void
44
    {
45
        //TODO:: Мешает отладке, позже включу
46
47
        // $activeAnotherProcesses = Processes::getPidOfProcess(static::class, getmypid());
48
        // $processes              = explode(' ', $activeAnotherProcesses);
49
        // if (empty($processes[0])) {
50
        //     array_shift($processes);
51
        // }
52
        // $countProc = count($processes) + 1;
53
        // $killApp   = Util::which('kill');
54
        // if ($this->maxProc === 1 && $countProc > 1) {
55
        //     // Kill old processes with timeout, maybe it is soft restart and worker die without any help
56
        //     Processes::mwExec("{$killApp} SIGUSR1 {$activeAnotherProcesses}");
57
        // } elseif ($this->maxProc > $countProc) {
58
        //     // Start additional processes
59
        //     while ($countProc < $this->maxProc) {
60
        //         sleep(3);
61
        //         Processes::processPHPWorker(static::class, 'start', 'multiStart');
62
        //         $countProc++;
63
        //     }
64
        // } elseif ($this->maxProc < $countProc) {
65
        //     // Получим количество лишних процессов.
66
        //     $countProc4Kill = $countProc - $this->maxProc;
67
        //     // Завершим лишние
68
        //     while ($countProc4Kill >= 0) {
69
        //         if ( ! isset($processes[$countProc4Kill])) {
70
        //             break;
71
        //         }
72
        //         // Kill old processes with timeout, maybe it is soft restart and worker die without any help
73
        //         Processes::mwExec("{$killApp} SIGUSR1 {$processes[$countProc4Kill]}");
74
        //         $countProc4Kill--;
75
        //     }
76
        // }
77
    }
78
79
    /**
80
     * Saves pid to pidfile
81
     */
82
    private function savePidFile(): void
83
    {
84
        $activeProcesses = Processes::getPidOfProcess(static::class);
85
        $processes       = explode(' ', $activeProcesses);
86
        if (count($processes) === 1) {
87
            file_put_contents($this->getPidFile(), $activeProcesses);
88
        } else {
89
            $pidFilesDir = dirname($this->getPidFile());
90
            $pidFile     = $pidFilesDir . '/' . pathinfo($this->getPidFile(), PATHINFO_BASENAME);
91
            // Delete old PID files
92
            $rm = Util::which('rm');
93
            Processes::mwExec("{$rm} -rf {$pidFile}*");
94
            $i = 1;
95
            foreach ($processes as $process) {
96
                file_put_contents("{$pidFile}-{$i}.pid", $process);
97
                $i++;
98
            }
99
        }
100
    }
101
102
    /**
103
     * Create PID file for worker
104
     */
105
    public function getPidFile(): string
106
    {
107
        $name = str_replace("\\", '-', static::class);
108
109
        return "/var/run/{$name}.pid";
110
    }
111
112
    /**
113
     * Process async system signal
114
     *
115
     */
116
    public function signalHandler($signal): void
0 ignored issues
show
Unused Code introduced by
The parameter $signal is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

116
    public function signalHandler(/** @scrutinizer ignore-unused */ $signal): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
117
    {
118
        $this->needRestart = true;
119
    }
120
121
    /**
122
     * Ping callback for keep alive check
123
     *
124
     * @param BeanstalkClient $message
125
     */
126
    public function pingCallBack(BeanstalkClient $message): void
127
    {
128
        $message->reply(json_encode($message->getBody() . ':pong'));
129
    }
130
131
    /**
132
     * If it was Ping request to check worker, we answer Pong and return True
133
     *
134
     * @param $parameters
135
     *
136
     * @return bool
137
     */
138
    public function replyOnPingRequest($parameters): bool
139
    {
140
        $pingTube = $this->makePingTubeName(static::class);
141
        if ($pingTube === $parameters['UserEvent']) {
142
            $this->am->UserEvent("{$pingTube}Pong", []);
143
144
            return true;
145
        }
146
147
        return false;
148
    }
149
150
    /**
151
     * Makes ping tube from classname and ping word
152
     *
153
     * @param string $workerClassName
154
     *
155
     * @return string
156
     */
157
    public function makePingTubeName(string $workerClassName): string
158
    {
159
        return Text::camelize("ping_{$workerClassName}", '\\');
160
    }
161
162
    /**
163
     * Deletes old PID files
164
     */
165
    public function __destruct()
166
    {
167
        $pidFilesDir = dirname($this->getPidFile());
168
        $pidFile     = $pidFilesDir . '/' . pathinfo($this->getPidFile(), PATHINFO_BASENAME);
169
        // Delete old PID files
170
        $rm = Util::which('rm');
171
        Processes::mwExec("{$rm} -rf {$pidFile}*");
172
    }
173
}