Passed
Push — develop ( da1f69...28c097 )
by Nikolay
04:52
created

WorkerApiCommands   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 122
Duplicated Lines 0 %

Importance

Changes 15
Bugs 0 Features 0
Metric Value
wmc 14
eloc 55
c 15
b 0
f 0
dl 0
loc 122
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A checkNeedReload() 0 10 5
A prepareAnswer() 0 21 4
A start() 0 14 3
A registerProcessors() 0 14 1
A getNeedRestartActions() 0 9 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, 10 2020
7
 */
8
9
namespace MikoPBX\PBXCoreREST\Workers;
10
11
use MikoPBX\Core\System\{BeanstalkClient, System, Util, Processes};
12
use MikoPBX\Core\Workers\WorkerBase;
13
use MikoPBX\PBXCoreREST\Lib\AdvicesProcessor;
14
use MikoPBX\PBXCoreREST\Lib\CdrDBProcessor;
15
use MikoPBX\PBXCoreREST\Lib\IAXStackProcessor;
16
use MikoPBX\PBXCoreREST\Lib\LicenseManagementProcessor;
17
use MikoPBX\PBXCoreREST\Lib\PbxExtensionsProcessor;
18
use MikoPBX\PBXCoreREST\Lib\SysLogsManagementProcessor;
19
use MikoPBX\PBXCoreREST\Lib\PBXApiResult;
20
use MikoPBX\PBXCoreREST\Lib\SIPStackProcessor;
21
use MikoPBX\PBXCoreREST\Lib\StorageManagementProcessor;
22
use MikoPBX\PBXCoreREST\Lib\SysinfoManagementProcessor;
23
use MikoPBX\PBXCoreREST\Lib\SystemManagementProcessor;
24
use MikoPBX\PBXCoreREST\Lib\FilesManagementProcessor;
25
use Throwable;
26
27
require_once 'Globals.php';
28
29
class WorkerApiCommands extends WorkerBase
30
{
31
    /**
32
     * The maximum parallel worker processes
33
     *
34
     * @var int
35
     */
36
    protected int $maxProc = 2;
37
38
    /**
39
     * Available REST API processors
40
     */
41
    private array $processors;
42
43
44
    /**
45
     * @param $argv
46
     *
47
     */
48
    public function start($argv): void
49
    {
50
        $beanstalk = $this->di->getShared('beanstalkConnectionWorkerAPI');
51
        $beanstalk->subscribe($this->makePingTubeName(self::class), [$this, 'pingCallBack']);
52
        $beanstalk->subscribe(__CLASS__, [$this, 'prepareAnswer']);
53
54
        $this->registerProcessors();
55
56
        while ($this->needRestart === false) {
57
            $beanstalk->wait();
58
        }
59
        if ($this->needRestart){
60
            Processes::processPHPWorker(self::class,'start','restart');
61
            Processes::restartAllWorkers();
62
        }
63
    }
64
65
    /**
66
     * Prepares list of available processors
67
     */
68
    private function registerProcessors(): void
69
    {
70
        $this->processors = [
71
            'advices' => AdvicesProcessor::class,
72
            'cdr'     => CdrDBProcessor::class,
73
            'iax'     => IAXStackProcessor::class,
74
            'license' => LicenseManagementProcessor::class,
75
            'sip'     => SIPStackProcessor::class,
76
            'storage' => StorageManagementProcessor::class,
77
            'system'  => SystemManagementProcessor::class,
78
            'syslog'  => SysLogsManagementProcessor::class,
79
            'sysinfo' => SysinfoManagementProcessor::class,
80
            'files'   => FilesManagementProcessor::class,
81
            'modules' => PbxExtensionsProcessor::class
82
        ];
83
    }
84
85
    /**
86
     * Process API request from frontend
87
     *
88
     * @param BeanstalkClient $message
89
     *
90
     */
91
    public function prepareAnswer(BeanstalkClient $message): void
92
    {
93
        $res            = new PBXApiResult();
94
        $res->processor = __METHOD__;
95
        try {
96
            $request   = json_decode($message->getBody(), true, 512, JSON_THROW_ON_ERROR);
97
            $processor = $request['processor'];
98
99
            if (array_key_exists($processor, $this->processors)) {
100
                $res = $this->processors[$processor]::callback($request);
101
            } else {
102
                $res->success    = false;
103
                $res->messages[] = "Unknown processor - {$processor} in prepareAnswer";
104
            }
105
        } catch (Throwable $exception) {
106
            $res->messages[] = 'Exception on WorkerApiCommands - ' . $exception->getMessage();
107
            $request        = [];
108
        } finally {
109
            $message->reply(json_encode($res->getResult()));
110
            if ($res->success) {
111
                $this->checkNeedReload($request);
112
            }
113
        }
114
115
    }
116
117
    /**
118
     * Checks if the module or worker needs to be reloaded.
119
     *
120
     * @param array $request
121
     */
122
    private function checkNeedReload(array $request): void
123
    {
124
        // Check if new code added from modules
125
        $restartActions = $this->getNeedRestartActions();
126
        foreach ($restartActions as $processor => $actions) {
127
            foreach ($actions as $action) {
128
                if ($processor === $request['processor']
129
                    && $action === $request['action']) {
130
                    $this->needRestart = true;
131
                    return;
132
                }
133
            }
134
        }
135
    }
136
137
    /**
138
     * Prepares array of processor => action depends restart this kind worker
139
     *
140
     * @return array
141
     */
142
    private function getNeedRestartActions(): array
143
    {
144
        return [
145
            'system'  => [
146
                 'enableModule',
147
                 'disableModule',
148
                 'uninstallModule',
149
                 'installNewModule',
150
                 'restoreDefaultSettings',
151
            ],
152
        ];
153
    }
154
155
}
156
157
// Start worker process
158
$workerClassname = WorkerApiCommands::class;
159
if (isset($argv) && count($argv) > 1 && $argv[1] === 'start') {
160
    cli_set_process_title($workerClassname);
161
    while (true) {
162
        try {
163
            $worker = new $workerClassname();
164
            $worker->start($argv);
165
        } catch (Throwable $e) {
166
            global $errorLogger;
167
            $errorLogger->captureException($e);
168
            Util::sysLogMsg("{$workerClassname}_EXCEPTION", $e->getMessage());
169
        }
170
    }
171
}
172