fix: keep analytics from ever slowing a WordPress site - #25
Merged
Merged
Conversation
With the queue off, every PHP request on an active path sends one analytics POST. The SDK caps its own client at 1s, but the plugin injects WP_Http_Client, so the POST ran on WordPress's 5s default. A slow relay then held a PHP worker for up to 5s per request (and the visitor too, without FastCGI), enough to exhaust the worker pool. Build the per-request transport in the plugin with a dedicated 1s client. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When the queue insert failed (for example a site updated without reactivation, before an admin or cron request creates the table), enqueue() fell back to a synchronous POST on the visitor request, on WordPress's 5s default timeout. On a missing table that is every request. Queue mode now never makes a network call on a visitor request. A failed insert drops the event with a debug log. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The queue keeps the visitor request down to one row insert, but it only ran when a merchant defined SUPERTAB_CONNECT_USE_WP_QUEUE, which no doc mentions. A fresh install sent one POST per PHP request instead. The queue is now on unless the constant is defined false. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The hourly drain sent at most 5,000 events an hour (10 batches of 500), and the 10,000-row buffer cap drops anything beyond that without a trace. A publisher doing about 3 PHP requests a second already loses events. Drain every 15 minutes, the shortest WP-Cron interval the VIP coding standard accepts, with up to 20 batches per run: 40,000 events an hour. A schedule left at another interval by an earlier version is replaced, tracked by a new option that uninstall removes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
During a relay outage each run claimed and lost up to 20 batches, each waiting out a 5s timeout, holding a PHP worker for most of two minutes. The run now stops at the first failed POST: one batch and one timeout per run, and the remaining rows wait for the next run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The implementation matches the stated reliability goals and covers the changed behavior with focused tests.
Review effort: Balanced
Findings: None
What changed in this PR
Makes analytics delivery fail-open and prevents relay latency from blocking visitor requests.
Changes:
- Enables queued analytics by default with faster, bounded draining.
- Adds a one-second timeout for queue opt-outs.
- Drops events on queue failures and expands tests.
| File | Description |
|---|---|
uninstall.php |
Removes the flush interval option. |
src/class-analytics-dispatcher.php |
Updates buffering, draining, failure handling, and scheduling. |
src/class-analytics-queue-table.php |
Updates queue documentation. |
src/class-plugin.php |
Defaults to queued delivery and configures opt-out transport. |
src/utils/class-wp-http-client.php |
Adds configurable request timeouts. |
tests/AnalyticsDispatcherTest.php |
Tests queue, scheduling, and failure behavior. |
tests/PluginTest.php |
Tests default queueing and short timeout transport. |
tests/WPHttpClientTest.php |
Tests timeout configuration. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
tomasstark
approved these changes
Oct 2, 2026
ranael-garem
marked this pull request as ready for review
October 2, 2026 09:38
github-actions Bot
pushed a commit
that referenced
this pull request
Oct 2, 2026
## [1.3.1](v1.3.0...v1.3.1) (2026-10-02) ### Bug Fixes * keep analytics from ever slowing a WordPress site ([#25](#25)) ([0da4338](0da4338))
|
🎉 This PR is included in version 1.3.1 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Analytics can no longer slow down or take down a merchant's WordPress site, even when our ingest is slow or down. On a fresh install the queue was off, since turning it on needed a
wp-config.phpconstant nobody documented. So every PHP request sent one POST with WordPress's 5s timeout. If our relay got slow, that held a PHP worker for up to 5s per request and could exhaust the pool.Changes:
SUPERTAB_CONNECT_USE_WP_QUEUEas false opts out.WP_Http_Client.Review notes (delete on merge)
With these changes, a visitor request in queue mode does two queries on the plugin's own table and no network calls.
The one thing to look at: why 15 minutes and not 5.
WordPress.WP.CronIntervalflags WP-Cron intervals under 15 minutes, and some of these merchants may be on VIP. The cron schedule array uses a literal15 * MINUTE_IN_SECONDSso the sniff can read it. Existing installs get their hourly schedule replaced on the next admin or cron request, tracked by a newsupertab_connect_flush_intervaloption.Still deliver-once. I looked at keeping rows until the relay returns a 2xx, but doing it safely means holding row locks across the HTTP call. With a nearly empty table those locks block visitor inserts, which is the exact failure this PR removes. Doing it without locks needs a claim column and a schema bump, so it's left for a follow-up.
Not covered: the billing
/eventsPOST on token-bearing requests still runs synchronously on the visitor request with the 5s default. Today that's only the small slice of requests carrying a license token. It's an SDK-level change.🤖 Generated with Claude Code