Skip to content

Commit

Permalink
Search: Default state is no active index versions
Browse files Browse the repository at this point in the history
  • Loading branch information
rebeccahum committed May 3, 2023
1 parent 9a736d9 commit a77682a
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 131 deletions.
30 changes: 10 additions & 20 deletions search/includes/classes/class-versioning.php
Original file line number Diff line number Diff line change
Expand Up @@ -227,36 +227,22 @@ public function get_versions( Indexable $indexable, bool $provide_default = true
$versions = [];

if ( $indexable->global ) {
$versions = get_site_option( self::INDEX_VERSIONS_OPTION_GLOBAL, array() );
$versions = get_site_option( self::INDEX_VERSIONS_OPTION_GLOBAL );
} else {
$versions = get_option( self::INDEX_VERSIONS_OPTION, array() );
$versions = get_option( self::INDEX_VERSIONS_OPTION );
}

$slug = $indexable->slug;

if ( ! $this->versions_array_has_slug( $versions, $slug ) ) {
if ( $provide_default ) {
return array(
1 => array(
'number' => 1,
'active' => true,
'created_time' => null, // We don't know when it was actually created
'activated_time' => null,
),
);
} else {
return [];
}
if ( ! is_array( $versions ) || ! isset( $versions[ $indexable->slug ] ) ||
( isset( $versions[ $indexable->slug ] ) && ! is_array( $versions[ $indexable->slug ] ) ) ) {
return [];
}

// Normalize the versions to ensure consistency (have all fields, etc)
return array_map( array( $this, 'normalize_version' ), $versions[ $slug ] );
}

private function versions_array_has_slug( $versions, $slug ) {
return is_array( $versions ) && isset( $versions[ $slug ] ) && is_array( $versions[ $slug ] ) && ! empty( $versions[ $slug ] );
}

/**
* Normalize the fields of a version, to handle old or incomplete data
*
Expand Down Expand Up @@ -426,7 +412,11 @@ public function get_version( Indexable $indexable, $version_number ) {
public function add_version( Indexable $indexable ) {
$versions = $this->get_versions( $indexable );

$new_version_number = $this->get_next_version_number( $versions );
if ( empty( $versions ) ) {
$new_version_number = 1;
} else {
$new_version_number = $this->get_next_version_number( $versions );
}

if ( ! $new_version_number ) {
return new WP_Error( 'unable-to-get-next-version', 'Unable to determine next index version' );
Expand Down
104 changes: 74 additions & 30 deletions search/includes/classes/commands/class-corecommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,44 +125,88 @@ private function list_indexes() {
}

protected function maybe_setup_index_version( $assoc_args ) {
if ( array_key_exists( 'version', $assoc_args ) || array_key_exists( 'using-versions', $assoc_args ) ) {
$version_number = '';
$using_versions = $assoc_args['using-versions'] ?? false;
if ( $assoc_args['version'] ?? false ) {
$setup_flag = isset( $assoc_args['setup'] ) && $assoc_args['setup'];
$using_versions_flag = isset( $assoc_args['using-versions'] ) && $assoc_args['using-versions'];
$version_flag = isset( $assoc_args['version'] ) && $assoc_args['version'];

// For each indexable specified, override the version
if ( ! isset( $assoc_args['indexables'] ) ) {
$indexables = \ElasticPress\Indexables::factory()->get_all();
if ( empty( $indexables ) ) {
WP_CLI::Error( 'No indexables found!' );
}
} else {
$indexables = $this->parse_indexables( $assoc_args );
}

$search = \Automattic\VIP\Search\Search::instance();
foreach ( $indexables as $indexable ) {
if ( ! $version_flag && ! $using_versions_flag && ! $setup_flag ) {
// No flags set, so we need to get the active version to index.
$version_number = $search->versioning->get_active_version_number( $indexable );
if ( is_wp_error( $version_number ) ) {
WP_CLI::Error( sprintf( 'No active version found for %s', $indexable->slug ) );
}
$this->set_version( $indexable, $version_number );
continue;
}

if ( $version_flag ) {
// If version flag passed in, explicitly use that. This will also cover a --version && --setup case.
$version_number = $assoc_args['version'];
} elseif ( $using_versions ) {
$version_number = 'next';
$version = $search->versioning->get_version( $indexable, $version_number );
if ( ! $version ) {
WP_CLI::Error( sprintf( 'No version found for %d for %s', $version_number, $indexable->slug ) );
}

$this->set_version( $indexable, $version_number );
continue;
}

if ( $version_number ) {
$search = \Automattic\VIP\Search\Search::instance();

// For each indexable specified, override the version
$indexables = $this->parse_indexables( $assoc_args );

if ( $using_versions ) {
foreach ( $indexables as $indexable ) {
$current_versions = $search->versioning->get_versions( $indexable );
if ( count( $current_versions ) > 1 ) {
WP_CLI::error( sprintf(
'There needs to be only one version per indexable in order to automatically use versions to reindex. Please remove inactive versions for indexable "%s".',
$indexable->slug
) );
}
}
$current_versions = $search->versioning->get_versions( $indexable );
if ( $using_versions_flag ) {
if ( count( $current_versions ) > 1 ) {
WP_CLI::error( sprintf(
'There needs to be only one version per indexable in order to automatically use versions to reindex. Please remove inactive versions for indexable "%s".',
$indexable->slug
) );
}
if ( empty( $current_versions ) ) {
WP_CLI::error( sprintf(
'There needs to be at least one version in order to use the --using-versions parameter. Please add a version for indexable "%s".',
$indexable->slug
) );
}

foreach ( $indexables as $indexable ) {
$result = $search->versioning->add_version( $indexable );
if ( is_wp_error( $result ) ) {
WP_CLI::error( sprintf( 'Error adding new version: %s', $result->get_error_message() ) );
}
$version_number = $search->versioning->get_active_version_number( $indexable );
if ( is_wp_error( $version_number ) ) {
WP_CLI::Error( sprintf( 'No active version found for %s. Must have an active version to use the --using-versions parameter.', $indexable->slug ) );
}
$result = $search->versioning->add_version( $indexable );
if ( is_wp_error( $result ) ) {
WP_CLI::error( sprintf( 'Error adding new version: %s', $result->get_error_message() ) );
}
$version_number = 'next';
} else {
if ( empty( $current_versions ) ) {
// If no versions exist, create new version and activate it.
$result = $search->versioning->add_version( $indexable );
if ( is_wp_error( $result ) ) {
WP_CLI::error( sprintf( 'Error adding new version: %s', $result->get_error_message() ) );
}
$result = $search->versioning->activate_version( $indexable, 1 ); // Activate first version
if ( is_wp_error( $result ) ) {
WP_CLI::error( sprintf( 'Error activating version 1: %s', $result->get_error_message() ) );
}
}

foreach ( $indexables as $indexable ) {
$this->set_version( $indexable, $version_number );
// Check that there is an active version to use before assigning $version_number.
$active_version = $search->versioning->get_active_version_number( $indexable );
if ( is_wp_error( $active_version ) ) {
$result = $search->versioning->activate_version( $indexable, array_key_first( $current_versions ) ); // Activate first version
}
$version_number = 'active';
}
$this->set_version( $indexable, $version_number );
}
}

Expand Down
15 changes: 15 additions & 0 deletions tests/search/includes/classes/test-class-health.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,24 @@ class Health_Test extends WP_UnitTestCase {

public function tearDown(): void {
Constant_Mocker::clear();
delete_option( Versioning::INDEX_VERSIONS_OPTION );

parent::tearDown();
}

public function setUp(): void {
do_action( 'plugins_loaded' );

parent::setUp();

Constant_Mocker::define( 'VIP_ORIGIN_DATACENTER', 'foo' );

// Set-up initial version
$indexable = \ElasticPress\Indexables::factory()->get( 'post' );
self::$search_instance->versioning->add_version( $indexable );
self::$search_instance->versioning->activate_version( $indexable, 1 );
}

public static function setUpBeforeClass(): void {
self::$search_instance = new \Automattic\VIP\Search\Search();
self::$search_instance->init();
Expand Down
26 changes: 18 additions & 8 deletions tests/search/includes/classes/test-class-queue.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,6 @@ public static function setUpBeforeClass(): void {
}

require_once __DIR__ . '/../../../../search/search.php';

\Automattic\VIP\Search\Search::instance()->init();

// Required so that EP registers the Indexables
do_action( 'plugins_loaded' );

// Users indexable doesn't get registered by default, but we have tests that queue user objects
\ElasticPress\Indexables::factory()->register( new \ElasticPress\Indexable\User\User() );
}

public function setUp(): void {
Expand All @@ -49,6 +41,22 @@ public function setUp(): void {
$this->es = \Automattic\VIP\Search\Search::instance();
$this->es->init();

// Required so that EP registers the Indexables
do_action( 'plugins_loaded' );

// Users indexable doesn't get registered by default, but we have tests that queue user objects
\ElasticPress\Indexables::factory()->register( new \ElasticPress\Indexable\User\User() );

// Create user indexable and activate it
$user_indexable = \ElasticPress\Indexables::factory()->get( 'user' );
$this->es->versioning->add_version( $user_indexable );
$this->es->versioning->activate_version( $user_indexable, 1 );

// Create post indexable and activate it
$post_indexable = \ElasticPress\Indexables::factory()->get( 'post' );
$this->es->versioning->add_version( $post_indexable );
$this->es->versioning->activate_version( $post_indexable, 1 );

$this->queue = $this->es->queue;

$this->queue->schema->prepare_table();
Expand All @@ -61,6 +69,8 @@ public function setUp(): void {
public function tearDown(): void {
remove_filter( 'ep_do_intercept_request', [ $this, 'filter_index_exists_request_ok' ], PHP_INT_MAX );

delete_option( $this->es->versioning::INDEX_VERSIONS_OPTION );

parent::tearDown();
}

Expand Down
24 changes: 24 additions & 0 deletions tests/search/includes/classes/test-class-search.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@ public function setUp(): void {
}, E_USER_WARNING );
}

public function test_initial_state_no_versions() {
$this->init_es();

$indexable = \ElasticPress\Indexables::factory()->get( 'post' );
$versions = $this->search_instance->versioning->get_versions( $indexable );

$this->assertEquals( [], $versions, 'There should be no versions in the initial state' );

$skip = apply_filters( 'ep_skip_query_integration', false );
$this->assertTrue( $skip );
}

public function tearDown(): void {
restore_error_handler();

Expand All @@ -64,13 +76,18 @@ public function test_query_es_with_invalid_type() {
* Test `ep_index_name` filter for ElasticPress + VIP Search
*/
public function test__vip_search_filter_ep_index_name() {
Constant_Mocker::define( 'VIP_ORIGIN_DATACENTER', 'bar' );
$this->init_es();

$indexable = \ElasticPress\Indexables::factory()->get( 'post' );
$this->search_instance->versioning->add_version( $indexable );
$this->search_instance->versioning->activate_version( $indexable, 1 );

$index_name = apply_filters( 'ep_index_name', 'index-name', 1, $indexable );

$this->assertEquals( 'vip-123-post-1', $index_name );

delete_option( $this->search_instance->versioning::INDEX_VERSIONS_OPTION );
}

/**
Expand All @@ -79,13 +96,18 @@ public function test__vip_search_filter_ep_index_name() {
* On "global" indexes, such as users, no blog id will be present
*/
public function test__vip_search_filter_ep_index_name_global_index() {
Constant_Mocker::define( 'VIP_ORIGIN_DATACENTER', 'bar' );

$this->init_es();

$indexable = \ElasticPress\Indexables::factory()->get( 'post' );
$this->search_instance->versioning->add_version( $indexable );
$this->search_instance->versioning->activate_version( $indexable, 1 );

$index_name = apply_filters( 'ep_index_name', 'index-name', null, $indexable );

$this->assertEquals( 'vip-123-post', $index_name );
delete_option( $this->search_instance->versioning::INDEX_VERSIONS_OPTION );
}

/**
Expand Down Expand Up @@ -294,6 +316,8 @@ public function test__vip_search_filter_ep_index_name_with_overridden_version()
Constant_Mocker::define( 'FILES_CLIENT_SITE_ID', 123 );

$indexable = \ElasticPress\Indexables::factory()->get( 'post' );
$this->search_instance->versioning->add_version( $indexable );
$this->search_instance->versioning->activate_version( $indexable, 1 );

add_filter( 'ep_do_intercept_request', [ $this, 'filter_ok_es_requests' ], PHP_INT_MAX, 5 );

Expand Down
13 changes: 13 additions & 0 deletions tests/search/includes/classes/test-class-settingshealthjob.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,22 @@ public static function tearDownAfterClass(): void {
public function setUp(): void {
parent::setUp();

Constant_Mocker::define( 'VIP_ORIGIN_DATACENTER', 'foo' );

\Automattic\VIP\Prometheus\Plugin::get_instance()->init_registry();
self::$search->load_collector();
\Automattic\VIP\Prometheus\Plugin::get_instance()->load_collectors();

$indexable = \ElasticPress\Indexables::factory()->get( 'post' );
self::$search->versioning->add_version( $indexable );
self::$search->versioning->activate_version( $indexable, 1 );
}

public function tearDown(): void {
parent::tearDown();

Constant_Mocker::clear();
delete_option( Versioning::INDEX_VERSIONS_OPTION );
}

public function test__process_indexables_settings_health_results__reports_error() {
Expand Down
Loading

0 comments on commit a77682a

Please sign in to comment.