Flux agrégés : signaler les feeds en erreur dans l'admin #45

Closed
opened 2026-05-13 22:10:04 +00:00 by cedricAbonnel · 0 comments
Owner

Problème

Quand FeedFetcher::get() échoue (feed hors-ligne, XML malformé, timeout…), l'erreur est silencieuse : le feed disparaît de /flux sans aucune explication, ni pour l'admin ni pour l'utilisateur qui l'a ajouté.

Comportement souhaité

L'admin voit dans /flux (ou dans un futur onglet admin) la liste des feeds en erreur avec l'URL concernée, pour pouvoir les retirer ou contacter l'utilisateur.


Analyse technique

État actuel (public/index.php, case 'flux', ligne 1229)

foreach ($st->fetchAll(PDO::FETCH_ASSOC) as $_row) {
    $data = $fetcher->get($_row['feed_url']);
    if (!$data) {
        continue;  // ← échec silencieux
    }
    // ...
}

Implémentation

1. Collecter les erreurs dans la boucle :

$fluxErrors = [];

foreach ($st->fetchAll(PDO::FETCH_ASSOC) as $_row) {
    $data = $fetcher->get($_row['feed_url']);
    if (!$data) {
        $fluxErrors[] = [
            'feed_url'    => $_row['feed_url'],
            'label'       => $_row['label'],
            'author_name' => $_row['display_name'] ?? '',
        ];
        continue;
    }
    // ...
}

2. Passer $fluxErrors au template et afficher un bandeau admin dans templates/flux.php :

<?php if (!empty($fluxErrors) && isAdmin()): ?>
<div class="alert alert-warning mb-4">
    <strong><?= count($fluxErrors) ?> feed(s) en erreur :</strong>
    <ul class="mb-0 mt-1">
        <?php foreach ($fluxErrors as $_e): ?>
        <li>
            <?= htmlspecialchars($_e['label'] ?: $_e['feed_url']) ?>
            <span class="text-muted small">(<?= htmlspecialchars($_e['author_name']) ?>)</span>
            — <code class="small"><?= htmlspecialchars($_e['feed_url']) ?></code>
        </li>
        <?php endforeach; ?>
    </ul>
</div>
<?php endif; ?>

3. Optionnel : stocker la dernière erreur dans le cache

Dans FeedFetcher::fetch(), en cas d'échec, écrire dans le cache un marker :

// Dans fetch(), si $raw === false ou $httpCode >= 400 :
$this->cacheWrite($url, [
    'error'      => true,
    'error_code' => $httpCode,
    'fetched_at' => time(),
    'ttl'        => 300, // retry dans 5 min
]);
return null;

Cela évite de retenter une URL morte à chaque chargement de page (TTL court pour réessayer rapidement).

4. Dans FeedFetcher::get(), distinguer cache valide vs cache erreur :

$cached = $this->cacheRead($url);
if ($cached !== null) {
    if (!empty($cached['error'])) {
        // Cache d'erreur encore valide → ne pas retenter
        if (time() < $cached['fetched_at'] + $cached['ttl']) {
            return null;
        }
    } elseif (time() < $cached['fetched_at'] + $cached['ttl']) {
        return $cached;
    }
}

Fichiers concernés

  • public/index.phpcase 'flux' : collecter $fluxErrors (~5 lignes)
  • templates/flux.php — bandeau d'erreur admin (~15 lignes)
  • src/FeedFetcher.php — cache des erreurs + TTL court en cas d'échec (~15 lignes)

Migré depuis varlog#60

## Problème Quand `FeedFetcher::get()` échoue (feed hors-ligne, XML malformé, timeout…), l'erreur est silencieuse : le feed disparaît de `/flux` sans aucune explication, ni pour l'admin ni pour l'utilisateur qui l'a ajouté. ## Comportement souhaité L'admin voit dans `/flux` (ou dans un futur onglet admin) la liste des feeds en erreur avec l'URL concernée, pour pouvoir les retirer ou contacter l'utilisateur. --- ## Analyse technique ### État actuel (`public/index.php`, `case 'flux'`, ligne 1229) ```php foreach ($st->fetchAll(PDO::FETCH_ASSOC) as $_row) { $data = $fetcher->get($_row['feed_url']); if (!$data) { continue; // ← échec silencieux } // ... } ``` ### Implémentation **1. Collecter les erreurs dans la boucle** : ```php $fluxErrors = []; foreach ($st->fetchAll(PDO::FETCH_ASSOC) as $_row) { $data = $fetcher->get($_row['feed_url']); if (!$data) { $fluxErrors[] = [ 'feed_url' => $_row['feed_url'], 'label' => $_row['label'], 'author_name' => $_row['display_name'] ?? '', ]; continue; } // ... } ``` **2. Passer `$fluxErrors` au template** et afficher un bandeau admin dans `templates/flux.php` : ```php <?php if (!empty($fluxErrors) && isAdmin()): ?> <div class="alert alert-warning mb-4"> <strong><?= count($fluxErrors) ?> feed(s) en erreur :</strong> <ul class="mb-0 mt-1"> <?php foreach ($fluxErrors as $_e): ?> <li> <?= htmlspecialchars($_e['label'] ?: $_e['feed_url']) ?> <span class="text-muted small">(<?= htmlspecialchars($_e['author_name']) ?>)</span> — <code class="small"><?= htmlspecialchars($_e['feed_url']) ?></code> </li> <?php endforeach; ?> </ul> </div> <?php endif; ?> ``` **3. Optionnel : stocker la dernière erreur dans le cache** Dans `FeedFetcher::fetch()`, en cas d'échec, écrire dans le cache un marker : ```php // Dans fetch(), si $raw === false ou $httpCode >= 400 : $this->cacheWrite($url, [ 'error' => true, 'error_code' => $httpCode, 'fetched_at' => time(), 'ttl' => 300, // retry dans 5 min ]); return null; ``` Cela évite de retenter une URL morte à chaque chargement de page (TTL court pour réessayer rapidement). **4. Dans `FeedFetcher::get()`, distinguer cache valide vs cache erreur** : ```php $cached = $this->cacheRead($url); if ($cached !== null) { if (!empty($cached['error'])) { // Cache d'erreur encore valide → ne pas retenter if (time() < $cached['fetched_at'] + $cached['ttl']) { return null; } } elseif (time() < $cached['fetched_at'] + $cached['ttl']) { return $cached; } } ``` --- ## Fichiers concernés - `public/index.php` — `case 'flux'` : collecter `$fluxErrors` (~5 lignes) - `templates/flux.php` — bandeau d'erreur admin (~15 lignes) - `src/FeedFetcher.php` — cache des erreurs + TTL court en cas d'échec (~15 lignes) --- *Migré depuis [varlog#60](https://git.abonnel.fr/cedricAbonnel/varlog/issues/60)*
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: cedricAbonnel/folio#45