EventSubject::dispatch()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 2
dl 0
loc 9
ccs 7
cts 7
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Fatindeed\GitlabWebhookHandler;
4
5
use Exception, SplSubject, SplObserver, SplObjectStorage;
6
use Psr\Log\LoggerAwareTrait;
7
use Psr\Log\LoggerInterface;
8
use Interop\Queue\Context;
9
use TimoReymann\GitlabWebhookLibrary\Specification\Event;
10
11
/**
12
 * @see https://www.php.net/manual/zh/class.splsubject.php
13
 */
14
class EventSubject implements SplSubject
15
{
16
    use LoggerAwareTrait, SignalHandler;
17
18
    /**
19
     * @var \SplObjectStorage
20
     */
21
    private $observers;
22
23
    /**
24
     * @var \TimoReymann\GitlabWebhookLibrary\Specification\Event
25
     */
26
    private $event;
27
28
    /**
29
     * @var bool
30
     */
31
    private $loop = true;
32
33
    const DEFAULT_QUEUE_NAME = 'gitlab-webhook-queue';
34
35
    /**
36
     * @param  \Psr\Log\LoggerInterface $logger
37
     */
38 6
    public function __construct(LoggerInterface $logger = null)
39
    {
40 6
        $this->observers = new SplObjectStorage;
41 6
        $this->setLogger($logger ?? new NullLogger);
42 6
    }
43
44
    /**
45
     * Attach an SplObserver
46
     * 
47
     * @param  \SplObserver $observer
48
     * @return void
49
     */
50 5
    public function attach(SplObserver $observer): void
51
    {
52 5
        $this->observers->attach($observer);
53 5
    }
54
55
    /**
56
     * Detach an observer
57
     * 
58
     * @param  \SplObserver $observer
59
     * @return void
60
     */
61 1
    public function detach(SplObserver $observer): void
62
    {
63 1
        $this->observers->detach($observer);
64 1
    }
65
66
    /**
67
     * Returns the number of observers in the storage
68
     * 
69
     * @return int
70
     */
71 1
    public function count(): int
72
    {
73 1
        return $this->observers->count();
74
    }
75
76
    /**
77
     * Notify an observer
78
     * 
79
     * @return void
80
     */
81 3
    public function notify(): void
82
    {
83 3
        foreach ($this->observers as $observer) {
84
            try {
85 3
                $observer->update($this);
86 1
            } catch (Exception $e) {
87 3
                $this->logger->error(get_class($observer).': '.$e->getMessage());
88
            }
89
        }
90 3
    }
91
92
    /**
93
     * Get event
94
     * 
95
     * @return \TimoReymann\GitlabWebhookLibrary\Specification\Event|null
96
     */
97 2
    public function getEvent(): ?Event
98
    {
99 2
        return $this->event;
100
    }
101
102
    /**
103
     * Set event
104
     * 
105
     * @param  \TimoReymann\GitlabWebhookLibrary\Specification\Event $event
106
     * @return void
107
     */
108 2
    public function setEvent(Event $event): void
109
    {
110 2
        $this->event = $event;
111 2
    }
112
113
    /**
114
     * Dispatch event
115
     * 
116
     * @param  \TimoReymann\GitlabWebhookLibrary\Specification\Event $event
117
     * @param  \Interop\Queue\Context|null $context
118
     * @return void
119
     */
120 3
    public function dispatch(Event $event, ?Context $context = null): void
121
    {
122 3
        if ($context) {
123 1
            $queue = $context->createQueue($_ENV['QUEUE_NAME'] ?? self::DEFAULT_QUEUE_NAME);
124 1
            $message = $context->createMessage(serialize($event));
125 1
            $context->createProducer()->send($queue, $message);
126
        } else {
127 2
            $this->setEvent($event);
128 2
            $this->notify();
129
        }
130 3
    }
131
132
    /**
133
     * Run infinite loop
134
     * 
135
     * @param  \Interop\Queue\Context $context
136
     * @return void
137
     */
138 2
    public function run(Context $context): void
139
    {
140 2
        $queue = $context->createQueue($_ENV['QUEUE_NAME'] ?? self::DEFAULT_QUEUE_NAME);
141 2
        $consumer = $context->createConsumer($queue);
142 2
        while ($this->loop) {
143
            try {
144 2
                $message = $consumer->receive(5000);
145 1
                if ($message) {
146 1
                    $event = unserialize($message->getBody());
147 1
                    $this->dispatch($event);
148 1
                    $consumer->acknowledge($message);
149
                }
150 1
            } catch (Exception $e) {
151 1
                $this->logger->error($e->getMessage());
152
            }
153 2
            $this->signalDispatch();
154
        }
155 2
    }
156
157
    /**
158
     * SIGTERM signal handler
159
     * 
160
     * @param  int $signo
161
     * @return void
162
     */
163 2
    public function terminate(int $signo): void
164
    {
165 2
        $this->logger->info('Gitlab webhook handler terminated on signal #'.$signo.'.');
166 2
        $this->loop = false;
167
    }
168
}