BUG > No lock/mutex on transient cache refresh
Subject: No lock/mutex on transient cache refresh in Mfn_Dashboard/Mfn_Api — causes concurrent PHP-FPM workers to make redundant simultaneous outbound API calls under load
Betheme 28.5.10
Site: imaginity.com
Environment: WordPress 7.1.2, PHP 8.3.33, WP Rocket + WPML + Imagify active, PHP-FPM (2 CPU cores)
Summary:
Mfn_Dashboard::__construct() (in functions/admin/class-mfn-dashboard.php) calls get_promo_version() and get_expiration() on every request that instantiates the class, which our stack traces show happening on plain admin-ajax.php and admin.php requests — including ones triggered by unrelated background tasks (e.g. other plugins' async queue dispatches). Similarly, Mfn_Api::get_update_version() and get_update_pricing() run from the same constructor chain.
Each of these follows the pattern:
php
$version = get_site_transient( 'betheme_xxx' );
if ( ! $version ) {
$version = $this->refresh_xxx(); // makes the actual outbound HTTP call
}
This correctly avoids calling out to muffingroup.com on every request — but only while the transient is valid. The moment a transient expires, there is no lock around refresh_xxx(). If multiple PHP-FPM workers process concurrent requests in that same window (which is common under real traffic, since admin-ajax.php is hit constantly by other plugins), every one of them independently sees the cache miss and independently fires its own outbound curl_exec() call to the same Muffin Group endpoint at the same time.
Evidence:
We caught this live via PHP-FPM's slow-request log (request_slowlog_timeout lowered to 2s to capture it). Within a single ~5-minute window we saw three separate PHP-FPM worker PIDs simultaneously blocked in curl_exec(), all inside remote_get_pricing() / remote_get_promo_version() / remote_get_version(), all originating from Mfn_Dashboard::__construct() → functions.php:228 → wp-settings.php:747. Live FPM status showed those workers' request durations climbing past 1-2.4 seconds while stuck. Individually, each Muffin Group endpoint responds in ~0.5s when tested directly — the slowdown is entirely from redundant concurrent calls stacking up, not from your API being slow.
Impact:
On any moderately busy or CPU-constrained server, this produces bursts of simultaneous multi-second PHP-FPM worker stalls every time one of these transients expires (TTLs observed: 6 hours for update version, 1 day for promo version and pricing, 1 week for expiration) — i.e., a recurring, predictable performance hit, worse on lower-resource hosting where several concurrent curl/TLS operations compete for limited CPU.
Suggested fix:
Add a short-lived (e.g. 30-60 second) "refreshing" lock transient around each refresh_xxx() function: the first request to see a cache miss sets the lock and performs the real fetch; any other concurrent request that finds the lock set simply returns the last cached value (or the existing -1 fallback sentinel your code already uses for failed fetches) instead of also calling the API. This is a standard cache-stampede guard and would be a minimal, low-risk change to class-mfn-dashboard.php and class-mfn-api.php.
We've applied a workaround on our end via a small mu-plugin (using WordPress's pre_http_request filter to deduplicate concurrent calls to muffingroup.com) so this isn't currently affecting us, but flagging it since it would affect any customer under similar concurrent load.
Happy to share the exact PHP-FPM stack traces or our workaround code if useful for reproducing this.
Comments
Hello,
We would like to politely point out that we will no longer be responding to automatically generated messages from AI agents. We strictly provide real human support to resolve actual user issues.
If you encounter any operational problems while using our theme, please describe the issue you are experiencing, and we will gladly fix it. Please refrain from pasting automated code analysis generated by AI tools.
Best regards
Thank you Phil for your reply
It seems the problem was more related to object-cache and WPML flushing it. We are still investigating the issue
The situation is probably not Betheme related, sorry for the false report
Thank you for your kind support, as always
Best regards