wikimedia/mediawiki-extensions-CirrusSearch

View on GitHub
includes/Sanity/MultiClusterRemediatorHelper.php

Summary

Maintainability
A
1 hr
Test Coverage
<?php

namespace CirrusSearch\Sanity;

use InvalidArgumentException;

/**
 * Helper to maintain the association with Remediators and theirs corresponding
 * BufferedRemediator.
 * When calling sendBatch this class evaluates if all action scheduled to the
 * BufferedRemediator are the same and send them to the all cluster remediator.
 * The aim is to minimize the number of generated LinksUpdate jobs in a setup
 * where there are many clusters. If the same elements are to be verified on
 * all the clusters then it is equivalent and more efficient to send these
 * elements to all clusters using the [ "cluster" => null ] job param as some
 * steps (link counting) will be shared accross all the clusters as opposed
 * to sending a LinksUpdate job per cluster.
 */
class MultiClusterRemediatorHelper {
    /** @var Remediator[] */
    private $perClusterRemediators;

    /** @var AllClustersQueueingRemediator */
    private $allClusterRemediator;

    /** @var BufferedRemediator[] */
    private $perClusterBufferedRemediator;

    /**
     * @param Remediator[] $perClusterRemediators
     * @param BufferedRemediator[] $perClusterBufferedRemediator
     * @param AllClustersQueueingRemediator $allClusterRemediator
     * @see \CirrusSearch\Job\CirrusGenericJob::decideClusters()
     */
    public function __construct(
        array $perClusterRemediators,
        array $perClusterBufferedRemediator,
        AllClustersQueueingRemediator $allClusterRemediator
    ) {
        if ( array_keys( $perClusterRemediators ) != array_keys( $perClusterBufferedRemediator ) ) {
            throw new InvalidArgumentException( '$perClusterRemediators and $perClusterBufferedRemediator must have the same keys' );
        }
        $this->perClusterRemediators = $perClusterRemediators;
        $this->perClusterBufferedRemediator = $perClusterBufferedRemediator;
        $this->allClusterRemediator = $allClusterRemediator;
    }

    /**
     * Evaluate if all BufferedRemediator contain the same elements and replay
     * the recorded actions to the all cluster remediator or to their corresponding
     * remediators otherwize.
     */
    public function sendBatch() {
        $allSame = true;
        $firstRemediator = null;
        foreach ( $this->perClusterBufferedRemediator as $remediator ) {
            if ( $firstRemediator === null ) {
                $firstRemediator = $remediator;
            } elseif ( !$remediator->hasSameActions( $firstRemediator ) ) {
                $allSame = false;
                break;
            }
        }
        if ( $allSame && $this->allClusterRemediator->canSendOptimizedJob( array_keys( $this->perClusterRemediators ) ) ) {
            $firstRemediator->replayOn( $this->allClusterRemediator );
        } else {
            foreach ( $this->perClusterBufferedRemediator as $cluster => $remediator ) {
                $remediator->replayOn( $this->perClusterRemediators[$cluster] );
            }
        }
        foreach ( $this->perClusterBufferedRemediator as $remediator ) {
            $remediator->resetActions();
        }
    }
}