Completed
Push — master ( 0e6469...31759b )
by Tomas
02:30
created

Dispatcher::emit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 4
Bugs 1 Features 1
Metric Value
c 4
b 1
f 1
dl 0
loc 11
ccs 8
cts 8
cp 1
rs 9.4285
cc 1
eloc 7
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Tomaj\Hermes;
4
5
use Exception;
6
use Psr\Log\LoggerInterface;
7
use Psr\Log\LogLevel;
8
use Tomaj\Hermes\Handler\HandlerInterface;
9
use Tomaj\Hermes\Driver\DriverInterface;
10
use Tracy\Debugger;
11
12
class Dispatcher implements DispatcherInterface
13
{
14
    /**
15
     * Dispatcher driver
16
     *
17
     * @var DriverInterface
18
     */
19
    private $driver;
20
21
    /**
22
     * Logger
23
     *
24
     * @var LoggerInterface
25
     */
26
    private $logger;
27
28
    /**
29
     * All registered handalers
30
     *
31
     * @var array
32
     */
33
    private $handlers = [];
34
35
    /**
36
     * Create new Dispatcher
37
     *
38
     * @param DriverInterface $driver
39
     */
40 21
    public function __construct(DriverInterface $driver, LoggerInterface $logger = null)
41
    {
42 21
        $this->driver = $driver;
43 21
        $this->logger = $logger;
44 21
    }
45
46
    /**
47
     * {@inheritdoc}
48
     */
49 6
    public function emit(MessageInterface $message)
50
    {
51 6
        $this->driver->send($message);
52
        
53 6
        $this->log(
54 6
            LogLevel::INFO,
55 6
            "Dispatcher send message #{$message->getId()} to driver " . get_class($this->driver),
56 6
            $this->messageLoggerContext($message)
57 6
        );
58 6
        return $this;
59
    }
60
61
    /**
62
     * Basic method for background job to star listening.
63
     *
64
     * This method hook to driver wait() method and start listening events.
65
     * Method is blockig, so when you call it all processing will stop.
66
     * WARNING! Dont use it on web server calls. Run it only with cli.
67
     *
68
     * @return void
69
     */
70
    public function handle()
71
    {
72 15
        $this->driver->wait(function (MessageInterface $message) {
73 15
            $this->log(
74 15
                LogLevel::INFO,
75 15
                "Start handle message #{$message->getId()} ({$message->getType()})",
76 15
                $this->messageLoggerContext($message)
77 15
            );
78 15
            return $this->dispatch($message);
79 15
        });
80 15
    }
81
82 15
    private function dispatch(MessageInterface $message)
83
    {
84 15
        $type = $message->getType();
85
86 15
        if (!$this->hasHandlers($type)) {
87 6
            return true;
88
        }
89
90 12
        $result = true;
91
92 12
        foreach ($this->handlers[$type] as $handler) {
93 12
            $handlerResult = $this->handleMessage($handler, $message);
94
95 12
            if ($result && !$handlerResult) {
96 6
                $result = false;
97 6
            }
98 12
        }
99
100 12
        return $result;
101
    }
102
103 12
    private function handleMessage($handler, $message)
104
    {
105
        // check if handler implements Psr\Log\LoggerAwareInterface (you can use \Psr\Log\LoggerAwareTrait)
106 12
        if ($this->logger && method_exists($handler, 'setLogger')) {
107
            $handler->setLogger($this->logger);
108
        }
109
110
        try {
111 12
            $result = $handler->handle($message);
112
            
113 9
            $this->log(
114 9
                LogLevel::INFO,
115 9
                "End handle message #{$message->getId()} ({$message->getType()})",
116 9
                $this->messageLoggerContext($message)
117 9
            );
118 12
        } catch (Exception $e) {
119 3
            $this->log(
120 3
                LogLevel::ERROR,
121 3
                "Handler " . get_class($handler) . " throws exception - {$e->getMessage()}",
122 3
                ['error' => $e, 'message' => $this->messageLoggerContext($message), 'exception' => $e]
123 3
            );
124 3
            Debugger::log($e, Debugger::EXCEPTION);
125 3
            $result = false;
126
        }
127 12
        return $result;
128
    }
129
130 15
    private function hasHandlers($type)
131
    {
132 15
        return isset($this->handlers[$type]) && count($this->handlers[$type]) > 0;
133
    }
134
135
    /**
136
     * {@inheritdoc}
137
     */
138 15
    public function registerHandler($type, HandlerInterface $handler)
139
    {
140 15
        if (!isset($this->handlers[$type])) {
141 15
            $this->handlers[$type] = [];
142 15
        }
143
144 15
        $this->handlers[$type][] = $handler;
145 15
    }
146
147 21
    private function messageLoggerContext(MessageInterface $message)
148
    {
149
        return [
150 21
            'id' => $message->getId(),
151 21
            'created' => $message->getCreated(),
152 21
            'type' => $message->getType(),
153 21
            'payload' => $message->getPayload(),
154 21
        ];
155
    }
156
157 21
    private function log($level, $message, $context)
158
    {
159 21
        if ($this->logger) {
160 6
            $this->logger->log($level, $message, $context);
161 6
        }
162 21
    }
163
}
164