perf: cache locking, TTL map, purge script and SW LRU limit

This commit is contained in:
2026-07-27 09:15:00 +04:00
parent 8181dbd57c
commit cb13fcfb9f
3 changed files with 206 additions and 28 deletions
+74 -28
View File
@@ -6,11 +6,11 @@
class SimpleAPICache {
private $cacheDir;
private $enabled;
public function __construct() {
$this->cacheDir = __DIR__ . '/../cache/api';
public function __construct($cacheDir = null) {
$this->cacheDir = $cacheDir ?? (__DIR__ . '/../cache/api');
$this->enabled = true;
// Créer le répertoire de cache s'il n'existe pas
if (!is_dir($this->cacheDir)) {
mkdir($this->cacheDir, 0755, true);
@@ -66,9 +66,28 @@ class SimpleAPICache {
'created' => time()
];
file_put_contents($file, json_encode($data));
// Verrou exclusif : évite les écritures concurrentes tronquées
file_put_contents($file, json_encode($data), LOCK_EX);
}
/**
* Vide entièrement le cache (entrées valides comme expirées)
*
* @return int Nombre de fichiers supprimés
*/
public function clear() {
$files = glob($this->cacheDir . '/cache_*.json');
$deleted = 0;
foreach ($files as $file) {
if (unlink($file)) {
$deleted++;
}
}
return $deleted;
}
/**
* Nettoie le cache expiré
*/
@@ -91,44 +110,71 @@ class SimpleAPICache {
// Instance globale
$GLOBALS['simple_api_cache'] = new SimpleAPICache();
/**
* TTL de cache selon l'endpoint PeerTube.
*
* Correspondance exacte d'abord, puis par préfixe. L'ancien matching par
* sous-chaîne (strpos) créait des collisions : « accounts/{nom}/videos »
* capturait le TTL de « videos » (10 min) au lieu de celui de « accounts »
* (5 min, pensé pour les lives).
*
* @param string $endpoint Endpoint de l'API (sans slash initial)
* @return int TTL en secondes
*/
function getPeerTubeCacheTtl($endpoint) {
static $exactMap = [
'videos/categories' => 3600, // 1 heure
'videos' => 600, // 10 minutes
'search/videos' => 600, // 10 minutes
'wp-posts' => 900, // 15 minutes pour WordPress
'accounts' => 300 // 5 minutes pour live streams
];
static $prefixMap = [
'accounts/' => 300, // lives : accounts/{nom}/videos
'video-channels/' => 600, // vidéos d'une chaîne
'videos/' => 600 // videos/{id}, commentaires
];
if (isset($exactMap[$endpoint])) {
return $exactMap[$endpoint];
}
foreach ($prefixMap as $prefix => $ttl) {
if (strpos($endpoint, $prefix) === 0) {
return $ttl;
}
}
return 300; // Défaut 5 minutes
}
/**
* Version cachée de callPeerTubeApi - remplace l'originale
*/
function callPeerTubeApiCached($endpoint, $params = []) {
$cache = $GLOBALS['simple_api_cache'];
// TTL selon le type de contenu
$ttlMap = [
'videos/categories' => 3600, // 1 heure
'videos' => 600, // 10 minutes (augmenté)
'search/videos' => 600, // 10 minutes
'wp-posts' => 900, // 15 minutes pour WordPress
'accounts' => 300 // 5 minutes pour live streams
];
// TTL dynamique selon l'endpoint
$ttl = 300; // Défaut 5 minutes
foreach ($ttlMap as $pattern => $time) {
if (strpos($endpoint, $pattern) !== false) {
$ttl = $time;
break;
}
// Cache désactivé : appel direct, sans lecture ni écriture
if (!defined('CACHE_ENABLED') || !CACHE_ENABLED) {
return callPeerTubeApiOriginal($endpoint, $params);
}
$cache = $GLOBALS['simple_api_cache'];
$ttl = getPeerTubeCacheTtl($endpoint);
// Essayer le cache d'abord
$cached = $cache->get($endpoint, $params);
if ($cached !== null) {
return $cached;
}
// Appeler l'API originale
$data = callPeerTubeApiOriginal($endpoint, $params);
// Mettre en cache si on a des données
if (!empty($data)) {
$cache->set($endpoint, $params, $data, $ttl);
}
return $data;
}