From 78df24aa94c4cffd6b3595fd87ea9ff5cee5b303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?batuhan=20i=C3=A7=C3=B6z?= Date: Fri, 7 Aug 2026 18:04:02 +0200 Subject: [PATCH] Refresh sync state after CAS conflicts --- includes/class-spacefast-sync-state.php | 5 ++++- readme.txt | 5 ++++- spacefast-wordpress.php | 4 ++-- tests/acceptance/wordpress.php | 2 +- tests/behavior.php | 22 +++++++++++++++++++--- 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/includes/class-spacefast-sync-state.php b/includes/class-spacefast-sync-state.php index 1c0959e..af6ef35 100644 --- a/includes/class-spacefast-sync-state.php +++ b/includes/class-spacefast-sync-state.php @@ -202,8 +202,11 @@ private static function compare_and_swap_option( string $option, $expected, $nex maybe_serialize( $expected ) ) ); + // Raw SQL bypasses WordPress's option-cache maintenance. A failed CAS + // means another request changed the row, so the next retry must reload + // that newer value instead of comparing the same stale cached value. + wp_cache_delete( $option, 'options' ); if ( 1 === $updated ) { - wp_cache_delete( $option, 'options' ); return true; } return false; diff --git a/readme.txt b/readme.txt index 9392f4b..95aed2e 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: spacefast Tags: static site, headless cms, simply static, deployment Requires at least: 6.5 Requires PHP: 8.1 -Stable tag: 0.5.2 +Stable tag: 0.5.3 License: GPLv2 or later Publish a Simply Static export to Spacefast, or rebuild a headless site when WordPress content changes. @@ -31,6 +31,9 @@ OAuth access is limited to the Team you authorize and the mode you choose. WordP == Changelog == += 0.5.3 = +* Reload the WordPress option cache after a concurrent sync-state update so large publishes keep progressing. + = 0.5.2 = * Keep large first-publish upload receipts intact for WordPress sites with thousands of files. diff --git a/spacefast-wordpress.php b/spacefast-wordpress.php index 8718f88..29316cb 100644 --- a/spacefast-wordpress.php +++ b/spacefast-wordpress.php @@ -3,7 +3,7 @@ * Plugin Name: Spacefast * Plugin URI: https://spacefast.com/ * Description: Publishes static WordPress exports or rebuilds a headless Spacefast site. - * Version: 0.5.2 + * Version: 0.5.3 * Update URI: https://github.com/spacefast/wordpress * Requires at least: 6.5 * Requires PHP: 8.1 @@ -14,7 +14,7 @@ defined( 'ABSPATH' ) || exit; -define( 'SPACEFAST_WORDPRESS_VERSION', '0.5.2' ); +define( 'SPACEFAST_WORDPRESS_VERSION', '0.5.3' ); define( 'SPACEFAST_WORDPRESS_FILE', __FILE__ ); require_once __DIR__ . '/includes/class-spacefast-settings.php'; diff --git a/tests/acceptance/wordpress.php b/tests/acceptance/wordpress.php index fe447ff..46b99aa 100644 --- a/tests/acceptance/wordpress.php +++ b/tests/acceptance/wordpress.php @@ -113,7 +113,7 @@ function spacefast_accept( bool $condition, string $message ): void { ); $plugin = get_plugin_data( WP_PLUGIN_DIR . '/spacefast-wordpress/spacefast-wordpress.php', false, false ); -spacefast_accept( '0.5.2' === $plugin['Version'], 'Unexpected plugin version.' ); +spacefast_accept( '0.5.3' === $plugin['Version'], 'Unexpected plugin version.' ); spacefast_accept( 'https://github.com/spacefast/wordpress' === $plugin['UpdateURI'], 'Update URI is missing.' ); Spacefast_Settings::disconnect(); diff --git a/tests/behavior.php b/tests/behavior.php index 6f3ef95..0a9c193 100644 --- a/tests/behavior.php +++ b/tests/behavior.php @@ -9,6 +9,8 @@ define( 'SPACEFAST_WORDPRESS_VERSION', '0.1.0-test' ); $GLOBALS['spacefast_options'] = array(); +$GLOBALS['spacefast_cached_options'] = array(); +$GLOBALS['spacefast_cache_enabled'] = array(); $GLOBALS['spacefast_scheduled'] = array(); $GLOBALS['spacefast_before_query'] = null; $GLOBALS['spacefast_post_types'] = array(); @@ -50,6 +52,14 @@ function sanitize_key( string $value ): string { return preg_replace( '/[^a-z0-9_\\-]/', '', strtolower( $value ) ) ?? ''; } function get_option( string $name, $default = false ) { + if ( ! empty( $GLOBALS['spacefast_cache_enabled'][ $name ] ) ) { + if ( array_key_exists( $name, $GLOBALS['spacefast_cached_options'] ) ) { + return $GLOBALS['spacefast_cached_options'][ $name ]; + } + $value = $GLOBALS['spacefast_options'][ $name ] ?? $default; + $GLOBALS['spacefast_cached_options'][ $name ] = $value; + return $value; + } return $GLOBALS['spacefast_options'][ $name ] ?? $default; } function update_option( string $name, $value ): bool { @@ -86,7 +96,9 @@ function wp_unschedule_event( int $timestamp, string $hook ): bool { function maybe_serialize( $value ): string { return serialize( $value ); } -function wp_cache_delete(): void {} +function wp_cache_delete( string $name ): void { + unset( $GLOBALS['spacefast_cached_options'][ $name ] ); +} function wp_json_encode( $value ): string { return (string) json_encode( $value, JSON_UNESCAPED_SLASHES ); } @@ -486,11 +498,13 @@ static function ( string $url, array $args ) use ( &$revoke_requests ): array { ) ); $GLOBALS['spacefast_before_query'] = static function (): void { - $current = Spacefast_Sync_State::get(); + $current = $GLOBALS['spacefast_options'][ Spacefast_Sync_State::OPTION ]; $current['desired'] = 2; $current['event_id'] = 'event-two'; - Spacefast_Sync_State::save( $current ); + $GLOBALS['spacefast_options'][ Spacefast_Sync_State::OPTION ] = $current; }; +$GLOBALS['spacefast_cache_enabled'][ Spacefast_Sync_State::OPTION ] = true; +$GLOBALS['spacefast_cached_options'][ Spacefast_Sync_State::OPTION ] = Spacefast_Sync_State::get(); $cas_ack = Spacefast_Sync_State::mutate( static fn( array $current ): array => Spacefast_Sync_State::acknowledge( $current, @@ -502,6 +516,8 @@ static function ( string $url, array $args ) use ( &$revoke_requests ): array { check( 1 === $cas_ack['delivered'], 'CAS acknowledges only the delivered generation' ); check( 'event-two' === $cas_ack['event_id'], 'CAS preserves the successor event id' ); check( 'building' === $cas_ack['last_status'], 'CAS keeps the accepted build active while preserving its successor' ); +unset( $GLOBALS['spacefast_cache_enabled'][ Spacefast_Sync_State::OPTION ] ); +unset( $GLOBALS['spacefast_cached_options'][ Spacefast_Sync_State::OPTION ] ); $invalid_response = new Spacefast_Client( static fn(): array => array(