Passed
Push — develop ( c32ccc...c40cee )
by Nikolay
05:27
created

WorkerBase   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 123
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 12
eloc 38
c 1
b 0
f 0
dl 0
loc 123
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A savePidFile() 0 16 3
A getPidFile() 0 5 1
A __construct() 0 10 1
A __destruct() 0 3 1
A pingCallBack() 0 3 1
A replyOnPingRequest() 0 10 2
A signalHandler() 0 4 1
A shutdownHandler() 0 4 1
A makePingTubeName() 0 3 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
    protected AsteriskManager $am;
21
    public int $maxProc = 1;
22
    protected bool $needRestart = false;
23
24
    /**
25
     * Workers shared constructor
26
     * Do not remove FINAL there, use START function to add something
27
     */
28
    final public function __construct()
29
    {
30
        pcntl_async_signals(true);
31
        pcntl_signal(
32
            SIGUSR1,
33
            [$this, 'signalHandler'],
34
            false
35
        );
36
        register_shutdown_function( [$this, 'shutdownHandler']);
37
        $this->savePidFile();
38
    }
39
40
    /**
41
     * Saves pid to pidfile
42
     */
43
    private function savePidFile(): void
44
    {
45
        $activeProcesses = Processes::getPidOfProcess(static::class);
46
        $processes       = explode(' ', $activeProcesses);
47
        if (count($processes) === 1) {
48
            file_put_contents($this->getPidFile(), $activeProcesses);
49
        } else {
50
            $pidFilesDir = dirname($this->getPidFile());
51
            $pidFile     = $pidFilesDir . '/' . pathinfo($this->getPidFile(), PATHINFO_BASENAME);
52
            // Delete old PID files
53
            $rm = Util::which('rm');
54
            Processes::mwExec("{$rm} -rf {$pidFile}*");
55
            $i = 1;
56
            foreach ($processes as $process) {
57
                file_put_contents("{$pidFile}-{$i}.pid", $process);
58
                $i++;
59
            }
60
        }
61
    }
62
63
    /**
64
     * Create PID file for worker
65
     */
66
    public function getPidFile(): string
67
    {
68
        $name = str_replace("\\", '-', static::class);
69
70
        return "/var/run/{$name}.pid";
71
    }
72
73
    /**
74
     * Process async system signal
75
     *
76
     */
77
    public function signalHandler(int $signal): void
78
    {
79
        Util::sysLogMsg(static::class, "Receive signal to restart  ".$signal);
80
        $this->needRestart = true;
81
    }
82
83
    /**
84
     * Process shutdown event
85
     *
86
     */
87
    public function shutdownHandler(): void
88
    {
89
        $e = error_get_last();
90
        Util::sysLogMsg(static::class, "shutdownHandler ". print_r($e,true));
91
    }
92
93
94
    /**
95
     * Ping callback for keep alive check
96
     *
97
     * @param BeanstalkClient $message
98
     */
99
    public function pingCallBack(BeanstalkClient $message): void
100
    {
101
        $message->reply(json_encode($message->getBody() . ':pong'));
102
    }
103
104
    /**
105
     * If it was Ping request to check worker, we answer Pong and return True
106
     *
107
     * @param $parameters
108
     *
109
     * @return bool
110
     */
111
    public function replyOnPingRequest($parameters): bool
112
    {
113
        $pingTube = $this->makePingTubeName(static::class);
114
        if ($pingTube === $parameters['UserEvent']) {
115
            $this->am->UserEvent("{$pingTube}Pong", []);
116
117
            return true;
118
        }
119
120
        return false;
121
    }
122
123
    /**
124
     * Makes ping tube from classname and ping word
125
     *
126
     * @param string $workerClassName
127
     *
128
     * @return string
129
     */
130
    public function makePingTubeName(string $workerClassName): string
131
    {
132
        return Text::camelize("ping_{$workerClassName}", '\\');
133
    }
134
135
    /**
136
     * Deletes old PID files
137
     */
138
    public function __destruct()
139
    {
140
        $this->savePidFile();
141
    }
142
}