Passed
Pull Request — master (#190)
by Dmitriy
02:42
created

Worker::process()   B

Complexity

Conditions 6
Paths 14

Size

Total Lines 35
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 7.6796

Importance

Changes 0
Metric Value
cc 6
eloc 25
nc 14
nop 2
dl 0
loc 35
ccs 16
cts 25
cp 0.64
crap 7.6796
rs 8.8977
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Queue\Worker;
6
7
use Closure;
8
use Psr\Container\ContainerInterface;
9
use Psr\Log\LoggerInterface;
10
use RuntimeException;
11
use Throwable;
12
use Yiisoft\Injector\Injector;
13
use Yiisoft\Queue\Exception\JobFailureException;
14
use Yiisoft\Queue\Message\HandlerEnvelope;
15
use Yiisoft\Queue\Message\MessageHandlerInterface;
16
use Yiisoft\Queue\Message\MessageInterface;
17
use Yiisoft\Queue\Middleware\ConsumeFinalHandler;
18
use Yiisoft\Queue\Middleware\FailureHandling\FailureFinalHandler;
19
use Yiisoft\Queue\Middleware\FailureHandling\FailureHandlingRequest;
20
use Yiisoft\Queue\Middleware\FailureHandling\FailureMiddlewareDispatcher;
21
use Yiisoft\Queue\Middleware\MiddlewareDispatcher;
22
use Yiisoft\Queue\Middleware\Request;
23
use Yiisoft\Queue\QueueInterface;
24
use Yiisoft\Queue\Message\IdEnvelope;
25
26
final class Worker implements WorkerInterface
27
{
28 19
    public function __construct(
29
        private LoggerInterface $logger,
30
        private Injector $injector,
31
        private ContainerInterface $container,
32
        private MiddlewareDispatcher $consumeMiddlewareDispatcher,
33
        private FailureMiddlewareDispatcher $failureMiddlewareDispatcher,
34
    ) {
35 19
    }
36
37
    /**
38
     * @throws Throwable
39
     */
40 10
    public function process(MessageInterface $message, QueueInterface $queue): MessageInterface
41
    {
42 10
        $this->logger->info('Processing message #{message}.', ['message' => $message->getMetadata()[IdEnvelope::MESSAGE_ID_KEY] ?? 'null']);
43
44 10
        $handlerClass = $message instanceof HandlerEnvelope ? $message->getHandler() : null;
45
46 10
        if (!is_subclass_of($handlerClass, MessageHandlerInterface::class, true)) {
47
            throw new RuntimeException(sprintf(
48
                'Message handler "%s" for "%s" must implement "%s".',
49
                $handlerClass,
50
                $message::class,
51
                MessageHandlerInterface::class,
52
            ));
53
        }
54 10
        $handler = $this->container->get($handlerClass);
0 ignored issues
show
Bug introduced by
It seems like $handlerClass can also be of type null; however, parameter $id of Psr\Container\ContainerInterface::get() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

54
        $handler = $this->container->get(/** @scrutinizer ignore-type */ $handlerClass);
Loading history...
55 10
        if ($handler === null) {
56
            throw new RuntimeException(sprintf('Queue handler with name "%s" does not exist', $handlerClass));
57
        }
58
59 10
        $request = new Request($message, $queue->getAdapter());
60 10
        $closure = fn (MessageInterface $message): mixed => $this->injector->invoke([$handler, 'handle'], [$message]);
61
        try {
62 10
            return $this->consumeMiddlewareDispatcher->dispatch($request, new ConsumeFinalHandler($closure))->getMessage();
63 1
        } catch (Throwable $exception) {
64 1
            $request = new FailureHandlingRequest($request->getMessage(), $exception, $queue);
65
66
            try {
67 1
                $result = $this->failureMiddlewareDispatcher->dispatch($request, new FailureFinalHandler());
68
                $this->logger->info($exception->getMessage());
69
70
                return $result->getMessage();
71 1
            } catch (Throwable $exception) {
72 1
                $exception = new JobFailureException($message, $exception);
73 1
                $this->logger->error($exception->getMessage());
74 1
                throw $exception;
75
            }
76
        }
77
    }
78
79
    private function createConsumeHandler(Closure $handler): MessageHandlerConsumeInterface
0 ignored issues
show
Bug introduced by
The type Yiisoft\Queue\Worker\Mes...HandlerConsumeInterface 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...
Unused Code introduced by
The method createConsumeHandler() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
80
    {
81
        return new ConsumeFinalHandler($handler);
0 ignored issues
show
Bug Best Practice introduced by
The expression return new Yiisoft\Queue...eFinalHandler($handler) returns the type Yiisoft\Queue\Middleware\ConsumeFinalHandler which is incompatible with the type-hinted return Yiisoft\Queue\Worker\Mes...HandlerConsumeInterface.
Loading history...
82
    }
83
84
    private function createFailureHandler(): MessageFailureHandlerInterface
0 ignored issues
show
Unused Code introduced by
The method createFailureHandler() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
Bug introduced by
The type Yiisoft\Queue\Worker\Mes...FailureHandlerInterface 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...
85
    {
86
        return new FailureFinalHandler();
0 ignored issues
show
Bug Best Practice introduced by
The expression return new Yiisoft\Queue...g\FailureFinalHandler() returns the type Yiisoft\Queue\Middleware...ing\FailureFinalHandler which is incompatible with the type-hinted return Yiisoft\Queue\Worker\Mes...FailureHandlerInterface.
Loading history...
87
    }
88
}
89