%PDF- %PDF-
Direktori : /www/varak.net/wiki.varak.net/extensions/CirrusSearch/includes/ |
Current File : /www/varak.net/wiki.varak.net/extensions/CirrusSearch/includes/OtherIndexes.php |
<?php namespace CirrusSearch; use MediaWiki\Logger\LoggerFactory; use Title; /** * Tracks whether a Title is known on other indexes. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * http://www.gnu.org/copyleft/gpl.html */ class OtherIndexes extends Updater { /** @var string Local site we're tracking */ private $localSite; /** * @param Connection $connection * @param SearchConfig $config * @param array $flags * @param string $localSite */ public function __construct( Connection $connection, SearchConfig $config, array $flags, $localSite) { parent::__construct( $connection, $config, $flags ); $this->localSite = $localSite; } /** * Get the external index identifiers for title. * @param Title $title * @return string[] array of index identifiers. empty means none. */ public static function getExternalIndexes( Title $title ) { global $wgCirrusSearchExtraIndexes; $namespace = $title->getNamespace(); return isset( $wgCirrusSearchExtraIndexes[ $namespace ] ) ? $wgCirrusSearchExtraIndexes[ $namespace ] : []; } /** * Get any extra indexes to query, if any, based on namespaces * @param int[] $namespaces An array of namespace ids * @return string[] array of indexes */ public static function getExtraIndexesForNamespaces( array $namespaces ) { global $wgCirrusSearchExtraIndexes; $extraIndexes = []; if ( $wgCirrusSearchExtraIndexes ) { foreach( $wgCirrusSearchExtraIndexes as $namespace => $indexes ) { if ( in_array( $namespace, $namespaces ) ) { $extraIndexes = array_merge( $extraIndexes, $indexes ); } } } return $extraIndexes; } /** * Update the indexes for other wiki that also store information about $titles. * @param Title[] $titles array of titles in other indexes to update */ public function updateOtherIndex( $titles ) { global $wgCirrusSearchWikimediaExtraPlugin; if ( !isset( $wgCirrusSearchWikimediaExtraPlugin['super_detect_noop'] ) ) { $this->logFailure( $titles, 'super_detect_noop plugin not enabled' ); return; } $updates = []; // Build multisearch to find ids to update $findIdsMultiSearch = new \Elastica\Multi\Search( $this->connection->getClient() ); $findIdsClosures = []; foreach ( $titles as $title ) { foreach ( OtherIndexes::getExternalIndexes( $title ) as $otherIndex ) { if ( $otherIndex === null ) { continue; } $type = $this->connection->getPageType( $otherIndex ); $bool = new \Elastica\Query\BoolQuery(); // Note that we need to use the keyword indexing of title so the analyzer gets out of the way. $bool->addFilter( new \Elastica\Query\Term( [ 'title.keyword' => $title->getText() ] ) ); $bool->addFilter( new \Elastica\Query\Term( [ 'namespace' => $title->getNamespace() ] ) ); $query = new \Elastica\Query( $bool ); $query->setFields( [] ); // We only need the _id so don't load the _source $query->setSize( 1 ); $findIdsMultiSearch->addSearch( $type->createSearch( $query ) ); $findIdsClosures[] = function( $docId ) use ( $otherIndex, &$updates, $title ) { $updates[$otherIndex][] = [ 'docId' => $docId, 'ns' => $title->getNamespace(), 'dbKey' => $title->getDBkey(), ]; }; } } $findIdsClosuresCount = count( $findIdsClosures ); if ( $findIdsClosuresCount === 0 ) { // No other indexes to check. return; } // Look up the ids and run all closures to build the list of updates $this->start( "searching for {numIds} ids in other indexes", [ 'numIds' => $findIdsClosuresCount, 'queryType' => 'other_idx_lookup', ] ); $findIdsMultiSearchResult = $findIdsMultiSearch->search(); try { $this->success(); for ( $i = 0; $i < $findIdsClosuresCount; $i++ ) { $results = $findIdsMultiSearchResult[ $i ]->getResults(); if ( count( $results ) === 0 ) { continue; } $result = $results[ 0 ]; call_user_func( $findIdsClosures[ $i ], $result->getId() ); } } catch ( \Elastica\Exception\ExceptionInterface $e ) { $this->failure( $e ); return; } if ( !$updates ) { return; } // These are split into a job per index so one index // being frozen doesn't block updates to other indexes // in the same update. foreach ( $updates as $indexName => $actions ) { $job = new Job\ElasticaWrite( reset( $titles ), [ 'method' => 'sendOtherIndexUpdates', 'arguments' => [ $this->localSite, $indexName, $actions ], 'cluster' => $this->writeToClusterName, ] ); $job->run(); } } /** * @param Title[] $titles * @param string $reason */ private function logFailure( array $titles, $reason = '' ) { $articleIDs = array_map( function( Title $title ) { return $title->getArticleID(); }, $titles ); if ( $reason ) { $reason = " ($reason)"; } LoggerFactory::getInstance( 'CirrusSearchChangeFailed' )->info( "Other Index$reason for article ids: " . implode( ',', $articleIDs ) ); } }