Note: The developers are aware of this and are working to resolve it and other issues.
I recently installed the latest plugin from Elevated Extensions — Site Search — which added a very nice search feature. Unfortunately, I kept running into issues with the reindexing. I submitted a ticket to the developer, but wanted to get this up and running as quickly as possible, so I dropped the plugin into ChatGPT to help determine the cause, and below are its findings.
I successfully implemented the ChatGPT fix, but I don’t recommend doing so without thoroughly testing in your environment.
ChatGPT Findings
If your plugin’s reindex process never starts, even though there are no PHP errors or log entries, the problem may be a stale rebuild lock.
In this case, the issue was caused by the plugin failing to completely remove an expired transient lock before attempting to create a new one.
Symptoms
You may notice one or more of the following:
- Reindexing never begins.
- Reindexing error
- No PHP errors are logged.
- No detailed debug messages indicate a problem.
Where to Make the Change
Open the following file:
includes/search/class-search-engine.php
Locate the acquire_rebuild_lock() method.
Inside this method, you’ll find logic that removes an expired rebuild lock. The original code only deletes the timeout transient:
DELETE FROM {$wpdb->options}
WHERE option_name = '_transient_timeout_elevated_ss_rebuild_in_progress'Unfortunately, this leaves behind the actual transient value:
_transient_elevated_ss_rebuild_in_progressWhen the plugin later attempts to recreate the lock using INSERT IGNORE, WordPress ignores the insert because the transient already exists. As a result, the lock cannot be acquired, and the rebuild process exits without an error.
The Fix
Replace the existing expired-lock cleanup with the following code:
// Purge expired lock first.
$expired_timeout = (int) $wpdb->get_var(
$wpdb->prepare(
"SELECT option_value FROM {$wpdb->options} WHERE option_name = %s",
$timeout_key
)
);
if ($expired_timeout > 0 && $expired_timeout < time()) {
$wpdb->query(
$wpdb->prepare(
"DELETE FROM {$wpdb->options} WHERE option_name IN (%s, %s)",
$key,
$timeout_key
)
);
}Why This Works
WordPress stores a database-backed transient as two separate records:
_transient_elevated_ss_rebuild_in_progress
_transient_timeout_elevated_ss_rebuild_in_progressThe original implementation only removed the timeout record after it expired.
Because the transient itself remained, the subsequent INSERT IGNORE failed to recreate the lock. The method interpreted this as “another rebuild is already running” and exited immediately.
By deleting both records whenever an expired lock is detected, the plugin can successfully acquire a new lock and continue with the rebuild.
Recommendation
If you’re implementing your own database-backed locking mechanism, always treat the transient and timeout as a pair:
- Check whether the timeout has expired.
- If it has, remove both the timeout and the transient value.
- Only then attempt to acquire a new lock.
This small change prevents stale locks from blocking future rebuilds while preserving the existing locking strategy.
Leave a Reply