Passed
Branch master (6c6bd5)
by Sébastien
03:15
created

MessageBusHandler   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 95
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 10
eloc 20
c 1
b 0
f 0
dl 0
loc 95
ccs 0
cts 33
cp 0
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 2
A __invoke() 0 9 1
A dispatch() 0 13 4
A toEnvelope() 0 19 3
1
<?php
2
3
namespace Bdf\QueueMessengerBundle\Transport\Handler;
4
5
use Bdf\Queue\Message\EnvelopeInterface as QueuedEnvelope;
6
use Bdf\Queue\Message\InteractEnvelopeInterface;
7
use Bdf\QueueMessengerBundle\Transport\Stamp\NullStampsSerializer;
8
use Bdf\QueueMessengerBundle\Transport\Stamp\StampsSerializerInterface;
9
use Symfony\Component\Messenger\Envelope;
10
use Symfony\Component\Messenger\Exception\LogicException;
11
use Symfony\Component\Messenger\MessageBusInterface;
12
use Symfony\Component\Messenger\Stamp\HandledStamp;
13
use Symfony\Component\Messenger\Stamp\ReceivedStamp;
14
15
/**
16
 * Job for dispatch a queued command to the bus
17
 * If the message do not contains a valid object as data, an InternalMessage is dispatched
18
 *
19
 * If the a reply is requested on the message,
20
 * a synchronised dispatch is performed,
21
 * and the result is returned as reply
22
 */
23
class MessageBusHandler
24
{
25
    /**
26
     * The command dispatcher
27
     *
28
     * @var MessageBusInterface
29
     */
30
    private $dispatcher;
31
32
    /**
33
     * @var StampsSerializerInterface
34
     */
35
    private $stampsSerializer;
36
37
38
    /**
39
     * Constructor
40
     *
41
     * @param MessageBusInterface $dispatcher
42
     * @param StampsSerializerInterface|null $stampsSerializer
43
     */
44
    public function __construct(MessageBusInterface $dispatcher, StampsSerializerInterface $stampsSerializer = null)
45
    {
46
        $this->dispatcher = $dispatcher;
47
        $this->stampsSerializer = $stampsSerializer ?: new NullStampsSerializer();
48
    }
49
50
    /**
51
     * Handle a queued command
52
     *
53
     * @param mixed $message
54
     * @param QueuedEnvelope $queuedEnvelope
55
     */
56
    public function __invoke($message, QueuedEnvelope $queuedEnvelope)
57
    {
58
        $envelope = $this
59
            ->toEnvelope($message, $queuedEnvelope)
60
            // Symfony 4.3 add transport name in constructor
61
            ->with(new ReceivedStamp($queuedEnvelope->connection()->getName()))
62
        ;
63
64
        $this->dispatch($envelope, $queuedEnvelope);
65
    }
66
67
    /**
68
     * Dispatch the envelope to the bus
69
     *
70
     * If the message is replyable and a reply is requested, a synchronized call is performed and the result is returned
71
     *
72
     * @param Envelope $envelope
73
     * @param QueuedEnvelope $queuedEnvelope
74
     */
75
    private function dispatch(Envelope $envelope, QueuedEnvelope $queuedEnvelope): void
76
    {
77
        $envelope = $this->dispatcher->dispatch($envelope);
78
79
        if ($queuedEnvelope instanceof InteractEnvelopeInterface && $queuedEnvelope->message()->needsReply()) {
80
            /** @var HandledStamp[] $handledStamps */
81
            $handledStamps = $envelope->all(HandledStamp::class);
82
83
            if (!$handledStamps) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $handledStamps of type Symfony\Component\Messenger\Stamp\HandledStamp[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
84
                throw new LogicException(sprintf('Message of type "%s" was handled zero times. Exactly one handler is expected when using "%s::%s()".', \get_class($envelope->getMessage()), \get_class($this), __FUNCTION__));
85
            }
86
87
            $queuedEnvelope->reply($handledStamps[0]->getResult());
88
        }
89
    }
90
91
    /**
92
     * Get the envelope from the message payload
93
     *
94
     * @param mixed $message
95
     * @param QueuedEnvelope $queuedEnvelope
96
     *
97
     * @return Envelope
98
     */
99
    private function toEnvelope($message, QueuedEnvelope $queuedEnvelope): Envelope
100
    {
101
        if ($message instanceof Envelope) {
102
            return $message;
103
        }
104
105
        // TODO How to handle non object message
106
//        if (!is_object($message)) {
107
//            $message = new InternalMessage(
108
//                $queuedEnvelope->message()->name() ?: $queuedEnvelope->message()->queue(),
109
//                $message
110
//            );
111
//        }
112
113
        if ($stamps = $queuedEnvelope->message()->header('stamps')) {
114
            return new Envelope($message, $this->stampsSerializer->deserialize($stamps));
115
        }
116
117
        return new Envelope($message);
118
    }
119
}
120