ajjlechu
Forum Replies Created
-
Forum: Plugins
In reply to: [LiteSpeed Cache] Global Purge Triggered Every ~12h Without Visible CauseThanks a lot! I really appreciate you checking this with your dev. Please let me know if there’s any possible way to handle or block CLI-triggered purges from my side (via code or MU-plugin) 🙂
Forum: Plugins
In reply to: [LiteSpeed Cache] Global Purge Triggered Every ~12h Without Visible CauseI only have FTP and hosting panel access, no SSH/root.
Is there any way to block or ignore CLI-triggered cache purges via a must-use plugin or WordPress code (for testing), given that I don’t have direct server access?Forum: Plugins
In reply to: [LiteSpeed Cache] Global Purge Triggered Every ~12h Without Visible Causearound 2/3 weeks ago I came across this entry in the logs,
09/07/25 20:29:32.350 [=CLI=wordpress2477988 1 HK8] X-LiteSpeed-Purge: public,stale,2ae_FD => LiteSpeed\LSC->send_headers()@615 => WP_Hook->apply_filters(,ARRAY)@324 => WP_Hook->do_action(ARRAY)@348 => /wp-includes/load.php@517and time-wise it would actually match with the global purge. But as far as I understand,
2ae_FDis not a global purge.I suspect that something triggered the purge via CLI, which is why I can’t see the usual trace of it in the logs.
Forum: Plugins
In reply to: [LiteSpeed Cache] Global Purge Triggered Every ~12h Without Visible Causethanks a lot for your detailed reply.
I downloaded the entire
wp-contentdirectory and wrote a Python script to search through all files forlitespeed-purge. Please see the file below with the results – everything that containslitespeed-purgeis only inside the official LiteSpeed plugin folder, nothing outside of it.* **API** Supportlitespeed_purged_fronthook. (Umberto Fiorelli)
* **API** New filterlitespeed_purge_ucssto purge a single page UCSS. (#376681)
* **API** New APIlitespeed_purge_all_objectandlitespeed_purged_all_objectaction hooks.
* **API** Removed functionlitespeed_purge_single_post.
* [API] Added LITESPEED_PURGE_SILENT const to bypass the notification when purging
* [NEW FEATURE] New API function litespeed_purge_single_post($post_id).
* **API** Addedlitespeed_purge_tagsfilter to allow manipulation of purge tags.
// Actionlitespeed_purge_finalize
add_action( 'litespeed_purge', __NAMESPACE__ . '\Purge::add' );
add_action( 'litespeed_purge_all', __NAMESPACE__ . '\Purge::purge_all' );
add_action( 'litespeed_purge_post', array( $this, 'purge_post' ) );
add_action( 'litespeed_purge_posttype', __NAMESPACE__ . '\Purge::purge_posttype' );
add_action( 'litespeed_purge_url', array( $this, 'purge_url' ) );
add_action( 'litespeed_purge_widget', __NAMESPACE__ . '\Purge::purge_widget' );
add_action( 'litespeed_purge_esi', __NAMESPACE__ . '\Purge::purge_esi' );
add_action( 'litespeed_purge_private', __NAMESPACE__ . '\Purge::add_private' );
add_action( 'litespeed_purge_private_esi', __NAMESPACE__ . '\Purge::add_private_esi' );
add_action( 'litespeed_purge_private_all', __NAMESPACE__ . '\Purge::add_private_all' );
// Actionlitespeed_purged_all
add_action( 'litespeed_purge_all_object', __NAMESPACE__ . '\Purge::purge_all_object' );
add_action( 'litespeed_purge_ucss', __NAMESPACE__ . '\Purge::purge_ucss' );
$purge_post_events = apply_filters('litespeed_purge_post_events', array(
!defined('LITESPEED_PURGE_SILENT') && Admin_Display::success($msg);
do_action('litespeed_purged_all');
do_action('litespeed_purged_all_lscache');
!defined('LITESPEED_PURGE_SILENT') && Admin_Display::success($msg);
do_action('litespeed_purged_all_ccss');
!defined('LITESPEED_PURGE_SILENT') && Admin_Display::success($msg);
do_action('litespeed_purged_all_ucss');
!defined('LITESPEED_PURGE_SILENT') && Admin_Display::success($msg);
do_action('litespeed_purged_all_lqip');
!defined('LITESPEED_PURGE_SILENT') && Admin_Display::success($msg);
do_action('litespeed_purged_all_avatar');
!defined('LITESPEED_PURGE_SILENT') && Admin_Display::success($msg);
do_action('litespeed_purged_all_localres');
!defined('LITESPEED_PURGE_SILENT') && Admin_Display::success($msg);
do_action('litespeed_purged_all_cssjs');
!defined('LITESPEED_PURGE_SILENT') && Admin_Display::success($msg);
!defined('LITESPEED_PURGE_SILENT') && Admin_Display::error($msg);
!defined('LITESPEED_PURGE_SILENT') && Admin_Display::error($msg);
!defined('LITESPEED_PURGE_SILENT') && Admin_Display::success($msg);
do_action('litespeed_purged_all_opcache');
!defined('LITESPEED_PURGE_SILENT') && Admin_Display::success($msg);
do_action('litespeed_purged_all_object');
!defined('LITESPEED_PURGE_SILENT') && Admin_Display::success($msg);
do_action('litespeed_purged_single');
do_action('litespeed_purged_front', $_SERVER['HTTP_REFERER']);
do_action('litespeed_purge_ucss', $url_tag);
!defined('LITESPEED_PURGE_SILENT') && Admin_Display::success($msg);
do_action('litespeed_purged_frontpage');
!defined('LITESPEED_PURGE_SILENT') && Admin_Display::success($msg);
do_action('litespeed_purged_pages');
!defined('LITESPEED_PURGE_SILENT') && Admin_Display::success($msg);
!defined('LITESPEED_PURGE_SILENT') && Admin_Display::success(sprintf(__('Purge category %s', 'litespeed-cache'), $val));
do_action('litespeed_purged_cat', $value);
!defined('LITESPEED_PURGE_SILENT') && Admin_Display::success(sprintf(__('Purge tag %s', 'litespeed-cache'), $val));
do_action('litespeed_purged_tag', $val);
!$quite && !defined('LITESPEED_PURGE_SILENT') && Admin_Display::success(sprintf(__('Purge url %s', 'litespeed-cache'), $val));
do_action('litespeed_purged_link', $url);
do_action('litespeed_purged_esi', $tag);
do_action('litespeed_purged_posttype', $post_type);
do_action('litespeed_purged_post', $pid);
do_action('litespeed_purged_widget', $widget_id);
do_action('litespeed_purged_comment_widget', $recent_comments->id);
do_action('litespeed_purged_feeds');
do_action('litespeed_purged_on_logout');
do_action('litespeed_purge_finalize');
$purge_tags = apply_filters('litespeed_purge_tags', $purge_tags, $is_private);
add_action('litespeed_purge_finalize', __CLASS__ . '::purge');
do_action('litespeed_purge_all', '3rd Autoptimize');
do_action('litespeed_purge_all', '3rd avada');
do_action('litespeed_purge_posttype', bbp_get_forum_post_type());
do_action('litespeed_purge_post', $ancestor);
do_action('litespeed_purge_widget', $replies_widget->id);
do_action('litespeed_purge_widget', $topic_widget->id);
do_action('litespeed_purge_all', '3rd Beaver_Builder');
do_action('litespeed_purge_all', 'Elementor - Regenerate CSS & Data');
do_action('litespeed_purge', self::CACHETAG_GALLERIES . $gallery->pageid);
do_action('litespeed_purge', self::CACHETAG_GALLERIES . sanitize_key($_REQUEST['gallery_id']));
do_action('litespeed_purge', self::CACHETAG_GALLERIES . sanitize_key($task_list[0]['query']['id']));
do_action('litespeed_purge', self::CACHETAG_GALLERIES . $image->galleryid);
do_action('litespeed_purge', self::CACHETAG_GALLERIES . sanitize_key($_GET['gid']));
do_action('litespeed_purge', self::CACHETAG_GALLERIES . $gid);
do_action('litespeed_purge', self::CACHETAG_GALLERIES . $new_gallery_id);
do_action('litespeed_purge', self::CACHETAG_GALLERIES . $new_gallery_id);
do_action('litespeed_purge', self::CACHETAG_GALLERIES . $image->galleryid);
do_action('litespeed_purge', self::CACHETAG_GALLERIES . $gid);
do_action('litespeed_purge', self::CACHETAG_ALBUMS . $aid);
do_action('litespeed_purge_private_esi', 'storefront-cart-header');
do_action('litespeed_purge_private_all');
do_action('litespeed_purge_post', $product->get_id());
do_action('litespeed_purge_post', $product->get_parent_id());
do_action('litespeed_purge_post', $translation->element_id);
do_action('litespeed_purge', self::CACHETAG_TERM . $tr_cat_id);
do_action('litespeed_purge', self::CACHETAG_TERM . $term_id);
do_action('litespeed_purge', self::CACHETAG_TERM . $cat);
do_action('litespeed_purge', self::CACHETAG_TERM . $tag);
do_action('litespeed_purge_post', $post_id);
do_action('litespeed_purge_esi', 'yith_wcwl_add');
var savedPurgeBy = getCookie('litespeed_purgeby_option');
setCookie('litespeed_purgeby_option', this.value, 30);
if ( ! empty( $_GET['dologin_gen_link'] ) && ! empty( $_GET['litespeed_purge_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['litespeed_purge_nonce'] ) ), 'litespeed_purge_action' ) ) {
<a href="<?php echo esc_url( wp_nonce_url( admin_url( 'admin.php?page=litespeed-toolbox&dologin_gen_link=1' ), 'litespeed_purge_action', 'litespeed_purge_nonce' ) ); ?>" class="button button-secondary"><?php esc_html_e( 'Generate Link for Current User', 'litespeed-cache' ); ?></a>Regarding my crawler: it works and caches correctly. Without it everything shows as MISS; after a full purge and running the crawler I can confirm I get HITs, both on mobile and PC (with old cache cleared).
The script itself works perfectly and warms up the cache exactly as I want.
About the debug log: I already set the limit to 300 MB, but the only entries I see there are my own manual purges – nothing else shows up, even though the cache is being purged. Unfortunately, I don’t have access to the server logs either, since the hosting provider doesn’t allow it on shared hosting.
Hi @longnha 🙂I also checked my database and found the same entry – the value in
wp_optionsforlitespeed.purge.queueis set to-1. From what I understand it should normally be0(or at least not remain stuck at-1).I even tried to change it manually to
0about a week ago, but it didn’t work – it always reverts back to-1.Forum: Plugins
In reply to: [LiteSpeed Cache] Global Purge Triggered Every ~12h Without Visible CauseHi,
Follow-up to report APYYVKRR.
Thanks for jumping in!
How I warm up the cache (custom CRON every 5 min)
- I prewarm only real pages (home, categories, brands, CMS, products).
- For each URL I request desktop and mobile variants, with gzip/br and WebP varies.
- I verify
X-LiteSpeed-Cache: hit; if MISS, I requeue. - I log the exact timestamp when homepage returns MISS (that’s how I detect purge times).
cURL examples
# Desktop HTML (gzip/br)
curl -sS -D - "https://reintec.ch/..." \
-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/126" \
-H "Accept: text/html,application/xhtml+xml" \
-H "Accept-Encoding: gzip, br" \
-H "Accept-Language: de-CH,en;q=0.8"
# Mobile HTML (triggers ismobile vary)
curl -sS -D - "https://reintec.ch/..." \
-H "User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 17_6 like Mac OS X) AppleWebKit/605.1.15 Mobile/15E148" \
-H "Accept: text/html,application/xhtml+xml" \
-H "Accept-Encoding: gzip, br"What I see
- After a full warm cycle everything is HIT.
- Roughly every ~12h there’s a global-like purge → many MISS until warmup completes.
- My MU sniffers on purge hooks (
litespeed_purge_all,litespeed_api_purge,litespeed_purge_post) didn’t catch a caller. - Host says the call lands in
purge.cls.php, but the origin is unknown. - Debug often shows:
X-LiteSpeed-Purge: public,stale,2ae_FDyet the cache behaves as if a broader purge happened (home/product/category MISS at once).
What I tried
- One-off LiteSpeed reset via PHP on this site (no change).
- Same prewarmer & LS settings on another site → no unexpected purges there.
- Purge on upgrade OFF, TTLs long (front page
604800), crawler & QUIC.cloud disabled.
Code excerpts (minimal, for context)
warm_critical.php (core ideas only)
$UA_DESKTOP = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Chrome/127';
$UA_MOBILE = 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 ...) Safari/604.1';
$ENCS = ['br','gzip']; // warm both encodings
$BATCH_SIZE = 10; // small batches, every 5 min
$WARM_MOBILE = 1; // warm mobile (ismobile vary)
$siteBase = 'https://reintec.ch';
// For each URL -> desktop & mobile, br & gzip
foreach ($batchUrls as $u) {
foreach ($ENCS as $enc) {
$tasks[] = ['url'=>$u,'ua'=>$UA_DESKTOP,'tag'=>'desk','enc'=>$enc];
if ($WARM_MOBILE) $tasks[] = ['url'=>$u,'ua'=>$UA_MOBILE,'tag'=>'mob','enc'=>$enc];
}
}
// Parse LS header and re-hit if not HIT
function parse_ls($resp){ /* ... extract X-LiteSpeed-Cache ... */ }
if ($ls !== 'hit') { /* single() retry once to confirm */ }
// Detect cycle wrap; on full pass rotate state & trim logs
if ($wrapped) { @unlink($stateFile); @unlink($critFile); @unlink($logFile); }cron-5min.php (calls warmers + wp-cron)
$BASE = 'https://reintec.ch';
// Critical batch warmup
hit("$BASE/warm_critical.php?cron=1&mobile=1&token=$TOKEN", 'warm_critical', 24, [
"X-WARM-TOKEN: $TOKEN",
'User-Agent: ReinTec-Cron/1.0',
]);
// Whole-site warmup (detached)
hit("$BASE/warm_wholepage.php?cron=1&detached=1&token=$TOKEN", 'warm_wholepage', 24, [
"X-WARM-TOKEN: $TOKEN",
'User-Agent: ReinTec-Cron/1.0',
]);
// Kick WP-Cron (no auth, no cookies)
hit("$BASE/wp-cron.php?doing_wp_cron=1", 'wp-cron', 20);Questions
- How can I fully trace the caller of
purge_allinsidepurge.cls.php(hook/backtrace/file/line)? Any recommended filter to attach a backtrace logger? - Could server-level jobs (Enterprise LS nightly tasks, tmp cleaners, inode eviction/limits, etc.) cause a broad purge without WP hooks firing?
- Can
purge_stalequeues or REST/checkout actions escalate into a site-wide purge under some conditions? - Any additional headers I should include in warm-up (beyond UA / Accept / Accept-Encoding / Accept-Language) to avoid bypass/edge variants?
If helpful I can share the full scripts, but the essence is above. Any hint to pinpoint the exact trigger would be hugely appreciated.
Thanks!
LeszekForum: Plugins
In reply to: [LiteSpeed Cache] Global Purge Triggered Every ~12h Without Visible CauseHere is also a screenshot from my custom prewarmer script.
As you can see, the last detected purge was at 10:40 today.The script checks if the homepage is on HIT during the first visit – if it is on MISS, it saves a debug.log file with the exact time and date.
It only runs every 5 minutes via server CRON.