From 27c8c16e94aeba1e9ecda146c1373cbff42be743 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Mon, 9 May 2022 10:43:23 -0300 Subject: [PATCH 1/6] Use new functions to handle ep_last_cli_index --- includes/classes/Command.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/includes/classes/Command.php b/includes/classes/Command.php index b3eda79261..dbd13a613a 100644 --- a/includes/classes/Command.php +++ b/includes/classes/Command.php @@ -1036,11 +1036,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'] ) ); From e0febe8a35a64c354098bc1b314a438747516ecb Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Mon, 9 May 2022 10:43:53 -0300 Subject: [PATCH 2/6] Use log instead of success, as it may be actually coming from a failure --- includes/classes/Command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/classes/Command.php b/includes/classes/Command.php index dbd13a613a..f1e29e9b1d 100644 --- a/includes/classes/Command.php +++ b/includes/classes/Command.php @@ -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' ) ); } /** From 70ab6588642b77b27d2ff352366b65d47f9f51f9 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Mon, 9 May 2022 10:45:30 -0300 Subject: [PATCH 3/6] New get-last-sync command --- includes/classes/Command.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/includes/classes/Command.php b/includes/classes/Command.php index f1e29e9b1d..4e59055666 100644 --- a/includes/classes/Command.php +++ b/includes/classes/Command.php @@ -1019,6 +1019,26 @@ public function get_indexing_status( $args, $assoc_args ) { $this->pretty_json_encode( $indexing_status, ! empty( $assoc_args['pretty'] ) ); } + /** + * Returns a JSON array with the results of the last index (if present) of 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) of an empty array. * From 722e2dad21d112a8c4fc9c00dc218ecb06b1ec45 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Mon, 9 May 2022 10:51:03 -0300 Subject: [PATCH 4/6] IndexHelper::get_last_index + namespace cleanup --- includes/classes/Screen/Sync.php | 12 +++++------- includes/partials/sync-page.php | 4 +--- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/includes/classes/Screen/Sync.php b/includes/classes/Screen/Sync.php index 5134d0151b..8a419f9ac6 100644 --- a/includes/classes/Screen/Sync.php +++ b/includes/classes/Screen/Sync.php @@ -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. @@ -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'] ), @@ -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; diff --git a/includes/partials/sync-page.php b/includes/partials/sync-page.php index d3cafc7401..0889e2379b 100644 --- a/includes/partials/sync-page.php +++ b/includes/partials/sync-page.php @@ -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'] ); ?> From 471f9d7f156e3b19b9127b6143cf6d8f5525e635 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Mon, 9 May 2022 10:55:02 -0300 Subject: [PATCH 5/6] Handle fatal errors during syncs --- includes/classes/IndexHelper.php | 95 ++++++++++++++++++++++++++++---- 1 file changed, 83 insertions(+), 12 deletions(-) diff --git a/includes/classes/IndexHelper.php b/includes/classes/IndexHelper.php index 427b14a21e..5d27626b87 100644 --- a/includes/classes/IndexHelper.php +++ b/includes/classes/IndexHelper.php @@ -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; @@ -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']; @@ -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; @@ -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']; @@ -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 @@ -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 = [ @@ -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. * @@ -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. * From 9ae8f5805b4d0ef7509556577c479dccab078678 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Mon, 9 May 2022 11:06:02 -0300 Subject: [PATCH 6/6] Fix typo in docs --- includes/classes/Command.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/classes/Command.php b/includes/classes/Command.php index 4e59055666..1973bb8ccb 100644 --- a/includes/classes/Command.php +++ b/includes/classes/Command.php @@ -1020,7 +1020,7 @@ public function get_indexing_status( $args, $assoc_args ) { } /** - * Returns a JSON array with the results of the last 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 * @@ -1040,7 +1040,7 @@ public function get_last_sync( $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 CLI index (if present) or an empty array. * * ## OPTIONS *