litespeedtech / litespeedtech/lscache_wp

[API] No supported way to enumerate what was purged — tooling must parse the debug log

Open
#1,046 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
PHP
Stars
257
Forks
123
PR merge metrics
No merged PRs in 30d

Description

### Summary

There is no supported way to ask LiteSpeed Cache *what it has purged*. The only record of a purge having fired is the debug log, whose line format, file path and timestamp encoding are internal implementation detail. Tooling that needs to confirm a purge actually happened has to parse that log, which breaks silently when the format changes.

### The gap

`Purge` accumulates tags and emits `X-LiteSpeed-Purge` headers, and there are `litespeed_purged_*` actions for some paths. But there is no read side: no way to query "which tags/URLs were purged in this request", and nothing persisted that a later request can inspect.

This appears to be the root cause shared by several existing open requests, each asking for a hook covering one specific purge path:

- #558 — `litespeed_api_purge_post` is documented but commented out in `src/api.cls.php`
- #570 — asks for a single-URL equivalent of `litespeed_purged_all`
- #615 — no hook for the *related* purges (front page, blog page) a post purge triggers

Each is reasonable on its own, and each would be satisfied by a general observability surface rather than another one-off hook.

### What we do without it, and why it is fragile

We operate a small fleet of WordPress sites with tooling that reports cache state to operators. To answer "did that purge actually fire", it parses the LSCache debug log:

- the path moved in LSCache 6.5
- timestamps are `gmdate( 'm/d/y H:i:s', $sec + LITESPEED_TIME_OFFSET )` (`src/debug2.cls.php:489`) — a 2-digit year with an offset applied
- the anchor is the literal `X-LiteSpeed-Purge:` line shape

None of that is contract, and all of it is reasonable for you to change. When it changes our parser returns **an empty list rather than an error**, which reads as "no purges happened" — a wrong answer that looks like a valid one. We re-verify it on every LiteSpeed release for exactly this reason (7.9 → 7.9.1 was fine; `debug2.cls.php` is byte-identical at the relevant lines).

`log_purge()` also writes request context — REQUEST_URI, query string, referer, cookie — into the same file, so anything parsing it is reading attacker-influenceable text and has to treat it as untrusted.

### Suggested shapes

Any one of these would remove the need to parse the log:

1. **A getter on `Purge`** returning the tags queued in the current request — the smallest change, and enough for same-request verification.
2. **A general action** fired for every purge with its type and payload, e.g. `do_action( 'litespeed_purged', $type, $tags )`. This would also close #558, #570 and #615 in one go.
3. **A short-lived persisted record** (last N purges with timestamp, type and tags) readable by other requests and WP-CLI — the most useful for operational tooling, and the only one that answers "did the scheduled purge run overnight".

(2) seems like the best ratio of effort to benefit, and it fits the existing `litespeed_purged_*` naming.

### Environment

- LiteSpeed Cache **7.9.1**
- Not a bug report — the current behaviour is consistent, there is simply no read side to it

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the Purge implementation and existing litespeed_purged_* actions, then inspect src/api.cls.php and src/debug2.cls.php for the current hook and logging paths. The issue presents multiple possible designs, so first establish the supported observability contract. Done means purge activity can be consumed without parsing debug logs and covers the paths represented by #558, #570, and #615.

Written by the indexing model from the issue text.

Assessment

Tech stack
php, wordpress
Domain
api, backend, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.