Skip to content

Fix verify token persistence on object-cache hosts#284

Merged
circlecube merged 3 commits into
mainfrom
fix/object-cache-transient-verify-token
Jul 22, 2026
Merged

Fix verify token persistence on object-cache hosts#284
circlecube merged 3 commits into
mainfrom
fix/object-cache-transient-verify-token

Conversation

@mr-vara

@mr-vara mr-vara commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Invalidate options object-cache entries before set/delete in Transient options-API fallback
  • Retry failed update_option() with delete_option() + add_option()
  • Abort HiiveConnection::connect() when nfd_data_verify_token cannot be read back after save

Problem

On Bluehost hosts with an object-cache.php drop-in, Transient::set() could leave a stale nfd_data_verify_token in Redis. Connect sent a new token to Hiive while WordPress still validated against the old one, causing Supplied token could not be validated (401).

Test plan

  • vendor/bin/phpunit tests/phpunit/includes/Helpers/TransientTest.php
  • On object-cache host: reset hiive connection, confirm connect returns 201
  • Confirm nfd_data_verify_token updates between connect attempts

Invalidate the options object-cache group before writing options-table
transient fallbacks, and retry with add_option when update_option fails.
Abort connect when the verify token cannot be read back after saving.
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

AI code review

✅ Strengths

  • Proactively addresses a real-world failure mode on object-cache hosts by explicitly invalidating the options cache group before set/delete in the options-table transient fallback. This is a pragmatic and low-risk guard against stale reads from Redis/Memcached drop-ins.
  • Adds a conservative retry path in Transient::set() using delete_option() + add_option() when update_option() returns false, which helps when caches or DB comparisons short-circuit updates.
  • Introduces a defensive read-after-write check in HiiveConnection::connect() to ensure the verify_token actually persisted before attempting the remote call—this should directly prevent the 401 regression described.
  • Updates tests to validate cache invalidation behavior and reconnect flow, with more realistic wp_remote_* stubs and coverage for the new cache deletion expectations.

⚠️ Suggestions (non-blocking)

  • When the token fails to read back in connect(), consider returning a WP_Error (e.g., new \WP_Error('nfd_data.token_persist_failed', 'Verify token could not be persisted/read')) rather than false, and optionally log a concise diagnostic. This will make upstream handling and observability cleaner.
  • In Transient::delete(), you currently delete the DB first and then invalidate the cache. For symmetry with set() and to reduce brief windows of stale reads under heavy concurrency, consider also invalidating the cache before the DB delete (or comment why post-delete is preferred on target drop-ins).
  • Add a unit test that exercises the update_option() failure path in Transient::set() and asserts the delete_option() + add_option() fallback is invoked. This will lock in the new behavior and prevent regressions.
  • Consider a tiny note in docs/changelog about: 1) options-cache invalidation for transients fallback, and 2) connect abort if the verify token can’t be read back. This change is operationally significant for support/triage.
  • PHPCS: a few class-level disables in tests are broad; if feasible, narrow them to lines/blocks to avoid masking unrelated issues.

❌ Potential issues / risks (review for correctness, not necessarily blockers)

  • The delete_option() + add_option() fallback introduces a short gap where the option does not exist. Given this is a transient-like value and your follow-up read is immediate, this is likely acceptable, but worth noting in case anything else reads the option concurrently. A potential refinement: only run the delete+add if a fresh get_option($key) does not already equal the intended value after the failed update_option() (i.e., avoid extra churn if the value already matches).
  • Behavior change in connect() return semantics: returning false early may differ from other failure paths (which might be WP_Error elsewhere). Ensure callers don’t rely on more structured errors here. If they do, prefer the WP_Error approach above.

✅ Verdict: Merge with minor follow-ups

This is a targeted, pragmatic fix that should resolve the stale-token issue on object-cache hosts with minimal risk. I recommend merging and following up with the minor refinements above (error type/logging, a unit test for the fallback path, and small docs/PHPCS tweaks).

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Coverage: Base 32.94% → PR 32.91% (must not decrease).
✅ No decrease.

Code Coverage

project coverage report 32.91% @ 9d6eb05

@circlecube
circlecube merged commit cfbfccd into main Jul 22, 2026
15 checks passed
@circlecube
circlecube deleted the fix/object-cache-transient-verify-token branch July 22, 2026 14:28
mr-vara added a commit that referenced this pull request Jul 22, 2026
Resolve HiiveConnectionTest conflict by keeping verify-token read-back
mocks from #284 and capabilities cache clear mocks from #285.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants