Framework updates

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2026-03-12 19:09:07 +00:00
parent 3294fc7337
commit daa9bb2fb1
47 changed files with 2495 additions and 525 deletions

105
app/RSpade/Core/FPC/Rsx_FPC.php Executable file
View File

@@ -0,0 +1,105 @@
<?php
namespace App\RSpade\Core\FPC;
use App\RSpade\Core\Manifest\Manifest;
/**
* Full Page Cache management utility
*
* Provides methods to clear FPC entries from Redis.
* The FPC is a Node.js reverse proxy that caches responses
* marked with #[FPC] attribute in Redis.
*
* Cache key format: fpc:{build_key}:{sha1(url)}
* Redis DB: 0 (shared cache database with LRU eviction)
*/
class Rsx_FPC
{
/**
* Clear all FPC cache entries for the current build key
*
* @return int Number of deleted entries
*/
public static function clear(): int
{
$redis = self::_get_redis();
if (!$redis) {
return 0;
}
$build_key = Manifest::get_build_key();
$pattern = "fpc:{$build_key}:*";
$count = 0;
// Use SCAN to avoid blocking Redis with KEYS
$iterator = null;
do {
$keys = $redis->scan($iterator, $pattern, 100);
if ($keys !== false && count($keys) > 0) {
$count += $redis->del($keys);
}
} while ($iterator > 0);
return $count;
}
/**
* Clear FPC cache for a specific URL
*
* @param string $url The URL path with optional query string (e.g., '/about' or '/search?q=test')
* @return bool True if entry was deleted
*/
public static function clear_url(string $url): bool
{
$redis = self::_get_redis();
if (!$redis) {
return false;
}
$build_key = Manifest::get_build_key();
// Parse and sort query params to match the proxy's key generation
$parsed = parse_url($url);
$path = $parsed['path'] ?? $url;
if (!empty($parsed['query'])) {
parse_str($parsed['query'], $params);
ksort($params);
$full_url = $path . '?' . http_build_query($params);
} else {
$full_url = $path;
}
$hash = sha1($full_url);
$key = "fpc:{$build_key}:{$hash}";
return $redis->del($key) > 0;
}
/**
* Get Redis connection for FPC operations
* Uses DB 0 (cache DB with LRU eviction)
*/
private static function _get_redis(): ?\Redis
{
static $redis = null;
if ($redis) {
return $redis;
}
$redis = new \Redis();
$host = env('REDIS_HOST', '127.0.0.1');
$port = (int) env('REDIS_PORT', 6379);
try {
$redis->connect($host, $port, 2.0);
$redis->select(0);
return $redis;
} catch (\Throwable $e) {
$redis = null;
return null;
}
}
}