Framework updates
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
105
app/RSpade/Core/FPC/Rsx_FPC.php
Executable file
105
app/RSpade/Core/FPC/Rsx_FPC.php
Executable 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user