Skip to content

Where PHP Iterators End, Ripgrep Begins

Choose a tag to compare

@hsntgm hsntgm released this 28 Apr 11:59
d81c2c2

πŸš€ Nginx Cache Purge Preload β€” v2.1.6

Where PHP Iterators End, Ripgrep Begins.

πŸ› οΈ 63 files changed Β |Β  βž• 10,344 lines Β |Β  βž– 7,287 lines β€” Faster Lookups. Granular Control. Smarter Purging.


✨ What's New

⚑ Ripgrep-Powered Cache Lookups (major milestone)

ripgrep (rg) is now deeply integrated into NPP's cache engine β€” replacing heavy recursive PHP iterators as the primary driver for both single-URL purges and full cache directory scans.

πŸ—οΈ Purge Architecture β€” Fast-Path Chain

Single-URL purges follow a layered fallback strategy. rg now slots in at FP3, ahead of the PHP recursive scan:

Fast-Path Method Condition
FP1 HTTP Purge via ngx_cache_purge Module enabled in Settings
FP2 Index lookup URL present in persistent index
FP3 RG Purge (new) rg installed
FP4 PHP RecursiveDirectoryIterator Ultimate fallback

On large caches, FP4 can take 30–60 seconds during Advanced Tab loads and 10–20 seconds during single-URL purges. RG Purge (FP3) reduces this to 1–2 seconds regardless of cache size, using ripgrep's parallel, memory-mapped I/O and early-exit strategy.

πŸ“‚ Advanced Tab Load Timings

The Advanced tab (Cache Manager) scans every cache file, on large caches this is the dominant cost. The scan method depends on what's installed:

Environment Method Speed
No ripgrep PHP RecursiveDirectoryIterator over FUSE 🐌 Slowest
ripgrep, no safexec rg over FUSE mount 🟑 Faster
ripgrep + safexec rg via safexec β€” FUSE bypassed βœ… Fastest

Real-world benchmark β€” 8,000 URLs, containerised FUSE (bindfs) environment

Setup Advanced Tab Load
PHP only ⚠️ ~21 seconds
ripgrep + safexec βœ… ~5 seconds

~76% reduction in load time. Gains scale with cache size.

FUSE mounts (bindfs) bridge every open() and read() through a userspace daemon β€” each file op crosses the FUSE boundary, multiplying I/O cost. safexec drops rg's privileges to the Nginx user and runs it directly against the real source path on disk, bypassing the FUSE layer entirely with zero FUSE crossings.

With ripgrep + safexec in place, the only remaining Advanced Tab overhead is DOM rendering β€” the cached-URL table is a client-side DataTable sourced entirely from the scan payload. The scan itself even with FUSE mount is no longer the bottleneck.

The same rg scanning chain also runs automatically during Scheduled Preload, Preload All, and many other places where rg is detected on the system.

πŸš€ Setup

apt install ripgrep   # Debian / Ubuntu
dnf install ripgrep   # RHEL / Fedora
apk add ripgrep       # Alpine Linux

Install safexec for security first and then for FUSE environments β€” see Help Tab β†’ "What is safexec?" for the one-liner installer. Once both are present, NPP detects and uses them automatically. Confirm in the Status tab.


πŸŽ›οΈ Revamped Auto Purge System (major milestone)

The single global Auto Purge toggle is gone β€” replaced with a full suite of granular, event-based controls.

  • Gives you precise, per-event management over what triggers a cache purge.
  • Improved compatibility across Gutenberg, Elementor, Classic Editor, Redis Cache, and WooCommerce.
  • Replaces one blunt switch with targeted controls β€” purge what you need, when you need it.

πŸ”“ Custom Cache Directory Override (major milestone)

Power users can now override default cache directory restrictions when their setup demands it.

  • Unlocks non-standard cache path roots for advanced configurations.
  • ⚠️ Use with extreme caution β€” intended for power users only. Misconfiguration can cause unintended purges.

🐾 Additional Highlights

  • Custom Mobile User Agent β€” define your own UA string for mobile cache variant detection.
  • Pre-bootstrap Abuse Logger β€” logs abuse attempts against NPP endpoints before the plugin fully initialises.
  • open_basedir documentation β€” important warnings and guidance added for environments with open_basedir restrictions. (Thanks to @tvarga77)
  • $request_method fix β€” resolved a long-standing issue where strict GET filtering caused partial failures on cache keys without a defined $request_method. NPP now purges both GET and HEAD requests. (Huge thanks to Slava Shevchenko @kaganvmz)
  • GLOB_BRACE safeguards β€” compatibility fixes for Alpine Linux and musl libc environments.

