wikimedia/mediawiki-extensions-CirrusSearch

View on GitHub
includes/Maintenance/Validators/ShardAllocationValidator.php

Summary

Maintainability
A
2 hrs
Test Coverage
<?php

namespace CirrusSearch\Maintenance\Validators;

use CirrusSearch\Maintenance\Printer;
use Elastica\Index;
use MediaWiki\Status\Status;

class ShardAllocationValidator extends Validator {
    /**
     * @var Index
     */
    private $index;

    /**
     * @var array
     */
    private $indexAllocation;

    /**
     * @param Index $index
     * @param array $indexAllocation
     * @param Printer|null $out
     */
    public function __construct( Index $index, array $indexAllocation, Printer $out = null ) {
        parent::__construct( $out );

        $this->index = $index;
        $this->indexAllocation = $indexAllocation;
    }

    /**
     * @return Status
     */
    public function validate() {
        $this->outputIndented( "\tValidating shard allocation settings..." );

        $actual = $this->fetchActualAllocation();
        $changed = false;
        foreach ( [ 'include', 'exclude', 'require' ] as $type ) {
            $desired = $this->indexAllocation[$type];
            if ( $desired ) {
                $this->output( "\n" );
                $this->outputIndented( "\t\tUpdating '$type' allocations..." );
                $this->set( $type, $desired );
                $this->output( "done" );
                $changed = true;
            }
            if ( isset( $actual[$type] ) ) {
                $undesired = array_filter( array_keys( $actual[$type] ),
                    static function ( $key ) use ( $actual, $type, $desired ) {
                        return $actual[$type][$key] !== '' && !isset( $desired[$key] );
                    }
                );

                if ( $undesired ) {
                    $this->output( "\n" );
                    $this->outputIndented( "\t\tClearing '$type' allocations..." );
                    $this->set( $type, array_fill_keys( $undesired, '' ) );
                    $this->output( "done" );
                    $changed = true;
                }
            }
        }
        if ( $changed ) {
            $this->output( "\n" );
        } else {
            $this->output( "done\n" );
        }

        return Status::newGood();
    }

    /**
     * @return array
     */
    private function fetchActualAllocation() {
        $settings = $this->index->getSettings()->get();
        return $settings['routing']['allocation'] ?? [];
    }

    /**
     * @param string $type
     * @param array $allocation
     */
    private function set( $type, $allocation ) {
        $this->index->getSettings()->set( [
            'routing' => [
                'allocation' => [
                    $type => $allocation,
                ]
            ]
        ] );
    }
}