Passed
Push — release-11.5.x ( 2858e4...857414 )
by Rafael
39:14 queued 21:21
created

EventQueueWorkerTask   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 155
Duplicated Lines 0 %

Test Coverage

Coverage 80.43%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 12
eloc 49
c 1
b 0
f 0
dl 0
loc 155
ccs 37
cts 46
cp 0.8043
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A execute() 0 4 1
A getEventDispatcher() 0 3 1
A getAdditionalInformation() 0 13 1
A getLimit() 0 3 1
A getEventQueueItemRepository() 0 3 1
A setLimit() 0 3 1
A getSolrLogManager() 0 3 1
A processEvents() 0 49 5
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the TYPO3 CMS project.
7
 *
8
 * It is free software; you can redistribute it and/or modify it under
9
 * the terms of the GNU General Public License, either version 2
10
 * of the License, or any later version.
11
 *
12
 * For the full copyright and license information, please read the
13
 * LICENSE.txt file that was distributed with this source code.
14
 *
15
 * The TYPO3 project - inspiring people to share!
16
 */
17
18
namespace ApacheSolrForTypo3\Solr\Task;
19
20
use ApacheSolrForTypo3\Solr\Domain\Index\Queue\UpdateHandler\EventListener\Events\DelayedProcessingFinishedEvent;
21
use ApacheSolrForTypo3\Solr\Domain\Index\Queue\UpdateHandler\Events\DataUpdateEventInterface;
22
use ApacheSolrForTypo3\Solr\System\Logging\SolrLogManager;
23
use ApacheSolrForTypo3\Solr\System\Records\Queue\EventQueueItemRepository;
24
use Doctrine\DBAL\Driver\Exception as DBALDriverException;
25
use Doctrine\DBAL\Exception as DBALException;
26
use InvalidArgumentException;
27
use Psr\EventDispatcher\EventDispatcherInterface;
28
use Throwable;
29
use TYPO3\CMS\Core\Utility\GeneralUtility;
30
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
31
use TYPO3\CMS\Scheduler\Task\AbstractTask;
32
33
/**
34
 * A worker processing the queued data update events
35
 *
36
 * @author Markus Friedrich <[email protected]>
37
 */
