Add re-migrate support to HPOS CLI. (#38690)

This commit is contained in:
Ron Rennick 2023-06-14 10:05:38 -03:00 committed by GitHub
commit 960fa1035a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 33 deletions

View File

@ -0,0 +1,4 @@
Significance: patch
Type: add
Add re-migrate support to HPOS CLI.

View File

@ -304,6 +304,11 @@ class CLIRunner {
* ---
* default: Output of function `wc_get_order_types( 'cot-migration' )`
*
* [--re-migrate]
* : Attempt to re-migrate orders that failed verification. You should only use this option when you have never run the site with HPOS as authoritative source of order data yet, or you have manually checked the reported errors, otherwise, you risk stale data overwriting the more recent data.
* This option can only be enabled when --verbose flag is also set.
* default: false
*
* ## EXAMPLES
*
* # Verify migrated order data, 500 orders at a time.
@ -327,6 +332,7 @@ class CLIRunner {
'end-at' => - 1,
'verbose' => false,
'order-types' => '',
're-migrate' => false,
)
);
@ -340,6 +346,7 @@ class CLIRunner {
$batch_size = ( (int) $assoc_args['batch-size'] ) === 0 ? 500 : (int) $assoc_args['batch-size'];
$verbose = (bool) $assoc_args['verbose'];
$order_types = wc_get_order_types( 'cot-migration' );
$remigrate = (bool) $assoc_args['re-migrate'];
if ( ! empty( $assoc_args['order-types'] ) ) {
$passed_order_types = array_map( 'trim', explode( ',', $assoc_args['order-types'] ) );
$order_types = array_intersect( $order_types, $passed_order_types );
@ -415,6 +422,36 @@ class CLIRunner {
$errors
)
);
if ( $remigrate ) {
WP_CLI::warning(
sprintf(
__( 'Attempting to remigrate...', 'woocommerce' )
)
);
$failed_ids = array_keys( $failed_ids_in_current_batch );
$this->synchronizer->process_batch( $failed_ids );
$errors_in_remigrate_batch = $this->post_to_cot_migrator->verify_migrated_orders( $failed_ids );
$errors_in_remigrate_batch = $this->verify_meta_data( $failed_ids, $errors_in_remigrate_batch );
if ( count( $errors_in_remigrate_batch ) > 0 ) {
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- This is a CLI command and debugging code is intended.
$formatted_errors = print_r( $errors_in_remigrate_batch, true );
WP_CLI::warning(
sprintf(
/* Translators: %1$d is number of errors and %2$s is the formatted array of order IDs. */
_n(
'%1$d error found: %2$s when re-migrating order. Please review the error above.',
'%1$d errors found: %2$s when re-migrating orders. Please review the errors above.',
count( $errors_in_remigrate_batch ),
'woocommerce'
),
count( $errors_in_remigrate_batch ),
$formatted_errors
)
);
} else {
WP_CLI::warning( 'Re-migration successful.', 'woocommerce' );
}
}
}
$progress->tick();

View File

@ -243,13 +243,7 @@ abstract class MetaToCustomTableMigrator extends TableMigrator {
$to_insert = array_diff_key( $data['data'], $existing_records );
$this->process_insert_batch( $to_insert );
$existing_records = array_filter(
$existing_records,
function( $record_data ) {
return '1' === $record_data->modified;
}
);
$to_update = array_intersect_key( $data['data'], $existing_records );
$to_update = array_intersect_key( $data['data'], $existing_records );
$this->process_update_batch( $to_update, $existing_records );
}
@ -357,38 +351,13 @@ abstract class MetaToCustomTableMigrator extends TableMigrator {
$entity_id_placeholder = implode( ',', array_fill( 0, count( $entity_ids ), '%d' ) );
// Additional SQL to check if the row needs update according to the column mapping.
// The IFNULL and CHAR(0) "hack" is needed because NULLs can't be directly compared in SQL.
$modified_selector = array();
$core_column_mapping = array_filter(
$this->core_column_mapping,
function( $mapping ) {
return ! isset( $mapping['select_clause'] );
}
);
foreach ( $core_column_mapping as $column_name => $mapping ) {
if ( $column_name === $source_primary_key_column ) {
continue;
}
$modified_selector[] =
"IFNULL(source.$column_name,CHAR(0)) != IFNULL(destination.{$mapping['destination']},CHAR(0))"
. ( 'string' === $mapping['type'] ? ' COLLATE ' . $wpdb->collate : '' );
}
if ( empty( $modified_selector ) ) {
$modified_selector = ', 1 AS modified';
} else {
$modified_selector = trim( implode( ' OR ', $modified_selector ) );
$modified_selector = ", if( $modified_selector, 1, 0 ) AS modified";
}
$additional_where = $this->get_additional_where_clause_for_get_data_to_insert_or_update( $entity_ids );
$already_migrated_entity_ids = $this->db_get_results(
$wpdb->prepare(
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare -- All columns and table names are hardcoded.
"
SELECT source.`$source_primary_key_column` as source_id, destination.`$destination_primary_key_column` as destination_id $modified_selector
SELECT source.`$source_primary_key_column` as source_id, destination.`$destination_primary_key_column` as destination_id
FROM `$destination_table` destination
JOIN `$source_table` source ON source.`$source_destination_join_column` = destination.`$destination_source_join_column`
WHERE source.`$source_primary_key_column` IN ( $entity_id_placeholder ) $additional_where