Passed
Pull Request — master (#93)
by
unknown
23:47
created

RoadRunnerGrpcApplicationRunner::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 29
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 14
c 1
b 0
f 0
nc 1
nop 13
dl 0
loc 29
ccs 15
cts 15
cp 1
crap 1
rs 9.7998

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Runner\RoadRunner;
6
7
use Psr\Container\ContainerExceptionInterface;
8
use Psr\Container\ContainerInterface;
9
use Psr\Container\NotFoundExceptionInterface;
10
use Spiral\RoadRunner\GRPC\Invoker;
11
use Spiral\RoadRunner\GRPC\InvokerInterface;
12
use Spiral\RoadRunner\GRPC\Server;
13
use Spiral\RoadRunner\GRPC\ServiceInterface;
14
use Spiral\RoadRunner\Worker;
15
use Yiisoft\Definitions\Exception\InvalidConfigException;
16
use Yiisoft\Di\StateResetter;
17
use Yiisoft\ErrorHandler\ErrorHandler;
0 ignored issues
show
Bug introduced by
The type Yiisoft\ErrorHandler\ErrorHandler was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
18
use Yiisoft\ErrorHandler\Exception\ErrorException;
19
use Yiisoft\ErrorHandler\Renderer\PlainTextRenderer;
20
use Yiisoft\Log\Logger;
21
use Yiisoft\Log\Target\File\FileTarget;
22
use Yiisoft\Yii\Runner\ApplicationRunner;
23
24
/**
25
 * `RoadRunnerGrpcApplicationRunner` runs the Yii gRPC application using RoadRunner.
26
 */
27
final class RoadRunnerGrpcApplicationRunner extends ApplicationRunner
28
{
29
    private ?ErrorHandler $temporaryErrorHandler = null;
30
    private ?InvokerInterface $invoker = null;
31
    private array $services = [];
32
    private ?Worker $worker = null;
33
34
    /**
35
     * @param string $rootPath The absolute path to the project root.
36
     * @param bool $debug Whether the debug mode is enabled.
37
     * @param bool $checkEvents Whether to check events' configuration.
38
     * @param string|null $environment The environment name.
39
     * @param string $bootstrapGroup The bootstrap configuration group name.
40
     * @param string $eventsGroup The events' configuration group name.
41
     * @param string $diGroup The container definitions' configuration group name.
42
     * @param string $diProvidersGroup The container providers' configuration group name.
43
     * @param string $diDelegatesGroup The container delegates' configuration group name.
44
     * @param string $diTagsGroup The container tags' configuration group name.
45
     * @param string $paramsGroup The configuration parameters group name.
46
     * @param array $nestedParamsGroups Configuration group names that are included into configuration parameters group.
47
     * This is needed for recursive merging of parameters.
48
     * @param array $nestedEventsGroups Configuration group names that are included into events' configuration group.
49
     * This is needed for reverse and recursive merge of events' configurations.
50
     *
51
     * @psalm-param list<string> $nestedParamsGroups
52
     * @psalm-param list<string> $nestedEventsGroups
53
     */
54 2
    public function __construct(
55
        string $rootPath,
56
        bool $debug = false,
57
        bool $checkEvents = false,
58
        ?string $environment = null,
59
        string $bootstrapGroup = 'bootstrap-grpc',
60
        string $eventsGroup = 'events-grpc',
61
        string $diGroup = 'di-grpc',
62
        string $diProvidersGroup = 'di-providers-grpc',
63
        string $diDelegatesGroup = 'di-delegates-grpc',
64
        string $diTagsGroup = 'di-tags-grpc',
65
        string $paramsGroup = 'params-grpc',
66
        array $nestedParamsGroups = ['params'],
67
        array $nestedEventsGroups = ['events'],
68
    ) {
69 2
        parent::__construct(
70 2
            $rootPath,
71 2
            $debug,
72 2
            $checkEvents,
73 2
            $environment,
74 2
            $bootstrapGroup,
75 2
            $eventsGroup,
76 2
            $diGroup,
77 2
            $diProvidersGroup,
78 2
            $diDelegatesGroup,
79 2
            $diTagsGroup,
80 2
            $paramsGroup,
81 2
            $nestedParamsGroups,
82 2
            $nestedEventsGroups,
83 2
        );
84
    }
85
86
    /**
87
     * @return void
88
     * @throws ContainerExceptionInterface
89
     * @throws ErrorException
90
     * @throws NotFoundExceptionInterface
91
     * @throws \ErrorException
92
     * @throws InvalidConfigException
93
     */
94 1
    public function run(): void
95
    {
96
        // Register temporary error handler to catch error while container is building.
97 1
        $temporaryErrorHandler = $this->createTemporaryErrorHandler();
98 1
        $this->registerErrorHandler($temporaryErrorHandler);
99
100 1
        $container = $this->getContainer();
101
102
        // Register error handler with real container-configured dependencies.
103
        /** @var ErrorHandler $actualErrorHandler */
104 1
        $actualErrorHandler = $container->get(ErrorHandler::class);
105 1
        $this->registerErrorHandler($actualErrorHandler, $temporaryErrorHandler);
106
107 1
        $this->runBootstrap();
108 1
        $this->checkEvents();
109
110 1
        $server = new Server($this->getInvoker(), ['debug' => $this->debug]);
111
112
        /**
113
         * @var class-string<ServiceInterface> $interface
114
         */
115 1
        foreach ($this->getServices() as $interface) {
116
            /** @var ServiceInterface $service */
117 1
            $service = $container->get($interface);
118 1
            $server->registerService($interface, $service);
119
        }
120
121 1
        $server->serve($this->getWorker(), finalize: function () use ($container) {
122 1
            $this->afterRespond($container);
123 1
        });
124
    }
125
126
    /**
127
     * @return ErrorHandler
128
     */
129 1
    private function createTemporaryErrorHandler(): ErrorHandler {
130 1
        if ($this->temporaryErrorHandler !== null) {
131
            return $this->temporaryErrorHandler;
132
        }
133
134 1
        $logger = new Logger([new FileTarget("$this->rootPath/runtime/logs/grpc.log")]);
135 1
        return new ErrorHandler($logger, new PlainTextRenderer());
136
    }
137
138
    /**
139
     * @throws ErrorException
140
     */
141 1
    private function registerErrorHandler(ErrorHandler $registered, ErrorHandler $unregistered = null): void {
142 1
        $unregistered?->unregister();
143
144 1
        if ($this->debug) {
145
            $registered->debug();
146
        }
147
148 1
        $registered->register();
149
    }
150
151
    /**
152
     * @param ContainerInterface $container
153
     * @return void
154
     * @throws ContainerExceptionInterface
155
     * @throws NotFoundExceptionInterface
156
     */
157 1
    private function afterRespond(ContainerInterface $container): void {
158
        /** @psalm-suppress MixedMethodCall */
159 1
        $container->get(StateResetter::class)->reset();
160 1
        gc_collect_cycles();
161
    }
162
163
    /**
164
     * Returns a new instance with the specified gRPC worker instance
165
     *
166
     * @return $this
167
     */
168 1
    public function withWorker(Worker $worker): self
169
    {
170 1
        $instance = clone $this;
171 1
        $instance->worker = $worker;
172
173 1
        return $instance;
174
    }
175
176
    /**
177
     * Transmitted services for registration gRPC server
178
     *
179
     * @param array $services Services array (key-value pairs)
180
     * ```php
181
     * [
182
     *      ServiceInterface::class
183
     * ]
184
     * ```
185
     *
186
     * @return $this
187
     */
188 2
    public function setServices(array $services): self
189
    {
190 2
        $this->services = $services;
191
192 2
        return $this;
193
    }
194
195 2
    public function getServices(): array
196
    {
197 2
        return $this->services;
198
    }
199
200 1
    public function getWorker(): Worker
201
    {
202 1
        return $this->worker ?? Worker::create();
203
    }
204
205 1
    public function getInvoker(): InvokerInterface
206
    {
207 1
        return $this->invoker ?? new Invoker();
208
    }
209
}
210