mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 19:19:19 +02:00
feat: system page caching via SystemCache + system_cache SQLite table
Add a TTL-based cache for the expensive checks on the admin system page,
eliminating repeated systemctl subprocess calls (~4×~100ms), curl self-pings
(~200-500ms), disk_*_space() and PHP ini reads on every page load.
Changes:
- storage/migrations/007_system_cache.sql: new migration creating the
system_cache table (key TEXT PK, value TEXT, updated_at INTEGER)
- storage/schema.sql: system_cache table added before pages table
- Applied migration to live storage/posterg.db
- src/SystemCache.php: new class with get/set/isStale/ageSeconds/invalidate;
uses SQLite INSERT … ON CONFLICT upsert; no external dependencies
- src/Database.php: added getDatabasePath(): string accessor
- public/admin/system.php:
- Bootstrap SystemCache at request start using the existing DB PDO handle
- system_status: cached with 2-min TTL (systemctl + curl checks)
- php_info: cached with 1-hour TTL (PHP ini values are runtime-constant)
- disk_info: cached with 5-min TTL (total/free/used/pct tuple)
- Logs section: unchanged — always reads live log tail per active tab
- ?refresh=1 GET param invalidates all three cache keys before rendering
- Status panel heading shows cache badge: '⚡ Cache — il y a Xs' (hit)
or '⟳ Actualisé' (miss/fresh), styled via new .sys-cache-badge rules
- public/assets/css/system.css: .sys-cache-badge / --hit / --miss styles
This commit is contained in:
16
TODO.md
16
TODO.md
@@ -58,20 +58,22 @@ The admin system page (`/admin/system.php`) runs expensive operations on every l
|
||||
- Nginx config file reading
|
||||
|
||||
### Solution: `system_cache` table + background refresh
|
||||
- [ ] **Add `system_cache` table** to schema: `CREATE TABLE system_cache (key TEXT PRIMARY KEY, value TEXT NOT NULL, updated_at INTEGER NOT NULL)` — stores JSON-encoded status snapshots keyed by section
|
||||
- [ ] **Add migration** `storage/migrations/007_system_cache.sql` to create the table
|
||||
- [ ] **Add `SystemCache` class** (`src/SystemCache.php`) with methods:
|
||||
- [x] **Add `system_cache` table** to schema: `CREATE TABLE system_cache (key TEXT PRIMARY KEY, value TEXT NOT NULL, updated_at INTEGER NOT NULL)` — stores JSON-encoded status snapshots keyed by section
|
||||
- [x] **Add migration** `storage/migrations/007_system_cache.sql` to create the table
|
||||
- [x] **Add `SystemCache` class** (`src/SystemCache.php`) with methods:
|
||||
- `get(string $key, int $maxAgeSec = 60): ?array` — returns cached JSON data if fresh, null if stale
|
||||
- `set(string $key, array $data): void` — upserts cache row
|
||||
- `isStale(string $key, int $maxAgeSec = 60): bool`
|
||||
- [ ] **Refactor `system.php` status section** to:
|
||||
- `ageSeconds(string $key): ?int` — returns age of cached entry in seconds
|
||||
- `invalidate(string $key): void` — force-deletes a cache entry
|
||||
- [x] **Refactor `system.php` status section** to:
|
||||
1. Check `SystemCache::get('system_status', 120)` — 2-minute TTL
|
||||
2. If cache hit → render from cache, show "mis en cache il y a X sec" label
|
||||
3. If cache miss → run checks, store in cache, render
|
||||
4. Add `?refresh=1` GET param to force-bypass cache
|
||||
- [ ] **Refactor `system.php` log sections** to not cache (logs should always be live) but avoid re-reading on every tab switch — only read the active tab's log
|
||||
- [ ] **Cache disk info** separately with 5-minute TTL: `SystemCache::get('disk_info', 300)`
|
||||
- [ ] **Cache PHP info** separately with 1-hour TTL: `SystemCache::get('php_info', 3600)` — PHP config doesn't change at runtime
|
||||
- [x] **Refactor `system.php` log sections** to not cache (logs should always be live) but avoid re-reading on every tab switch — only read the active tab's log
|
||||
- [x] **Cache disk info** separately with 5-minute TTL: `SystemCache::get('disk_info', 300)`
|
||||
- [x] **Cache PHP info** separately with 1-hour TTL: `SystemCache::get('php_info', 3600)` — PHP config doesn't change at runtime
|
||||
|
||||
## In Progress (from previous plan)
|
||||
- [ ] Extract `SearchController` — most complex public page (§2 step 4)
|
||||
|
||||
Reference in New Issue
Block a user