fix(checkout): honour is_publishing_stale in publish_pending_site() to unblock stuck pending sites#1267
Conversation
…o unblock stuck pending sites When two callers race to publish the same pending site (most commonly a duplicate $0-trial WooCommerce order, but also any caller retried while a prior PHP process died mid-publish), the second caller observed is_publishing=true and returned without doing anything, leaving the "Creating your site" overlay hung on the customer's screen until the next Action Scheduler retry — which often never fires, because the duplicate caller never reschedules. Site::is_publishing_stale() was added in 2.5.3 to detect this exact "flag set but the process that set it is dead" condition (default 5 minute window) and the AJAX poller already consumes it; this change wires it into publish_pending_site() too, so the second caller can finish the job the first caller never completed. A fresh in-flight flag still short-circuits as before. method_exists() guards the call so any pre-2.5.3 serialized Site objects in stored meta still behave like the old code path. The recovery emits a wu_log_add() line on the membership log so support can correlate the symptom. Regression coverage in tests/WP_Ultimo/Models/Membership_Test.php: - test_publish_pending_site_bails_when_flag_is_fresh: a fresh flag must still short-circuit (guards against accidentally rewriting the check into "always publish"). - test_publish_pending_site_proceeds_when_flag_is_stale: a stale flag must fall through and actually publish the blog (this is the regression guard for the BUG 2 fix). Both tests use wu_create_customer/wu_create_product/wu_create_membership to build a fully-persisted membership; the class-level setUp() uses raw Model constructors which can leave the in-memory ID at 0 in some environments, silently no-op'ing the meta calls the test depends on. The duplicate-order trigger in the WooCommerce gateway addon is filed separately; this commit fixes the core bail-out only.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthrough
ChangesStale Publishing Flag Recovery
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🔨 Build Complete - Ready for Testing!📦 Download Build Artifact (Recommended)Download the zip build, upload to WordPress and test:
🌐 Test in WordPress Playground (Very Experimental)Click the link below to instantly test this PR in your browser - no installation needed! Login credentials: |
|
Performance Test Results Performance test results for b8bdbdd are in 🛎️! Note: the numbers in parentheses show the difference to the previous (baseline) test run. Differences below 2% or 0.5 in absolute values are not shown. URL:
|
Summary
TriggerA real-world reproduction observed in production logs: a duplicate Patchif ($is_publishing) {
$is_stale = method_exists($pending_site, 'is_publishing_stale')
? $pending_site->is_publishing_stale()
: false;
if ( ! $is_stale) {
return true;
}
wu_log_add(/* … stale-recovery log line … */);
}
Regression coverage
Verification
Merged via PR #1267 to main. aidevops.sh v3.17.28 spent 32s on this as a headless bash routine. |
Summary
publish_pending_site()ininc/models/class-membership.phpbailedsilently when
is_publishing=true, even after the publishing processthat set the flag had died. The result: the "Creating your site"
overlay hung on the customer's screen until the next Action Scheduler
retry — which often never fires, because the duplicate caller never
reschedules.
This change wires
Site::is_publishing_stale()(added in 2.5.3 todetect this exact "flag set but the process that set it is dead"
condition, default 5-minute window) into
publish_pending_site()soa second caller can finish the job the first caller never completed.
The AJAX poller at
class-membership-manager.php:214already consumedis_publishing_stale(); this commit closes the symmetry on thepublish path.
A fresh in-flight flag still short-circuits, so the duplicate-call
short-circuit semantics are unchanged for the non-stale case.
Trigger
A real-world reproduction observed in production logs: a duplicate
$0-trial WooCommerce order arrives ~2.5 minutes after the first order
fails mid-publish (PHP process killed by
max_execution_time/ OOM /fatal error). Order #1 set
is_publishing=trueand died; order #2'spublish_pending_site()call saw the flag and returned without doinganything. The site stayed at
type=site_templateand the customer'soverlay never completed.
The duplicate-order root cause itself lives in the
ultimate-multisite-woocommerceaddon; this is the core defence-in-depthfix so the symptom self-heals after the 5-minute stale window.
Patch
method_exists()guards the call so any pre-2.5.3 serializedSiteobjects deserialized from membership meta still behave like the old
code path. The recovery emits a
wu_log_add()line on the membershiplog so support can correlate stuck-overlay reports.
Regression coverage
tests/WP_Ultimo/Models/Membership_Test.phptest_publish_pending_site_bails_when_flag_is_fresh— a fresh flagmust still short-circuit (guards against accidentally rewriting the
check into "always publish").
test_publish_pending_site_proceeds_when_flag_is_stale— a staleflag must fall through and actually publish the blog. This is the
regression guard for the BUG fix; reverting just the inc/ patch and
re-running this test fails as expected.
Both tests use
wu_create_customer/wu_create_product/wu_create_membership(BerlinDB-persisting helpers); the class-levelsetUp()uses raw Model constructors which can leave the in-memory IDat 0 in some environments, silently no-op'ing the meta calls these
tests depend on.
Verification
elsewhere in the test file are not touched)
[OK] No errorsOK (2 tests, 14 assertions)Membership_Testclass (118 tests): greenpre-patch and confirmed the fix post-patch on the dev install
Summary by CodeRabbit
Bug Fixes
Tests