Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
75.00% covered (warning)
75.00%
21 / 28
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
EventBusBridge
75.00% covered (warning)
75.00%
21 / 28
0.00% covered (danger)
0.00%
0 / 3
10.27
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 factory
80.00% covered (warning)
80.00%
8 / 10
0.00% covered (danger)
0.00%
0 / 1
4.13
 onLinksUpdateComplete
92.86% covered (success)
92.86%
13 / 14
0.00% covered (danger)
0.00%
0 / 1
4.01
1<?php
2
3namespace CirrusSearch\Event;
4
5use CirrusSearch\PageChangeTracker;
6use MediaWiki\Config\Config;
7use MediaWiki\Config\ConfigFactory;
8use MediaWiki\Deferred\DeferredUpdates;
9use MediaWiki\Extension\EventBus\EventBusFactory;
10use MediaWiki\Extension\EventBus\StreamNameMapper;
11use MediaWiki\Page\PageLookup;
12use MediaWiki\Request\WebRequest;
13use MediaWiki\Title\TitleFormatter;
14use Wikimedia\UUID\GlobalIdGenerator;
15
16/**
17 * Hook handler responsible for bridging internal MW events to dedicated event streams.
18 */
19class EventBusBridge extends PageChangeTracker implements EventBridge {
20    private EventBusFactory $eventBusFactory;
21    private PageLookup $pageLookup;
22    private PageRerenderSerializer $pageRerenderSerializer;
23
24    /**
25     * @param EventBusFactory $eventBusFactory
26     * @param PageLookup $pageLookup
27     * @param PageRerenderSerializer $pageRerenderSerializer
28     */
29    public function __construct(
30        EventBusFactory $eventBusFactory,
31        PageLookup $pageLookup,
32        PageRerenderSerializer $pageRerenderSerializer,
33        int $maxStateSize = 512
34    ) {
35        parent::__construct( $maxStateSize );
36        $this->eventBusFactory = $eventBusFactory;
37        $this->pageLookup = $pageLookup;
38        $this->pageRerenderSerializer = $pageRerenderSerializer;
39    }
40
41    /**
42     * @param ConfigFactory $configFactory
43     * @param Config $mainConfig
44     * @param GlobalIdGenerator $globalIdGenerator
45     * @param TitleFormatter $titleFormatter
46     * @param PageLookup $pageLookup
47     * @param EventBusFactory|null $eventBusFactory
48     * @return EventBridge
49     */
50    public static function factory(
51        ConfigFactory $configFactory,
52        Config $mainConfig,
53        GlobalIdGenerator $globalIdGenerator,
54        TitleFormatter $titleFormatter,
55        PageLookup $pageLookup,
56        ?EventBusFactory $eventBusFactory = null,
57        ?StreamNameMapper $streamNameMapper = null
58    ): EventBridge {
59        $config = $configFactory->makeConfig( "CirrusSearch" );
60        '@phan-var \CirrusSearch\SearchConfig $config';
61        if ( $eventBusFactory !== null && $config->get( 'CirrusSearchUseEventBusBridge' ) ) {
62            if ( $streamNameMapper === null ) {
63                throw new \RuntimeException( 'EventBusFactory provided without StreamNameMapper' );
64            }
65            $pageRerenderSerializer = new PageRerenderSerializer( $mainConfig, $titleFormatter,
66                $config, $globalIdGenerator, $streamNameMapper );
67            return new self( $eventBusFactory, $pageLookup, $pageRerenderSerializer );
68        }
69        return new class() implements EventBridge {
70            /**
71             * @inheritDoc
72             */
73            public function onLinksUpdateComplete( $linksUpdate, $ticket ) {
74            }
75        };
76    }
77
78    /**
79     * @inheritDoc
80     */
81    public function onLinksUpdateComplete( $linksUpdate, $ticket ) {
82        DeferredUpdates::addCallableUpdate( function () use ( $linksUpdate ) {
83            if ( $this->isPageChange( $linksUpdate->getPageId() ) ) {
84                // Page changes are handled via the page-change stream
85                return;
86            }
87            $page = $this->pageLookup->getPageById( $linksUpdate->getPageId() );
88            if ( $page === null ) {
89                // the page no longer exists
90                return;
91            }
92            if ( $page->isRedirect() ) {
93                // We are not really interested in redirects at this point
94                // since we would ultimately refresh the target of this redirect we assume
95                // that a LinksUpdate for the redirect does not imply that the target page has
96                // to re-render as well.
97                return;
98            }
99            $event = $this->pageRerenderSerializer->eventDataForPage( $page,
100                PageRerenderSerializer::LINKS_UPDATE_REASON, WebRequest::getRequestId() );
101            // Fire and forget, we do not check the return value, problems should be already logged by
102            // EventBus
103            $this->eventBusFactory
104                ->getInstanceForStream( $event['meta']['stream'] )
105                ->send( [ $event ] );
106        } );
107    }
108}