Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.67% covered (success)
96.67%
58 / 60
87.50% covered (warning)
87.50%
7 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
MetaVersionStore
96.67% covered (success)
96.67%
58 / 60
87.50% covered (warning)
87.50%
7 / 8
13
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 docId
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 buildIndexProperties
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
1
 update
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 updateAll
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 find
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 findAll
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
3
 buildDocument
92.00% covered (success)
92.00%
23 / 25
0.00% covered (danger)
0.00%
0 / 1
3.00
1<?php
2
3namespace CirrusSearch\MetaStore;
4
5use CirrusSearch\Connection;
6use CirrusSearch\Maintenance\AnalysisConfigBuilder;
7use CirrusSearch\Maintenance\ArchiveMappingConfigBuilder;
8use CirrusSearch\Maintenance\MappingConfigBuilder;
9use CirrusSearch\Maintenance\SuggesterAnalysisConfigBuilder;
10use CirrusSearch\Maintenance\SuggesterMappingConfigBuilder;
11use Elastica\Index;
12use Elastica\Query\BoolQuery;
13use GitInfo;
14use WikiMap;
15
16class MetaVersionStore implements MetaStore {
17    public const METASTORE_TYPE = 'version';
18
19    /** @var Connection */
20    private $connection;
21
22    /** @var Index */
23    private $index;
24
25    public function __construct( Index $index, Connection $connection ) {
26        $this->index = $index;
27        $this->connection = $connection;
28    }
29
30    /**
31     * @param Connection $connection
32     * @param string $baseName
33     * @param string $typeName
34     * @return string
35     */
36    public static function docId( Connection $connection, $baseName, $typeName ) {
37        return implode( '-', [
38            self::METASTORE_TYPE,
39            $connection->getIndexName( $baseName, $typeName )
40        ] );
41    }
42
43    /**
44     * @return array Properties to add to metastore for version info
45     */
46    public function buildIndexProperties() {
47        return [
48            'index_name' => [ 'type' => 'keyword' ],
49            'analysis_maj' => [ 'type' => 'long' ],
50            'analysis_min' => [ 'type' => 'long' ],
51            'mapping_maj' => [ 'type' => 'long' ],
52            'mapping_min' => [ 'type' => 'long' ],
53            'shard_count' => [ 'type' => 'long' ],
54            'mediawiki_version' => [ 'type' => 'keyword' ],
55            'mediawiki_commit' => [ 'type' => 'keyword' ],
56            'cirrus_commit' => [ 'type' => 'keyword' ],
57        ];
58    }
59
60    /**
61     * @param string $baseName
62     * @param string $typeName
63     */
64    public function update( $baseName, $typeName ) {
65        $this->index->addDocuments( [ self::buildDocument( $this->connection, $baseName, $typeName ) ] );
66    }
67
68    /**
69     * @param string $baseName
70     */
71    public function updateAll( $baseName ) {
72        $docs = [];
73        foreach ( $this->connection->getAllIndexSuffixes( null ) as $typeName ) {
74            $docs[] = self::buildDocument( $this->connection, $baseName, $typeName );
75        }
76        $this->index->addDocuments( $docs );
77    }
78
79    /**
80     * @param string $baseName
81     * @param string $typeName
82     * @return \Elastica\Document
83     */
84    public function find( $baseName, $typeName ) {
85        $docId = self::docId( $this->connection, $baseName, $typeName );
86        return $this->index->getDocument( $docId );
87    }
88
89    /**
90     * @param string|null $baseName Base index name to find, or all to
91     *  return all indices for all wikis.
92     * @return \Elastica\ResultSet
93     */
94    public function findAll( $baseName = null ) {
95        $filter = new BoolQuery();
96        $filter->addFilter( ( new \Elastica\Query\Term() )
97            ->setTerm( 'type', self::METASTORE_TYPE ) );
98        if ( $baseName !== null ) {
99            $ids = new \Elastica\Query\Ids();
100            foreach ( $this->connection->getAllIndexSuffixes( null ) as $typeName ) {
101                $ids->addId( self::docId( $this->connection, $baseName, $typeName ) );
102            }
103            $filter->addFilter( $ids );
104        }
105
106        $query = new \Elastica\Query( $filter );
107        // WHAT ARE YOU DOING TRACKING MORE THAN 5000 INDICES?!?
108        $query->setSize( 5000 );
109        return $this->index->search( $query );
110    }
111
112    /**
113     * Create version data for index type.
114     * @param Connection $connection
115     * @param string $baseName
116     * @param string $typeName
117     * @return \Elastica\Document
118     */
119    public static function buildDocument( Connection $connection, $baseName, $typeName ) {
120        global $IP;
121        if ( $typeName == Connection::TITLE_SUGGEST_INDEX_SUFFIX ) {
122            list( $aMaj, $aMin ) = explode( '.', SuggesterAnalysisConfigBuilder::VERSION, 3 );
123            list( $mMaj, $mMin ) = explode( '.', SuggesterMappingConfigBuilder::VERSION, 3 );
124        } elseif ( $typeName === Connection::ARCHIVE_INDEX_SUFFIX ) {
125            list( $aMaj, $aMin ) = explode( '.', AnalysisConfigBuilder::VERSION, 3 );
126            list( $mMaj, $mMin ) = explode( '.', ArchiveMappingConfigBuilder::VERSION, 3 );
127        } else {
128            list( $aMaj, $aMin ) = explode( '.', AnalysisConfigBuilder::VERSION, 3 );
129            list( $mMaj, $mMin ) = explode( '.', MappingConfigBuilder::VERSION, 3 );
130        }
131        $mwInfo = new GitInfo( $IP );
132        $cirrusInfo = new GitInfo( __DIR__ . '/../..' );
133        $docId = self::docId( $connection, $baseName, $typeName );
134        $data = [
135            'type' => self::METASTORE_TYPE,
136            'wiki' => WikiMap::getCurrentWikiId(),
137            'index_name' => $connection->getIndexName( $baseName, $typeName ),
138            'analysis_maj' => $aMaj,
139            'analysis_min' => $aMin,
140            'mapping_maj' => $mMaj,
141            'mapping_min' => $mMin,
142            'shard_count' => $connection->getSettings()->getShardCount( $typeName ),
143            'mediawiki_version' => MW_VERSION,
144            'mediawiki_commit' => $mwInfo->getHeadSHA1(),
145            'cirrus_commit' => $cirrusInfo->getHeadSHA1(),
146        ];
147
148        return new \Elastica\Document( $docId, $data, '_doc' );
149    }
150}