Test Failed
Pull Request — master (#93)
by
unknown
24:02
created

RoadRunnerGrpcApplicationRunner::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 29
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 1

Importance

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

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 2
     * @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
    public function __construct(
55
        string $rootPath,
56
        bool $debug = false,
57
        bool $checkEvents = false,
58 2
        ?string $environment = null,
59 2
        string $bootstrapGroup = 'bootstrap-web',
60 2
        string $eventsGroup = 'events-web',
61 2
        string $diGroup = 'di-web',
62 2
        string $diProvidersGroup = 'di-providers-web',
63 2
        string $diDelegatesGroup = 'di-delegates-web',
64 2
        string $diTagsGroup = 'di-tags-web',
65 2
        string $paramsGroup = 'params-web',
66 2
        array $nestedParamsGroups = ['params'],
67 2
        array $nestedEventsGroups = ['events'],
68 2
    ) {
69 2
        parent::__construct(
70 2
            $rootPath,
71 2
            $debug,
72 2
            $checkEvents,
73
            $environment,
74
            $bootstrapGroup,
75 1
            $eventsGroup,
76
            $diGroup,
77 1
            $diProvidersGroup,
78
            $diDelegatesGroup,
79
            $diTagsGroup,
80
            $paramsGroup,
81
            $nestedParamsGroups,
82
            $nestedEventsGroups,
83 1
        );
84 1
    }
85
86
    /**
87 1
     * @return void
88 1
     * @throws ContainerExceptionInterface
89 1
     * @throws ErrorException
90
     * @throws NotFoundExceptionInterface
91
     * @throws \ErrorException
92
     * @throws InvalidConfigException
93
     */
94
    public function run(): void
95
    {
96
        // Register temporary error handler to catch error while container is building.
97 1
        $temporaryErrorHandler = $this->createTemporaryErrorHandler();
98
        $this->registerErrorHandler($temporaryErrorHandler);
99 1
100 1
        $container = $this->getContainer();
101
102 1
        // Register error handler with real container-configured dependencies.
103
        /** @var ErrorHandler $actualErrorHandler */
104
        $actualErrorHandler = $container->get(ErrorHandler::class);
105
        $this->registerErrorHandler($actualErrorHandler, $temporaryErrorHandler);
106
107
        $this->runBootstrap();
108
        $this->checkEvents();
109
110
        $server = new Server($this->getInvoker(), ['debug' => $this->debug]);
111
112
        /**
113
         * @var class-string<ServiceInterface> $interface
114
         */
115
        foreach ($this->getServices() as $interface) {
116
            /** @var ServiceInterface $service */
117 2
            $service = $container->get($interface);
118
            $server->registerService($interface, $service);
119 2
        }
120
121 2
        $server->serve($this->getWorker(), finalize: function () use ($container) {
122
            $this->afterRespond($container);
123
        });
124 2
    }
125
126 2
    /**
127
     * @return ErrorHandler
128
     */
129 1
    private function createTemporaryErrorHandler(): ErrorHandler {
130
        if ($this->temporaryErrorHandler !== null) {
131 1
            return $this->temporaryErrorHandler;
132
        }
133
134 1
        $logger = new Logger([new FileTarget("$this->rootPath/runtime/logs/grpc.log")]);
135
        return new ErrorHandler($logger, new PlainTextRenderer());
136 1
    }
137
138
    /**
139
     * @throws ErrorException
140
     */
141
    private function registerErrorHandler(ErrorHandler $registered, ErrorHandler $unregistered = null): void {
142
        $unregistered?->unregister();
143
144
        if ($this->debug) {
145
            $registered->debug();
146
        }
147
148
        $registered->register();
149
    }
150
151
    /**
152
     * @param ContainerInterface $container
153
     * @return void
154
     * @throws ContainerExceptionInterface
155
     * @throws NotFoundExceptionInterface
156
     */
157
    private function afterRespond(ContainerInterface $container): void {
158
        /** @psalm-suppress MixedMethodCall */
159
        $container->get(StateResetter::class)->reset();
160
        gc_collect_cycles();
161
    }
162
163
    /**
164
     * Returns a new instance with the specified gRPC worker instance
165
     *
166
     * @return $this
167
     */
168
    public function withWorker(Worker $worker): self
169
    {
170
        $instance = clone $this;
171
        $instance->worker = $worker;
172
173
        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
    public function setServices(array $services): self
189
    {
190
        $this->services = $services;
191
192
        return $this;
193
    }
194
195
    public function getServices(): array
196
    {
197
        return $this->services;
198
    }
199
200
    public function getWorker(): Worker
201
    {
202
        return $this->worker ?? Worker::create();
203
    }
204
205
    public function getInvoker(): InvokerInterface
206
    {
207
        return $this->invoker ?? new Invoker();
208
    }
209
}
210