Skip to content

feat: implement cache fallback for resilient API responses - #4

Merged
surrealwolf merged 10 commits into
mainfrom
feature/cache-fallback
Oct 21, 2025
Merged

surrealwolf merged 10 commits into
mainfrom
feature/cache-fallback

Conversation

@surrealwolf

Copy link
Copy Markdown
Collaborator

Description

Implements cache fallback mechanism for API endpoints so they gracefully degrade when the Hell Divers 2 community API becomes unavailable. Previously, 5 endpoints would fail with 404 errors if the upstream API went offline. Now they fall back to the most recent cached data in the database.

Problem

When Hell Divers 2 community API (api.helldivers2.dev) is offline:

  • /api/planets - Returns 404 instead of cached data
  • /api/campaigns - Returns 404 instead of cached data
  • /api/planets/{index} - Returns 404 instead of cached data
  • /api/factions - Returns 404 instead of cached data
  • /api/biomes - Returns 404 instead of cached data

Solution

Implemented cache-first-with-fallback pattern on all 5 endpoints:

  1. Try to fetch fresh data from live API
  2. If API call fails (returns None), fall back to most recent cached data
  3. If no cache available, return 503 Service Unavailable

Changes

Database (src/database.py)

Added 4 new snapshot methods for cache fallback:

  • get_latest_planets_snapshot() - All planets from most recent collection
  • get_latest_campaigns_snapshot() - All campaigns from most recent collection
  • get_latest_factions_snapshot() - Extracted from war status cache
  • get_latest_biomes_snapshot() - Extracted from planet cache

API (src/app.py)

Updated 5 endpoints with cache fallback:

  • /api/planets - Try live, fallback to cache
  • /api/campaigns - Try live, fallback to cache
  • /api/planets/{index} - Try live, fallback to cache
  • /api/factions - Try live, fallback to cache
  • /api/biomes - Try live, fallback to cache

Testing

  • All 11 unit tests passing
  • Linting: ruff all checks passed
  • Type checking: mypy success with no issues

HTTP Status Codes

  • 200 - Success (fresh data from API or cached data)
  • 503 - Service unavailable (API down and no cached data)

Checklist

  • All tests passing
  • Linting passes
  • Type checking passes
  • No breaking changes
  • Improves system resilience

Copilot AI review requested due to automatic review settings October 20, 2025 05:53

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.

Pull Request Overview

Adds cache-fallback logic to serve the most recent database snapshots when the upstream Hell Divers 2 API is unavailable, improving resiliency of several endpoints.

  • Introduces four new snapshot helpers in the database layer.
  • Updates five API endpoints to try live fetch first and fall back to cached data; returns 503 when both are unavailable.

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
src/database.py Adds snapshot retrieval methods for planets, campaigns, factions, and biomes to support cache fallback.
src/app.py Implements cache-first-with-fallback on campaigns, planets, planet status by index, factions, and biomes endpoints; updates error codes to 503 when no cache is present.
Comments suppressed due to low confidence (1)

src/app.py:1

  • The same truthiness issue applies here; empty but valid objects would incorrectly fall through to the fallback and potentially to a 503. Replace with None checks: if data is None: for fallback and if data is not None: before returning.
import logging

Comment thread src/app.py Outdated
Comment thread src/app.py
Comment thread src/app.py
Comment thread src/app.py
Comment thread src/database.py Outdated
Copilot AI review requested due to automatic review settings October 20, 2025 05:59

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.

Pull Request Overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

Comment thread src/app.py Outdated
Comment thread src/app.py Outdated
Comment thread src/app.py Outdated
Copilot AI review requested due to automatic review settings October 20, 2025 06:45

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.

Pull Request Overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 8 comments.

Comments suppressed due to low confidence (1)

src/app.py:1

  • This endpoint calls collector.collect_planet_data(planet_index), which (per its design) collects and persists, but does not synchronously return the planet status payload for response. This will likely return None and always trigger the fallback path. Use scraper.get_planet_status(planet_index) for the live fetch, and align the fallback check to 'is None' for consistency with other endpoints.
import logging

Comment thread src/collector.py Outdated
Comment thread src/collector.py Outdated
Comment thread src/collector.py Outdated
Comment thread src/collector.py
Comment thread src/app.py Outdated
Comment thread src/app.py
Comment thread src/app.py
Comment thread src/app.py
Copilot AI review requested due to automatic review settings October 21, 2025 03:26

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.

Pull Request Overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Comment thread src/app.py Outdated
Comment thread src/collector.py Outdated
Comment thread src/collector.py Outdated
Comment thread src/scraper.py Outdated
@surrealwolf

Copy link
Copy Markdown
Collaborator Author

✅ Resolution Summary

All review comments have been addressed and resolved:

Fixed Issues:

  1. None vs Truthiness Checks - Converted all endpoints to use explicit is None/is not None checks instead of truthiness checks
  2. HTTP Status Codes - Maintained backward compatibility with 404 status codes per comment recommendations
  3. Health Endpoint - Removed upstream API call to prevent blocking the event loop
  4. Type Safety - Added isinstance() guard before accessing dict methods on biome field
  5. Collector Logic - Updated to use is not None for success tracking separate from truthiness for persistence
  6. Non-existent Methods - Removed calls to self.scraper.set_upstream_status() which doesn't exist
  7. Unused Variables - Removed unused success_count and failure_count variables

Current Status:

  • ✅ All 11 unit tests passing
  • ✅ Ruff linting: 0 errors
  • ✅ Mypy type checking: 0 issues
  • ✅ Code ready for CI

The feature branch is ready for merge once GitHub Actions CI confirms all tests pass across all matrix jobs (ubuntu/macos/windows × Python 3.13/3.14).

Copilot AI review requested due to automatic review settings October 21, 2025 03:43

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.

Pull Request Overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

Comment thread src/app.py Outdated
Comment thread src/database.py Outdated
Comment thread src/collector.py Outdated
Comment thread src/app.py Outdated
@surrealwolf
surrealwolf merged commit 8adbff3 into main Oct 21, 2025
8 checks passed
@surrealwolf
surrealwolf deleted the feature/cache-fallback branch October 21, 2025 04:00
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