Skip to content

feat: release v3.0.0 - asynchronous purging and memory optimization#53

Merged
denji merged 3 commits intomasterfrom
develop
Apr 17, 2026
Merged

feat: release v3.0.0 - asynchronous purging and memory optimization#53
denji merged 3 commits intomasterfrom
develop

Conversation

@denji
Copy link
Copy Markdown
Member

@denji denji commented Mar 28, 2026

Redesign background queue system, fix memory leaks and walk blocking

Memory Management:

  • Fixed memory leak in partial purge operations — buffers now stack-allocated per file visit instead of allocated from ngx_cycle pool on every call.
  • Eliminated per-file heap allocations in walk handlers by switching to a fixed-size key_buffer inside ngx_http_cache_purge_walk_ctx_t.

Background Queue System:

  • Implemented asynchronous purge queue backed by shared memory so the queue persists across worker restarts and is visible to all worker processes.
  • Queue processes one item per timer tick then yields back to the nginx event loop, guaranteeing connections are served normally between directory walks.
  • Added queue size limit and per-item timeout to guard against flooding and stale entries accumulating during worker downtime.

Deduplication:

  • ngx_http_cache_purge_find_duplicate now performs a two-step check: hash comparison first, then full ngx_memcmp on both cache_path and key string. Hash-only comparison silently discarded legitimate purge requests whenever two distinct keys produced the same 32-bit hash value.

Security & Stability:

  • Hardened file operations with path traversal protection and proper handle cleanup on all exit paths.
  • Purge endpoints should be restricted via access control lists or auth directives — the module does not enforce this itself.

No configuration directives removed, or renamed.
All existing defaults and behaviour for non-background purge paths unchanged.

denji added 2 commits March 28, 2026 19:12
This major update introduces a redesigned background queue system
and addresses critical memory management issues.

Memory Management & Performance:
- Fixed a critical memory leak in partial purge operations (previously
  improperly allocated from the 'ngx_cycle' pool).
- Eliminated per-file memory allocations by switching to stack-based buffers.
- Introduced batch processing and hash-based deduplication to reduce
  system load and I/O saturation.

Background Queue System:
- Implemented an asynchronous purge system to prevent request blocking.
- Added a shared memory queue that persists across worker restarts.
- Integrated configurable throttling to limit CPU and I/O impact.

Security & Stability:
- Hardened file operations with path traversal protection and
  proper handle cleanup.
- Added protection against queue flooding via size limits and timeouts.
- Recommended: Restrict purge endpoints using access control or auth.
Three correctness and reliability fixes to the background purge queue.
No configuration directives added, removed, or renamed.

- ngx_http_cache_purge_find_duplicate: hash-only comparison replaced
  with two-step check (hash, then ngx_memcmp on cache_path and key).
  Hash collisions between distinct keys previously caused the second
  purge request to be silently discarded as a duplicate.

- ngx_msleep() removed from all three walk handlers
  (delete_file, delete_partial_file, delete_exact_file).
  ngx_msleep is a literal usleep() call that blocks the OS thread,
  stalling every connection on the worker for the sleep duration.
  throttle_ms and batch_count removed from ngx_http_cache_purge_walk_ctx_t.
  NGX_CACHE_PURGE_BATCH_MAX constant removed.

- process_queue refactored from batch-per-tick to one-item-per-tick.
  The background handler now dequeues and walks one item per invocation,
  then re-arms the timer with throttle_ms. This gives the event loop a
  guaranteed yield between every directory walk. throttle_ms now controls
  inter-walk delay through the timer rather than intra-walk blocking sleep.
  The queue, all directives, and all defaults are unchanged.
This patch fixes a regression where wildcard purges and 'purge_all'
requests incorrectly returned 412/404, even when successful.

Previously, ngx_http_cache_purge_partial() returned void, causing
handlers to fall through to an exact-key lookup. Since wildcard/bulk
keys don't exist as exact entries, the module would report a miss.

Changes:
- Update ngx_http_cache_purge_partial() to return the count of deleted files.
- Short-circuit handlers after wildcard/purge_all operations to prevent
  unnecessary exact-key lookups and shm locks.
- Ensure 'purge_all' always returns 200 OK, as it is a zone-wide operation.
- Align wildcard miss behavior with 'cache_purge_legacy_status' (412/404).
- Update documentation and add regression tests for status code consistency.
@denji denji merged commit 1177237 into master Apr 17, 2026
14 checks passed
@kasparsd
Copy link
Copy Markdown

Great work on getting this merged! 👍

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.

2 participants