πŸ”’ Performance & Reliability

  • Replaced recursive filesystem iteration in permission checks with a lightweight write/delete probe.
  • Eliminated redundant recursive PHP filesystem iterations across Purge and Preload processes.
  • Significantly optimised Advanced and Status Tab load timings via refined background data retrieval and ripgrep integration.
  • Fixed Auto Preload failing to trigger after manual single-URL purges on the front page and Advanced Tab.
  • Fixed the index updater cron job failing to run.
  • Fixed a visual bug where the Preload Progress bar reached 100% while background preloading was still in progress.
  • Improved compatibility with FUSE mount cache paths via safexec.
  • Improved handling of diverse Nginx cache_key formats, including custom $request_method and URI structures.

πŸ—‘οΈ Changed / Updated

  • safexec updated to v1.9.6 β€” ⚠️ Update required alongside this plugin release.

🧩 Where to Find Things

Feature Location
Ripgrep requirements Help Tab β†’ Ripgrep / RG Purge
Auto Purge event controls Settings β†’ Auto Purge
Cache Directory Override Settings β†’ Advanced (power users only)
Custom Mobile User Agent Settings β†’ Preload Options
open_basedir guidance Help Tab
Abuse Logger Active pre-bootstrap on all NPP endpoints

πŸ”„ Upgrade Notes

  1. Update the plugin to v2.1.6 as usual.
  2. ⚠️ Update safexec to v1.9.6 β€” this is required alongside the plugin update.
  3. If rg (ripgrep) is not installed on your server, visit Help Tab β†’ Ripgrep for setup instructions. The plugin falls back gracefully, but installing rg is strongly recommended for best performance.
  4. Review your Auto Purge settings β€” the single global toggle has been replaced with granular event-based controls. Re-configure as needed after updating.
  5. If you run Alpine Linux or a musl libc environment, the GLOB_BRACE fix in this release resolves known compatibility issues β€” no action needed beyond updating.

πŸ™ Credits

Huge thanks to everyone who tested and reported issues. Special shout-out to @kaganvmz (Slava Shevchenko) for identifying the $request_method filtering bug, and to @tvarga77 for flagging the open_basedir compatibility gap. πŸ’™


πŸ“œ Changelog

  • Performance (MILESTONE): Replaced heavy recursive PHP iterators with ripgrep (rg) as the primary fast-path for cache lookups β€” dramatically accelerates purges and tab load timings, especially for 10,000+ URL sites.
  • Performance: Replaced recursive filesystem iteration in permission checks with a lightweight write/delete probe.
  • Performance: Eliminated redundant recursive PHP filesystem iterations across Purge and Preload.
  • Added (MILESTONE): Completely revamped Auto Purge system β€” single global toggle replaced with granular, event-based controls.
  • Added (MILESTONE): Power user override for default cache directory restrictions. Use with caution.
  • Added: Custom Mobile User Agent support.
  • Added: Pre-bootstrap Abuse Logger for NPP endpoints.
  • Added: Documentation and warnings for open_basedir restrictions. (Thanks to @tvarga77)
  • Fixed: Long-standing issue where strict $request_method (GET) filtering caused partial failures on cache keys without a defined $request_method. (Thanks to @kaganvmz)
  • Fixed: Auto Preload not triggering after manual single-URL purges on front page and Advanced Tab.
  • Fixed: GLOB_BRACE usage safeguards for Alpine Linux / musl libc compatibility.
  • Fixed: Index updater cron job failing to run.
  • Fixed: Preload Progress bar visually reaching 100% before background preloading completed.
  • Improved: Purge Single pipeline (FP1–FP4) β€” RG Purge fast-path.
  • Improved: Auto Purge compatibility with Gutenberg, Elementor, Classic Editor, Redis Cache, and WooCommerce.
  • Improved: FUSE mount cache path compatibility with safexec.
  • Improved: Handling of diverse Nginx cache_key formats including custom $request_method and URI structures.
  • Improved: $request_method filtering β€” NPP now purges both GET and HEAD requests.
  • Improved: Advanced and Status Tab load timings via refined background data retrieval and ripgrep.
  • Updated: safexec 1.9.6 β€” ⚠️ Update required.
  • Compatibility: Tested with WordPress 6.9, PHP 8.4, Nginx 1.30.0, FUSE 3.18.2, safexec 1.9.6 and bindfs 1.18.4.