Skip to content

Preserve guide data across EPG refresh failures - #182

Merged
cbulock merged 2 commits into
mainfrom
codex/epg-refresh-resilience
Sep 6, 2026
Merged

cbulock merged 2 commits into
mainfrom
codex/epg-refresh-resilience

Conversation

@cbulock

@cbulock cbulock commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Summary

  • retain last-known-good XMLTV per source during transient fetch or file failures
  • report explicit ok, degraded, and ailed EPG refresh outcomes through HTTP, scheduler, and MCP
  • serialize refresh requests and follow an in-flight pass with the latest requested configuration
  • remove the duplicate module interval; scheduler owns periodic refreshes

Validation

  • �slint . passes
  • 193 non-integration tests pass
  • est/integration/guide.test.js passes (7 tests), including stale fallback, recovery, and all-source failure
  • git diff --check passes

Copilot AI lite review requested due to automatic review settings September 6, 2026 15:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Some newly introduced outcome messaging and error-wrapping behavior is misleading or drops important error metadata, which can impair operational diagnosis and client handling.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR improves EPG refresh resiliency by retaining last-known-good XMLTV per source when a fetch/read fails, and by surfacing explicit refresh outcomes (ok, degraded, failed) through the scheduler, HTTP reload endpoint, and MCP tool.

Changes:

  • Serialize concurrent EPG refresh requests and return a structured refresh outcome from refreshEPG().
  • Retain and reuse last-good per-source XMLTV data to keep guide output available during transient source failures, and remove the module-owned periodic interval in favor of the scheduler job.
  • Expand integration coverage to validate stale fallback, recovery, and all-source failure behavior.
File summaries
File Description
test/integration/guide.test.js Adds integration coverage for stale fallback, recovery, and full failure outcomes.
server/epg.js Implements serialized refresh orchestration, per-source last-good retention, and refresh outcome reporting.
server/scheduler.js Treats failed refresh outcomes as job failures while allowing degraded runs to succeed.
server/mcp.js Returns explicit MCP error on failed outcome and includes outcome details in reload_epg responses.
server/config.js Updates /api/reload/epg to return outcome status and per-source results to callers.
Review details

Suppressed comments (1)

server/epg.js:430

  • Wrapping the Axios error in a new Error drops Axios-specific fields (e.g., err.code / err.response.status), so the downstream catch block’s actionable logging branches won’t run when there is no last-known-good fallback.
          } catch (httpErr) {
            sourceFetchError = new Error(`Failed to fetch EPG: ${httpErr.message}`);
            const lastGood = lastGoodSourceXml.get(sourceName);
            if (!lastGood || lastGood.url !== sourceUrl) {
              throw sourceFetchError;
            }
  • Files reviewed: 5/5 changed files
  • Comments generated: 4
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread server/config.js
Comment on lines +290 to +293
res.status(outcome.status === 'degraded' ? 207 : 200).json({
status: outcome.status,
sources: outcome.sourceResults,
});
Comment thread server/epg.js
Comment on lines 409 to +414
} catch (fileErr) {
throw new Error(`Failed to read file: ${fileErr.message}`);
sourceFetchError = new Error(`Failed to read file: ${fileErr.message}`);
const lastGood = lastGoodSourceXml.get(sourceName);
if (!lastGood || lastGood.url !== sourceUrl) {
throw sourceFetchError;
}
Comment thread server/epg.js
Comment on lines +614 to +616
const message = epgSources.length
? 'All configured EPG sources failed; retained the previous guide.'
: 'No EPG sources are configured.';
Comment thread server/mcp.js Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@cbulock
cbulock merged commit 6cbbcc3 into main Sep 6, 2026
5 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants