perf: give the voices GET a longer timeout than the shared render bound#578
Conversation
build_args() set a 30s timeout on every BeyondWords API request and suppressed the VIP RemoteRequestTimeout sniff to allow it. These are blocking requests on real page-generating paths: the classic editor render fires up to five sequential cached GETs (languages, voices, summarization/video templates, video settings), and the write POST/PUT runs synchronously inside wp_after_insert_post. A slow or unresponsive API could pin a PHP worker for up to 30s per call (~150s worst case on a cold cache), degrading the whole site under concurrency on VIP and hanging wp-admin for editors. Drop the timeout to 3s -- the VIP-recommended bound for blocking requests on render paths -- and remove the now-unnecessary phpcs:ignore. The 15-minute transients already keep these calls off the network on the hot path; the shorter timeout only changes behaviour when the API is slow, where failing fast beats worker exhaustion. Verified with phpcs (WordPress-VIP-Go ruleset): passes with no suppression. No PHPUnit/Jest test references the timeout value. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
✅ WordPress Plugin Check Report
📊 ReportAll checks passed! No errors or warnings found. 🤖 Generated by WordPress Plugin Check Action • Learn more about Plugin Check |
|
@gouravkhunger 3s enough time for requests to our REST API? Do we have any observable metrics for response times? WordPress VIP recommends < 3s. |
|
@galbus 3s should be enough for almost every query. The only one I will reconfirm is GET voices which usually takes around a second to prepare. |
|
No code change — leaving the bound at 3s, since ~1s for 🤖 Addressed by Claude Code |
…db3769 Conflict in Client::build_args(). main's 2be1ca0 ("defer audio deletion to VIP cron and shorten DELETE timeout") parametrized the timeout with REQUEST_TIMEOUT (30) / DELETE_TIMEOUT (3) and already dropped the phpcs:ignore, which supersedes this branch's flat `'timeout' => 3`. Resolved in favour of main: a flat 3s would have clobbered that design and forced the create/update content calls -- deliberately generous, and deferred to background cron on VIP -- down to 3s. That leaves the render path this branch set out to fix still unbounded: cached_get() called call_api() without a timeout, so the classic-editor dropdown GETs (languages, voices, templates, project/video settings) still defaulted to 30s -- up to five sequential blocking GETs during page generation on a cold cache. main's commit bounded DELETE only. Add CACHED_GET_TIMEOUT (3) following the existing per-path const idiom and pass it from cached_get(). This matches the reviewer feedback on PR #578 that 3s covers these queries (GET voices ~1s), and leaves REQUEST_TIMEOUT at 30 for the content writes per main's design. Verified: full phpcs ruleset clean; ClientTest 43 tests / 142 assertions and SyncTest 79 tests / 164 assertions pass, including a new test asserting the dropdown GETs are issued with CACHED_GET_TIMEOUT. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Heads up that merging What's left is the gap 🤖 Addressed by Claude Code |
|
@galbus as discussed on slack, only voices is slow (~3.7s p95 in sentry), every other editor GET is ~250ms p95 max, so I'll keep 3s on the rest and give voices a longer per-call timeout. |
Sentry p95 for the editor dropdown GETs: voices ~3.7s, every other endpoint ~250ms. The shared CACHED_GET_TIMEOUT (3s) would therefore abandon more than 5% of cold-cache voices fetches, leaving the Voice dropdown empty in the classic editor. Add VOICES_TIMEOUT (8s) and a $timeout param on cached_get() so get_voices() passes its own bound while the other dropdowns keep the short 3s. 8s is ~2x the observed p95 to absorb the tail, still well under the 30s REQUEST_TIMEOUT default, and only ever paid on a cache miss (15-minute CACHE_TTL). Verified: full phpcs ruleset clean; ClientTest 44/145, SelectVoiceTest 12/61 and SyncTest 79/164 pass, with a new test asserting voices is issued with VOICES_TIMEOUT and the other dropdowns keep CACHED_GET_TIMEOUT. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Done in 72f2b2c — split the bound per endpoint using your Sentry figures: added Flagging the one number I picked: 8s for voices, ~2x your 3.7s p95 to absorb the tail while staying ~4x tighter than the old 30s default. It's a named const, so it's a one-line change if you'd rather have 5s or 10s. Worth noting the cost is cold-cache only (15-minute phpcs clean; ClientTest 44/145 (two new tests asserting voices gets the longer bound and the rest keep the short one), SelectVoiceTest 12/61, SyncTest 79/164. 🤖 Addressed by Claude Code |
…db3769 main's afc4296 ("bound blocking editor-dropdown API calls on the metabox render path", PR #580) landed the same render-path fix as this branch, plus negative caching. As reconciled on main it gives RENDER_TIMEOUT (3s) passed by cached_get(), which fully supersedes this branch's CACHED_GET_TIMEOUT. Dropped that const and the test covering it -- main's render_path_gets_use_a_short_timeout asserts the same thing, via get_summarization_settings_templates() rather than voices, so it is unaffected by the change below. What survives is the voices-specific bound, and main makes the case stronger rather than weaker: cached_get() now applies a flat 3s to every render GET including voices, which is ~3.7s p95 in Sentry, and failures are negative-cached. Voices would therefore not merely time out on >5% of cold-cache fetches -- it would blank the Voice dropdown for a whole CACHE_TTL_ON_ERROR instead of retrying on the next render. Keep VOICES_TIMEOUT (8s) and thread a $timeout param through main's cached_get(), defaulting to RENDER_TIMEOUT so every other dropdown is untouched. Verified: full phpcs ruleset clean; ClientTest 44/148, SelectVoiceTest 12/61, SettingsFieldsTest 22/90 and SyncTest 79/164 pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Conflicts resolved against
Flagging one thing that So this PR is now just phpcs clean; ClientTest 44/148, SelectVoiceTest 12/61, SettingsFieldsTest 22/90, SyncTest 79/164. 🤖 Addressed by Claude Code |
What
Give the voices GET its own bound, since it's the one editor dropdown that's genuinely slow.
Every other dropdown keeps
RENDER_TIMEOUT(3s) via the default — nothing else changes.Why
afc4296applies a flatRENDER_TIMEOUTof 3s to every cached render GET. Per @gouravkhunger's Sentry figures that's correct for all of them except voices:mainSo on
maintoday, voices exceeds its own timeout at p95. And becauseafc4296also added negative caching, the consequence is worse than a single slow render: the timeout gets cached as an empty-array sentinel, so the Voice dropdown stays empty for a fullCACHE_TTL_ON_ERROR(2 min) rather than retrying on the next render.Reviewer notes
VOICES_TIMEOUT = 8is the one judgment call — ~2x the observed 3.7s p95 to absorb the tail, still well under the 30sREQUEST_TIMEOUT. It's a named const, so it's a one-line change if you'd prefer 5s or 10s.CACHE_TTL).main'srender_path_gets_use_a_short_timeoutexercisesget_summarization_settings_templates(), not voices, so it's unaffected by this change and still passes.CACHED_GET_TIMEOUTand its test were dropped as duplicates ofRENDER_TIMEOUT/render_path_gets_use_a_short_timeout.phpcs:ignoreadded.Verification
phpcsfull ruleset (WordPress-VIP-Go) — clean, exit 0.ClientTest— 44 tests / 148 assertions, includingvoices_get_uses_longer_timeout(asserts the exact bound, plus that it sits aboveRENDER_TIMEOUTand belowREQUEST_TIMEOUT).SelectVoiceTest— 12 / 61.SettingsFieldsTest— 22 / 90.SyncTest— 79 / 164.🤖 Generated with Claude Code