Skip to content

fix(cache): cap wp-content/litespeed size with automatic oldest-first pruning (#777) - #1037

Open
faisalahammad wants to merge 1 commit into
litespeedtech:devfrom
faisalahammad:fix/777-max-cache-folder-size
Open

fix(cache): cap wp-content/litespeed size with automatic oldest-first pruning (#777)#1037
faisalahammad wants to merge 1 commit into
litespeedtech:devfrom
faisalahammad:fix/777-max-cache-folder-size

Conversation

@faisalahammad

Copy link
Copy Markdown
Contributor

Summary

New site-level setting Maximum Cache Folder Size (MB) under Cache -> Purge. When set > 0, a 15-min cron task measures the regenerable asset subdirs (css, js, ucss, ccss, optimax, lqip, avatar, localres) and prunes the oldest files until the tree is at 90% of the configured cap. Default 0 keeps the cron as a no-op, so existing installs are unaffected. Fixes #777.

Changes

src/folder.cls.php (new)

Before: No automated protection. wp-content/litespeed grows unbounded under aggressive bot traffic (WooCommerce filter URL combinations in the repro), eventually filling the disk.
After: Static cron callback that walks the asset subdirs with a RecursiveIteratorIterator, sums sizes, and when over budget deletes oldest files first via wp_delete_file, capped at 5000 files per run to avoid hogging a single tick.
Why: Issue #777 asks for a cap. The hot path (File::save) cannot run a recursive scan per write, so enforcement lives in a low-frequency cron. 90% hysteresis prevents thrash. 5000-file per-run cap resumes on the next tick instead of stalling cron.

src/task.cls.php

Before: No cron entry for folder size.
After: Adds 'litespeed_task_folder_size' to the triggers map, hooked to LiteSpeed\Folder::cron on the standard 15-min 'litespeed_filter' schedule. Task::try_clean clears the schedule when the setting goes back to 0.
Why: Reuses the existing 15-min cron infrastructure; the trigger map pattern is used by every other recurring task in the plugin.

src/base.cls.php

Before: No option id for the new setting.
After: Adds O_MISC_MAX_FOLDER_SIZE const, default 0 in the site-level options array, and the new id in _conf_cron check_ids so saves propagate to Task::try_clean.
Why: Setting registration chain (const -> default -> check_ids) is the established pattern in this file.

tpl/cache/settings-purge.tpl.php

Before: No UI for the new setting.
After: Adds an MB input row before the closing , mirroring the existing O_DEBUG_FILESIZE MB-input pattern. Includes description and _validate_ttl range guard (1-100000).
Why: Cache -> Purge tab is the right home for size-driven purge controls.

data/const.default.json

Before: No default for the new id.
After: Empty-string default so first-install reads the site-level default (0).
Why: Required by the Conf auto-sync flow.

src/lang.cls.php

Before: No title.
After: 'Maximum Cache Folder Size' label.
Why: Required by the title() helper.

autoload.php

Before: src/folder.cls.php not in the require list.
After: Added between file.cls.php and guest.cls.php, alphabetical order.
Why: autoload.php hardcodes the require_once list and the spl_autoload fallback only handles thirdparty/. Without this entry, the new class would not be loaded and the cron callback would fatal.

readme.txt

Before: No 8.0 changelog entry.
After: Bullet under '= 8.0 - Coming soon 2026 =' describing the limit and oldest-first pruning.
Why: Discoverability for the feature and a clear signal for the maintainer during release.

Testing

Test 1: setting UI shows up

  1. Go to LiteSpeed Cache -> Cache -> Purge.
  2. Confirm 'Maximum Cache Folder Size' row with empty input and the description text.
    Result: row renders, persists.

Test 2: disabled (default) is a no-op

  1. Leave the field empty, save.
  2. wp cron event list shows no litespeed_task_folder_size.
  3. wp-content/litespeed/ size is unaffected.
    Result: BC preserved.

Test 3: enabled triggers oldest-first prune

  1. Enable CSS/JS Combine and UCSS, visit a few pages to grow css/js/ucss.
  2. Set Maximum Cache Folder Size to 1 (MB), save.
  3. Run wp cron event run litespeed_task_folder_size.
  4. du -sb wp-content/litespeed/ is now under ~900 KB.
  5. Debug log shows '[Folder] Pruned N file(s) to enforce 1 MB limit (...).
    Result: works as expected.

Test 4: disable clears the schedule

  1. Set the field back to 0, save.
  2. wp cron event list no longer lists litespeed_task_folder_size.
    Result: works as expected.

Test 5: bot-traffic simulation (original repro from #777)

  1. Set the field to 5 MB.
  2. Hit the site with a parameter sweep (?filter_color=red, ?filter_color=blue, ...).
  3. css/js/ucss subdirs stay under the cap; the cron reclaims oldest files.
    Result: works as expected.

Test 6: phpcs
vendor/bin/phpcs --standard=phpcs.ruleset.xml --no-cache autoload.php src/folder.cls.php src/task.cls.php src/base.cls.php src/lang.cls.php tpl/cache/settings-purge.tpl.php
Result: 0 errors, 0 warnings.

@faisalahammad
faisalahammad force-pushed the fix/777-max-cache-folder-size branch from 02b7fd6 to e3911f5 Compare August 9, 2026 13:46
@faisalahammad
faisalahammad changed the base branch from master to dev August 9, 2026 13:46
@timotei-litespeed

Copy link
Copy Markdown
Contributor

@faisalahammad there are some conflicts in this PR

…peedtech#777)

- New site-level setting 'Maximum Cache Folder Size' (MB) under Cache -> Purge
- 15-min cron task (litespeed_task_folder_size) measures regenerable
  asset subdirs (css, js, ucss, ccss, optimax, lqip, avatar, localres)
  and prunes oldest-first down to a 90% hysteresis target
- Default 0 keeps the cron as a no-op (BC). Setting reduced to 0
  clears the schedule via the standard _conf_cron / Task::try_clean path
- Multisite-safe: the recursive iterator walks all blog_id subfolders
- Skips debug, cloud, auto-backup, crawler subdirs and root files
  (.litespeed_conf.dat, .htaccess, robots.txt). WebP/AVIF live in
  uploads/ and are not affected
- Recreates .htaccess via File::ensure_static_protection() if the
  asset tree is fully cleared

Fixes litespeedtech#777
@faisalahammad
faisalahammad force-pushed the fix/777-max-cache-folder-size branch from e3911f5 to e792526 Compare August 10, 2026 20:40
@faisalahammad

Copy link
Copy Markdown
Contributor Author

Rebased on latest dev and resolved readme.txt changelog conflict. New cache folder size bullet now sits under 8.0 section. Also fixed folder pruning review findings: verify deletion state and continue safely on iterator errors. Ready for re-review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature request] Max size for LS cache folder

2 participants