perf: replace sleep(5) with 429 backoff and add cache warm-up script

This commit is contained in:
2026-07-27 02:06:06 +04:00
parent 3b074f00d8
commit b994383bf4
4 changed files with 100 additions and 21 deletions
+15
View File
@@ -319,6 +319,21 @@ grep STATIC_CACHE_NAME sw.js # le suffixe de version a été bumpé à l'heure d
Le bump de version dans `sw.js` est fait *sur le serveur uniquement* : le dépôt garde sa valeur de référence, le working tree du serveur est nettoyé (`git checkout -- sw.js`) avant chaque pull pour garantir le fast-forward.
== 🔥 Préchauffage du cache
Pour éviter que le premier visiteur ne paye le coût des appels API externes (PeerTube, Castopod) sur cache froid, préchauffez le cache par cron :
[source,bash]
----
# Toutes les 5 minutes, avec l'utilisateur deploy
sudo -u deploy crontab -e
# Ajouter :
*/5 * * * * php /var/www/annu-kute-ced/scripts/warm-cache.php >/dev/null 2>&1
----
Le script `scripts/warm-cache.php` appelle les fonctions de récupération des vidéos, catégories, podcasts et live, ce qui remplit `cache/api/` avant l'arrivée des visiteurs.
== 🧰 Dépannage
[cols="1,3",options="header"]
+10 -4
View File
@@ -197,7 +197,8 @@ Toutes ces sources sont modifiables dans `includes/config.local.php` (voir <<fr-
│ ├── pleroma-adapter.js # Adaptateur Pleroma → API Mastodon
│ └── pwa-update.js # Enregistrement SW + modal de mise à jour
├── scripts/
── check.sh # Vérifications qualité en local (avant push)
── check.sh # Vérifications qualité en local (avant push)
│ └── warm-cache.php # Préchauffage du cache API (cron)
├── uploads/ # Images d'annonces (non versionné, hors .gitkeep)
├── index.php # Page d'accueil (agrégateur)
├── video.php # Page de lecture d'une vidéo
@@ -415,7 +416,7 @@ Valeurs par défaut issues de `includes/config.default.php`.
| Nombre total d'épisodes affichés
|===
WARNING: Castopod applique un *rate limit* strict (HTTP 429) sur les flux RSS. Le code patiente 5 s entre chaque podcast. *Activez le cache* (`CACHE_ENABLED`) pour éviter ces délais à chaque page.
WARNING: Castopod applique un *rate limit* strict (HTTP 429) sur les flux RSS. Le code applique un backoff exponentiel (5 s, 10 s, 15 s) uniquement en cas de 429. *Activez le cache* (`CACHE_ENABLED`) et préchauffez-le avec `scripts/warm-cache.php` pour éviter ces délais à chaque page.
.Funkwhale (musique, optionnel)
[cols="2,2,3",options="header"]
@@ -695,6 +696,8 @@ TIP: Si vous déployez une instance indépendante, remplacez `LIBERAPAY_URL` par
NOTE: Le cache de l'API PeerTube et de WordPress (`includes/simple-cache.php`) est *toujours actif*, indépendamment de `CACHE_ENABLED`, avec des TTL par endpoint (catégories 1 h, vidéos/recherche 10 min, articles WP 15 min, comptes 5 min). Les fichiers sont stockés dans `cache/api/`.
TIP: Pour éviter que le premier visiteur ne paye le coût des appels API sur cache froid, préchauffez le cache via cron : `php /var/www/annu-kute-ced/scripts/warm-cache.php` (toutes les 5 minutes par exemple).
.Sécurité
[cols="2,2,3",options="header"]
|===
@@ -1167,7 +1170,8 @@ All of these sources can be changed in `includes/config.local.php` (see <<en-con
│ ├── pleroma-adapter.js # Pleroma → Mastodon API adapter
│ └── pwa-update.js # SW registration + update modal
├── scripts/
── check.sh # Local quality checks (before pushing)
── check.sh # Local quality checks (before pushing)
│ └── warm-cache.php # API cache warm-up (cron)
├── uploads/ # Announcement images (not versioned, except .gitkeep)
├── index.php # Homepage (aggregator)
├── video.php # Video playback page
@@ -1385,7 +1389,7 @@ Default values from `includes/config.default.php`.
| Total number of episodes displayed
|===
WARNING: Castopod enforces a strict *rate limit* (HTTP 429) on RSS feeds. The code waits 5 s between podcasts. *Enable the cache* (`CACHE_ENABLED`) to avoid these delays on every page.
WARNING: Castopod enforces a strict *rate limit* (HTTP 429) on RSS feeds. The code applies exponential backoff (5 s, 10 s, 15 s) only on HTTP 429. *Enable the cache* (`CACHE_ENABLED`) and warm it with `scripts/warm-cache.php` to avoid these delays on every page.
.Funkwhale (music, optional)
[cols="2,2,3",options="header"]
@@ -1665,6 +1669,8 @@ TIP: If you deploy an independent instance, replace `LIBERAPAY_URL` with your ow
NOTE: The PeerTube API and WordPress cache (`includes/simple-cache.php`) is *always on*, regardless of `CACHE_ENABLED`, with per-endpoint TTLs (categories 1 h, videos/search 10 min, WP posts 15 min, accounts 5 min). Files are stored in `cache/api/`.
TIP: To prevent the first visitor from paying the cost of API calls on a cold cache, warm the cache via cron: `php /var/www/annu-kute-ced/scripts/warm-cache.php` (every 5 minutes for example).
.Security
[cols="2,2,3",options="header"]
|===
+19 -7
View File
@@ -690,16 +690,16 @@ function getCastopodEpisodes($castopodUrl = null, $podcastSlugs = null, $count =
// Itérer sur chaque podcast
foreach ($podcastSlugs as $index => $podcastSlug) {
try {
// Ajouter un délai entre les requêtes pour éviter le rate limiting (sauf pour la première)
// Note: Castopod a un rate limit strict, le cache est fortement recommandé
if ($index > 0) {
sleep(5); // 5 secondes de délai minimum pour Castopod
}
// Construire l'URL du feed RSS pour ce podcast
$feedUrl = rtrim($castopodUrl, '/') . '/@' . $podcastSlug . '/feed';
// Récupérer le feed RSS
// Récupérer le feed RSS avec backoff uniquement sur rate limit (HTTP 429)
$maxAttempts = 3;
$attempt = 0;
$xmlContent = false;
$httpCode = 0;
while ($attempt < $maxAttempts) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $feedUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
@@ -711,6 +711,18 @@ function getCastopodEpisodes($castopodUrl = null, $podcastSlugs = null, $count =
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Succès ou erreur définitive : on sort de la boucle
if ($httpCode !== 429) {
break;
}
// Rate limit : attendre avant de réessayer (backoff exponentiel simple)
$attempt++;
if ($attempt < $maxAttempts) {
sleep(5 * $attempt);
}
}
if ($httpCode !== 200 || !$xmlContent) {
continue; // Passer au podcast suivant en cas d'erreur
}
+46
View File
@@ -0,0 +1,46 @@
<?php
/**
* Préchauffe le cache API de l'application.
*
* À appeler en tâche cron pour éviter que le premier visiteur ne paye le coût
* des appels API externes (PeerTube, Castopod, Funkwhale) sur cache froid.
*
* Exemple cron (toutes les 5 minutes) :
* php /var/www/annu-kute-ced/scripts/warm-cache.php >/dev/null 2>&1
* (à programmer toutes les 5 minutes dans la crontab)
*/
require_once __DIR__ . '/../includes/config.php';
$start = microtime(true);
$results = [];
// Vidéos PeerTube
$results['recent_videos'] = count(getRecentVideos());
$results['trending_videos'] = count(getTrendingVideos());
$results['shorts'] = count(getShorts());
// Catégories affichées
$categories = getDisplayCategories();
$results['display_categories'] = count($categories);
foreach ($categories as $category) {
$results['category_' . $category['id']] = count(getVideosByCategory($category['id']));
}
// Live
$live = getLiveStream();
$results['live_stream'] = $live ? 1 : 0;
// Podcasts Castopod
$results['castopod_episodes'] = count(getCastopodEpisodes());
// Funkwhale (si activé)
if (defined('FUNKWHALE_ENABLED') && FUNKWHALE_ENABLED) {
$results['funkwhale_tracks'] = count(getFunkwhaleTracks());
}
$duration = round(microtime(true) - $start, 2);
echo "Cache préchauffé en {$duration}s\n";
foreach ($results as $key => $value) {
echo " - {$key}: {$value}\n";
}