Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Syncs: status and error handling #2748

Merged
merged 6 commits into from
May 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions includes/classes/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -982,7 +982,7 @@ public function clear_index() {
*/
do_action( 'ep_cli_after_clear_index' );

WP_CLI::success( esc_html__( 'Index cleared.', 'elasticpress' ) );
WP_CLI::log( esc_html__( 'Index cleared.', 'elasticpress' ) );
}

/**
Expand Down Expand Up @@ -1020,7 +1020,27 @@ public function get_indexing_status( $args, $assoc_args ) {
}

/**
* Returns a JSON array with the results of the last CLI index (if present) of an empty array.
* Returns a JSON array with the results of the last index (if present) or an empty array.
*
* ## OPTIONS
*
* [--pretty]
* : Use this flag to render a pretty-printed version of the JSON response.
*
* @subcommand get-last-sync
* @alias get-last-index
* @since 4.2.0
* @param array $args Positional CLI args.
* @param array $assoc_args Associative CLI args.
*/
public function get_last_sync( $args, $assoc_args ) {
$last_sync = \ElasticPress\IndexHelper::factory()->get_last_index();

$this->pretty_json_encode( $last_sync, ! empty( $assoc_args['pretty'] ) );
}

/**
* Returns a JSON array with the results of the last CLI index (if present) or an empty array.
*
* ## OPTIONS
*
Expand All @@ -1036,11 +1056,10 @@ public function get_indexing_status( $args, $assoc_args ) {
* @param array $assoc_args Associative CLI args.
*/
public function get_last_cli_index( $args, $assoc_args ) {

$last_sync = get_site_option( 'ep_last_cli_index', array() );
$last_sync = Utils\get_option( 'ep_last_cli_index', array() );

if ( isset( $assoc_args['clear'] ) ) {
delete_site_option( 'ep_last_cli_index' );
Utils\delete_option( 'ep_last_cli_index' );
}

$this->pretty_json_encode( $last_sync, ! empty( $assoc_args['pretty'] ) );
Expand Down
95 changes: 83 additions & 12 deletions includes/classes/IndexHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ public function setup() {
* @param array $args Arguments.
*/
public function full_index( $args ) {
register_shutdown_function( [ $this, 'handle_index_error' ] );

$this->index_meta = Utils\get_indexing_status();
$this->args = $args;

Expand Down Expand Up @@ -717,16 +719,11 @@ function( $item ) {
}

/**
* Make the necessary clean up after a sync item of the stack was completely done.
* Update the sync info with the totals from the last sync item.
*
* @since 4.0.0
* @return void
* @since 4.2.0
*/
protected function index_cleanup() {
wp_reset_postdata();

$indexable = Indexables::factory()->get( $this->index_meta['current_sync_item']['indexable'] );

protected function update_totals_from_current_sync_item() {
$current_sync_item = $this->index_meta['current_sync_item'];

$this->index_meta['totals']['total'] += $current_sync_item['total'];
Expand All @@ -737,6 +734,22 @@ protected function index_cleanup() {
$this->index_meta['totals']['errors'],
$current_sync_item['errors']
);
}

/**
* Make the necessary clean up after a sync item of the stack was completely done.
*
* @since 4.0.0
* @return void
*/
protected function index_cleanup() {
wp_reset_postdata();

$this->update_totals_from_current_sync_item();

$indexable = Indexables::factory()->get( $this->index_meta['current_sync_item']['indexable'] );

$current_sync_item = $this->index_meta['current_sync_item'];

if ( $current_sync_item['failed'] ) {
$this->index_meta['current_sync_item']['failed'] = 0;
Expand Down Expand Up @@ -785,11 +798,11 @@ protected function index_cleanup() {
}

/**
* Make the necessary clean up after everything was sync'd.
* Update last sync info.
*
* @since 4.0.0
* @since 4.2.0
*/
protected function full_index_complete() {
protected function update_last_index() {
$start_time = $this->index_meta['start_time'];
$totals = $this->index_meta['totals'];

Expand All @@ -802,6 +815,15 @@ protected function full_index_complete() {
$totals['total_time'] = microtime( true ) - $start_time;
Utils\update_option( 'ep_last_cli_index', $totals, false );
Utils\update_option( 'ep_last_index', $totals, false );
}

/**
* Make the necessary clean up after everything was sync'd.
*
* @since 4.0.0
*/
protected function full_index_complete() {
$this->update_last_index();

/**
* Fires after executing a reindex
Expand Down Expand Up @@ -885,7 +907,7 @@ protected function output( $message_text, $type = 'info', $context = '' ) {
Utils\update_option( 'ep_index_meta', $this->index_meta );
} else {
Utils\delete_option( 'ep_index_meta' );
$totals = Utils\get_option( 'ep_last_index' );
$totals = $this->get_last_index();
}

$message = [
Expand Down Expand Up @@ -988,6 +1010,16 @@ public function is_full_reindexing( $indexable_slug, $blog_id = null ) {
return apply_filters( "ep_is_full_reindexing_{$indexable_slug}", $is_full_reindexing );
}

/**
* Get the last index/sync meta information.
*
* @since 4.2.0
* @return array
*/
public function get_last_index() {
return Utils\get_option( 'ep_last_index', [] );
}

/**
* Check if an object should be indexed or skipped.
*
Expand Down Expand Up @@ -1089,6 +1121,45 @@ public function get_index_meta() {
return Utils\get_option( 'ep_index_meta', [] );
}

/**
* Handle fatal errors during syncs.
*
* Logs the error and clears the sync status, preventing the sync status from being stuck.
*
* @since 4.2.0
*/
public function handle_index_error() {
$error = error_get_last();
if ( empty( $error['type'] ) || E_ERROR !== $error['type'] ) {
return;
}

$this->update_totals_from_current_sync_item();

$totals = $this->index_meta['totals'];

$this->index_meta['totals']['errors'][] = $error['message'];
$this->index_meta['totals']['failed'] = $totals['total'] - ( $totals['synced'] + $totals['skipped'] );
$this->update_last_index();

/**
* Fires after a sync failed due to a PHP fatal error.
*
* @since 4.2.0
* @hook ep_after_sync_error
* @param {array} $error The error
*/
do_action( 'ep_after_sync_error', $error );

$this->output_error(
sprintf(
/* translators: Error message */
esc_html__( 'Index failed: %s', 'elasticpress' ),
$error['message']
)
);
}

/**
* Return singleton instance of class.
*
Expand Down
12 changes: 5 additions & 7 deletions includes/classes/Screen/Sync.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@

namespace ElasticPress\Screen;

use ElasticPress\Features as Features;
use ElasticPress\Screen as Screen;
use ElasticPress\Utils as Utils;
use ElasticPress\Elasticsearch as Elasticsearch;
use ElasticPress\Indexables as Indexables;
use ElasticPress\IndexHelper;
use ElasticPress\Screen;
use ElasticPress\Utils;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
Expand Down Expand Up @@ -89,7 +87,7 @@ public function action_wp_ajax_ep_index() {
exit;
}

\ElasticPress\IndexHelper::factory()->full_index(
IndexHelper::factory()->full_index(
[
'method' => 'dashboard',
'put_mapping' => ! empty( $_REQUEST['put_mapping'] ),
Expand Down Expand Up @@ -167,7 +165,7 @@ public function admin_enqueue_scripts() {
$data['index_meta'] = $index_meta;
}

$ep_last_index = Utils\get_option( 'ep_last_index' );
$ep_last_index = IndexHelper::factory()->get_last_index();

if ( ! empty( $ep_last_index ) ) {
$data['ep_last_sync_date'] = ! empty( $ep_last_index['end_date_time'] ) ? $ep_last_index['end_date_time'] : false;
Expand Down
4 changes: 1 addition & 3 deletions includes/partials/sync-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
* @package elasticpress
*/

use ElasticPress\Utils as Utils;

$ep_last_index = Utils\get_option( 'ep_last_index' );
$ep_last_index = \ElasticPress\IndexHelper::factory()->get_last_index();
$ep_last_sync_has_error = ! empty( $ep_last_index['failed'] );

?>
Expand Down