38
final class EventQueueWorkerTask extends AbstractTask
39
{
40
    const DEFAULT_PROCESSING_LIMIT = 100;
41
42
    /**
43
     * Processing limit, the number of events to process
44
     *
45
     * @var int
46
     */
47
    protected int $limit = self::DEFAULT_PROCESSING_LIMIT;
48
49
    /**
50
     * Works through the indexing queue and indexes the queued items into Solr.
51
     *
52
     * @return bool Returns TRUE on success, FALSE if no items were indexed or none were found.
53
     *
54
     * @throws DBALDriverException
55
     * @throws DBALException|\Doctrine\DBAL\DBALException
56
     * @noinspection PhpMissingReturnTypeInspection See {@link \TYPO3\CMS\Scheduler\Task\AbstractTask::execute()}
57
     */
58 33
    public function execute()
59
    {
60 33
        $this->processEvents();
61 33
        return true;
62
    }
63
64
    /**
65
     * Process queued data update events
66
     *
67
     * @throws DBALDriverException
68
     * @throws DBALException|\Doctrine\DBAL\DBALException
69
     */
70 33
    protected function processEvents(): void
71
    {
72 33
        $itemRepository = $this->getEventQueueItemRepository();
73 33
        $dispatcher = $this->getEventDispatcher();
74
75 33
        $queueItems = $itemRepository->getEventQueueItems($this->limit);
76 33
        $processedItems = [];
77 33
        foreach ($queueItems as $queueItem) {
78
            try {
79 33
                $event = unserialize($queueItem['event']);
80 33
                if (!$event instanceof DataUpdateEventInterface) {
81 1
                    throw new InvalidArgumentException(
82
                        'Unsupported event found: '
83 1
                            . (is_object($event) ? get_class($event) : (string)$event),
84
                        1639747163
85
                    );
86
                }
87
88 32
                $event->setForceImmediateProcessing(true);
89 32
                $dispatcher->dispatch($event);
90 31
                $processedItems[] = $queueItem['uid'];
91
92
                // dispatch event processing finished event
93 31
                $dispatcher->dispatch(
94 31
                    new DelayedProcessingFinishedEvent($event)
95
                );
96 2
            } catch (Throwable $e) {
97 2
                $this->getSolrLogManager()->log(
98
                    SolrLogManager::ERROR,
99
                    'Couldn\'t process queued event',
100
                    [
101 2
                        'eventQueueItemUid' => $queueItem['uid'],
102 2
                        'error' => $e->getMessage(),
103 2
                        'errorCode' => $e->getCode(),
104 2
                        'errorFile' => $e->getFile() . ':' . $e->getLine(),
105
                    ]
106
                );
107 2
                $itemRepository->updateEventQueueItem(
108 2
                    $queueItem['uid'],
109
                    [
110 2
                        'error' => 1,
111 2
                        'error_message' => $e->getMessage() . '[' . $e->getCode() . ']',
112
                    ]
113
                );
114
            }
115
        }
116
117
        // update event queue
118 33
        $itemRepository->deleteEventQueueItems($processedItems);
119
    }
120
121
    /**
122
     * Returns some additional information about indexing progress, shown in
123
     * the scheduler's task overview list.
124
     *
125
     * @return string Information to display
126
     * @throws DBALDriverException
127
     * @throws DBALException|\Doctrine\DBAL\DBALException
128
     */
129
    public function getAdditionalInformation(): string
130
    {
131
        $message = LocalizationUtility::translate(
132
            'LLL:EXT:solr/Resources/Private/Language/locallang_be.xlf:task.eventQueueWorkerTask.statusMsg'
133
        );
134
135
        $fullItemCount = $this->getEventQueueItemRepository()->count(false);
136
        $pendingItemsCount = $this->getEventQueueItemRepository()->count();
137
        return sprintf(
138
            $message,
0 ignored issues
show
Bug introduced by
It seems like $message can also be of type null; however, parameter $format of sprintf() 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

138
            /** @scrutinizer ignore-type */ $message,
Loading history...
139
            $pendingItemsCount,
140
            ($fullItemCount - $pendingItemsCount),
141
            $this->limit
142
        );
143
    }
144
145
    /**
146
     * Sets the limit
147
     *
148
     * @param int $limit
149
     */
150 2
    public function setLimit(int $limit): void
151
    {
152 2
        $this->limit = $limit;
153
    }
154
155
    /**
156
     * Returns the limit
157
     *
158
     * @return int
159
     */
160
    public function getLimit(): int
161
    {
162
        return $this->limit;
163
    }
164
165
    /**
166
     * Return the SolrLogManager
167
     *
168
     * @return SolrLogManager
169
     */
170 2
    protected function getSolrLogManager(): SolrLogManager
171
    {
172 2
        return  GeneralUtility::makeInstance(SolrLogManager::class, /** @scrutinizer ignore-type */ __CLASS__);
173
    }
174
175
    /**
176
     * Return the EventQueueItemRepository
177
     *
178
     * @return EventQueueItemRepository
179
     */
180 33
    protected function getEventQueueItemRepository(): EventQueueItemRepository
181
    {
182 33
        return GeneralUtility::makeInstance(EventQueueItemRepository::class);
183
    }
184
185
    /**
186
     * Returns the EventDispatcher
187
     *
188
     * @return EventDispatcherInterface
189
     */
190 33
    protected function getEventDispatcher(): EventDispatcherInterface
191
    {
192 33
        return GeneralUtility::makeInstance(EventDispatcherInterface::class);
193
    }
194
}
195