Commit e2163ad0ad3 for woocommerce

commit e2163ad0ad3450756b8d4decab2d1cddf35f1438
Author: Peter Petrov <peter.petrov89@gmail.com>
Date:   Tue Sep 15 13:34:10 2026 +0300

    Fix emailed Analytics report exports that never arrive (#68621)

    Keep the report export status option out of autoloaded options

diff --git a/plugins/woocommerce/changelog/fix-analytics-export-email-never-arrives b/plugins/woocommerce/changelog/fix-analytics-export-email-never-arrives
new file mode 100644
index 00000000000..af8b12e1fd4
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-analytics-export-email-never-arrives
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fix emailed Analytics report exports never arriving on stores with a persistent object cache.
diff --git a/plugins/woocommerce/src/Admin/ReportExporter.php b/plugins/woocommerce/src/Admin/ReportExporter.php
index ffd9b087cdb..f9d3d49a0f7 100644
--- a/plugins/woocommerce/src/Admin/ReportExporter.php
+++ b/plugins/woocommerce/src/Admin/ReportExporter.php
@@ -199,7 +199,9 @@ class ReportExporter {

 		$exports_status[ $status_key ] = $percentage;

-		update_option( self::EXPORT_STATUS_OPTION, $exports_status );
+		// Not autoloaded: a persistent object cache can write back a stale copy of the autoloaded options from another
+		// request, which left the email action reading an old percentage and never sending the download link.
+		update_option( self::EXPORT_STATUS_OPTION, $exports_status, false );
 	}

 	/**
diff --git a/plugins/woocommerce/tests/php/src/Admin/ReportExporterTest.php b/plugins/woocommerce/tests/php/src/Admin/ReportExporterTest.php
index d5660b6524f..3c9b09f0745 100644
--- a/plugins/woocommerce/tests/php/src/Admin/ReportExporterTest.php
+++ b/plugins/woocommerce/tests/php/src/Admin/ReportExporterTest.php
@@ -538,4 +538,20 @@ class ReportExporterTest extends WC_Unit_Test_Case {
 			'The download handler should be registered.'
 		);
 	}
+
+	/**
+	 * @testdox Export progress is saved outside the autoloaded options, and an autoloaded copy is moved out on the next save.
+	 */
+	public function test_export_progress_is_not_autoloaded(): void {
+		global $wpdb;
+
+		update_option( ReportExporter::EXPORT_STATUS_OPTION, array( 'orders:earlier' => 100 ), true );
+
+		ReportExporter::update_export_percentage_complete( 'orders', 'current', 50 );
+
+		$this->assertArrayNotHasKey( ReportExporter::EXPORT_STATUS_OPTION, wp_load_alloptions(), 'A persistent object cache can write stale copies of the autoloaded options back, so export progress must not live there.' );
+		$this->assertSame( 'off', $wpdb->get_var( $wpdb->prepare( "SELECT autoload FROM {$wpdb->options} WHERE option_name = %s", ReportExporter::EXPORT_STATUS_OPTION ) ) );
+		$this->assertSame( 100, ReportExporter::get_export_percentage_complete( 'orders', 'earlier' ), 'Progress of earlier exports should survive the move.' );
+		$this->assertSame( 50, ReportExporter::get_export_percentage_complete( 'orders', 'current' ) );
+	}
 }