Preserve food search results and respect provider availability - #134
Merged
Conversation
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The new curl fallback parsing can mask real transport failures as “missing HTTP status” and should surface exit code/stderr when no status trailer is present.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR improves backend food search resilience by caching recent successful results in-process and preserving provider availability semantics (HTTP 429/503 + Retry-After) end-to-end, so the public /search-food endpoint can surface actionable cooldown information and avoid unnecessary upstream retries during outages.
Changes:
- Add process-local caching (LRU, bounded to 64 entries, 5-minute TTL) for successful non-empty Open Food Facts search results, returning deep-copied models to callers.
- Preserve provider-directed unavailability (429/503 + Retry-After) across primary and fallback transports, and enforce a shared cooldown that blocks new upstream attempts while still serving cached results.
- Update backend endpoint behavior, tests, and public data-safety documentation to reflect the new caching and availability handling.
File summaries
| File | Description |
|---|---|
| docs/public/data-safety.md | Documents the new in-process caching behavior and provider-directed cooldown handling. |
| backend/app/services/food_search_availability.py | Introduces shared cache + provider cooldown state and Retry-After parsing utilities. |
| backend/app/services/open_food_facts.py | Integrates caching/cooldowns into governed attempts and preserves 429/503 through fallback transports. |
| backend/app/main.py | Maps FoodSearchUnavailable into 429/503 HTTP responses with Retry-After and no-store/no-cache headers. |
| backend/tests/test_food_search_availability.py | Adds focused unit tests for cache bounds/TTL and cooldown behavior. |
| backend/tests/test_open_food_facts_normalization.py | Extends tests to cover caching survival during outages and fallback transport 429/503 preservation. |
| backend/tests/test_endpoints.py | Verifies the public endpoint forwards 429/503 + headers without leaking query text into responses/logs. |
Review details
- Files reviewed: 7/7 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Food search loses the provider's availability status: an Open Food Facts 503 becomes a generic CalorieApp 502, and another click starts another upstream search. A direct check of the existing search endpoint on 8 September returned HTTP 503 with the provider's temporary-unavailability page.
This PR:
The provider's outage itself remains external; a first uncached search cannot be guaranteed to succeed while it is unavailable. The separately documented Search-a-licious endpoint has not been verified here and is not introduced by this PR.
Validation: 142 targeted backend tests passed, covering search responses, fallback transport parsing and safe diagnostics, caching/expiry, provider pauses (including a pause started during rate reservation), rate governance, admission and log privacy. Source-boundary checks passed. The first review finding is fixed in
7dda309d67ef7f19c95e37ce09a96f0b65a03fde: curl transport failures retain their numeric exit code without exposing private stderr; known HTTP errors keep their status and Retry-After. The review thread is resolved. All four jobs in CI 34183525207 passed on this updated head. A fresh Copilot review was requested, but no new reviewer event or completed bot review of this commit has been confirmed; the resolved finding is not represented as a new approval.Scope: backend search only plus tests/documentation. No WordPress plugin, frontend, identity/login/logout or database-schema change. WordPress 0.3.27 remains installed. No merge, deployment or migration has been performed.
References: Open Food Facts API guidance, search API guidance. Follow-up to #132.