Add cache schema versioning and validation to fetch system#174
Add cache schema versioning and validation to fetch system#174jeremiah-k merged 19 commits intomainfrom
Conversation
Add cache schema versioning constants and validation system to ensure cache integrity. Includes schema version tracking in cache entries, a new _validate_release_entry method to verify release data structure, and validation checks during cache retrieval. Also adds a safety filter in the Android downloader to prevent prereleases from slipping through stable release filters, with automatic cache clearing on detection.
|
@coderabbitai review |
Summary of ChangesHello @jeremiah-k, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the reliability and integrity of the release caching system. It introduces schema versioning to cached data, allowing for automatic invalidation of outdated cache formats. Furthermore, it adds comprehensive validation checks for individual release entries within the cache, ensuring data integrity and preventing the use of malformed or incorrect data, such as prereleases mistakenly identified as stable. These changes aim to improve the overall stability and correctness of release data fetching by proactively handling potential cache corruption or format changes. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Code Review
This pull request introduces cache schema versioning and validation to improve the robustness of caching mechanisms. A defensive check was also added to the Android downloader. My review identifies a potential issue in the new cache validation logic that could lead to incorrect cache handling and suggests a correction. Additionally, I've pointed out a violation of encapsulation in the Android downloader's new defensive check and proposed a refactoring to improve the design.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdded a releases cache schema version constant and made releases cache read/write/prune/clear schema-aware with per-entry validation; Android downloader filters to stable releases and returns/clears history on invariant violations; project version bumped and tests extended for schema, pruning, and legacy-format normalization. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Downloader as Android Downloader
participant Cache as Releases Cache
participant GitHub as GitHub API
participant Logger
Client->>Downloader: request get_releases / update_release_history
Downloader->>Cache: read_releases_cache_entry(key)
alt cache valid & schema matches
Cache-->>Downloader: validated releases list
else cache miss / invalid / schema mismatch
Cache-->>Downloader: cache miss
Downloader->>GitHub: fetch releases
GitHub-->>Downloader: releases payload
Downloader->>Cache: write_releases_cache_entry(schema_version, releases)
end
Downloader->>Downloader: filter out prerelease entries
alt no stable releases
Downloader-->>Client: return None
else stable releases present
Downloader->>Cache: write_pruned_history(schema_version, releases)
Downloader-->>Client: return written history dict
end
alt invariant violation detected
Downloader->>Logger: log invariant violation ("Android")
Downloader->>Cache: clear_releases_cache()
Downloader-->>Client: return None
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
No actionable comments were generated in the recent review. 🎉 🧹 Recent nitpick comments
Tip Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
… helper method Introduce clear_releases_cache() method that handles path resolution and file removal internally. Simplify MeshtasticAndroidAppDownloader by replacing direct cache manager calls with the new abstraction. Revise write_json_with_timestamp() documentation to clarify atomic write behavior and timestamp key defaults.
…istic data - Add null assertions to verify cache read operations return valid data - Include prerelease and published_at fields in test releases data - Add type ignore comments for proper type checking with list indexing
|
/gemini review |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Code Review
This pull request introduces a cache schema versioning and validation system, which is a great step towards ensuring data integrity and forward compatibility. The changes are mostly well-implemented, with new constants for schema versions, validation logic for release entries, and a safety check in the Android downloader. My review includes a critical fix for the schema version validation to correctly handle old cache entries as described in the PR, and a suggestion to remove a redundant check in the Android downloader to improve code clarity. The test updates corresponding to these changes are appropriate.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
- Fix schema version validation to reject old cache entries (no schema_version field) - Replace redundant prerelease safety loop with invariant assertion - Add comprehensive tests for schema version validation (old format, mismatch, missing fields) - Add tests for update_release_history prerelease filtering - Fix existing test to include schema_version field This improves patch coverage for the cache schema versioning changes and simplifies the prerelease safety net logic.
|
/gemini review |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Code Review
This pull request introduces valuable improvements by adding schema versioning and validation to the caching system, making it more robust against malformed data. The changes are well-structured, with new constants for schema versions, validation logic in the CacheManager, and updated tests to cover the new behavior.
My main feedback is regarding the defensive guard in the Android downloader. The implementation uses an assert, which is disabled in production environments, rather than the intended production-safe check described in the pull request. I've provided a suggestion to align the code with the described behavior.
- Changed assert to if statement with logger.critical - Clear releases cache and return None if prerelease found in stable_releases - Addresses code review feedback: assert is removed in production (-O flag) - Ensures safety guard works in production environments
|
/gemini review |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Code Review
This pull request introduces cache schema versioning and validation, which is a significant improvement for cache robustness. The changes in cache.py and the associated tests are well-executed. I've identified a small issue in src/fetchtastic/download/android.py where a new safety check is logically unreachable. My review includes a suggestion to correct this, aligning the code with the stated intent of the pull request.
The check on lines 188-194 was logically unreachable: - Line 184 filters releases with: if not self._is_android_prerelease(r) - Line 188 checked if any: self._is_android_prerelease(r) for r in stable_releases - Since stable_releases only contains elements where NOT prerelease, the condition any(prerelease) can never be True The filtering logic is correct and complete. Cache corruption is already handled by the schema validation in cache.py (read_releases_cache_entry), which validates each entry and forces refresh on any invalid data. Removing dead code eliminates confusion and gives proper credit to the reviewer's correct observation. Addresses code review feedback about unreachable code.
|
@coderabbitai review |
|
/gemini review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Code Review
This pull request significantly improves the robustness of the caching system by introducing schema versioning and data validation. The changes are well-implemented and the new validation logic is a great step towards preventing issues with corrupted or outdated cache entries. The addition of comprehensive tests for the new caching behavior is also a valuable contribution. The PR description is clear, although there's a minor discrepancy regarding the replacement of an assert in MeshtasticAndroidAppDownloader, which I couldn't locate in the provided changes. Overall, this is a solid enhancement to the project's stability.
Docstrings generation was requested by @jeremiah-k. * #174 (comment) The following files were modified: * `src/fetchtastic/download/android.py` * `src/fetchtastic/download/cache.py`
Docstrings generation was requested by @jeremiah-k. * #174 (comment) The following files were modified: * `src/fetchtastic/download/android.py` * `src/fetchtastic/download/cache.py` Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces a robust cache schema versioning and validation system, which is a great improvement for handling cache consistency and preventing issues with outdated or malformed cached data. The centralization of pruning and normalization logic into the CacheManager is a significant refactoring that improves code clarity and maintainability. The replacement of an assert with production-safe error handling in the Android downloader is also a welcome change for stability. The new tests are comprehensive and cover the new functionality well. I have a couple of minor suggestions to improve type hints and docstrings for better maintainability.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@src/fetchtastic/download/android.py`:
- Around line 189-207: The invariant check that calls any(r.prerelease for r in
stable_releases) is unreachable because stable_releases is built by filtering
with self._is_android_prerelease(r) which already returns True when
release.prerelease is True; remove the dead branch or replace it with a
meaningful defense-in-depth check: either re-validate against the raw release
data (e.g., track the original release objects and check their prerelease field)
or change the comment to explicitly state this is a sanity assertion and keep it
as an assert (not runtime logic); update references to
self.cache_manager.clear_releases_cache() and the logger usage in the same block
accordingly so you don’t attempt to clear the cache for an unreachable
condition.
In `@src/fetchtastic/download/cache.py`:
- Around line 849-851: The docstring for the function that begins "Validate a
JSON cache file against an expiry period and return its parsed contents when
valid." contains a Unicode non‑breaking hyphen (U+2011) in "ISO‑8601"; replace
that character with a regular hyphen-minus (U+002D) so the text reads "ISO-8601"
to eliminate the RUF002 warning (search for the docstring text to locate the
correct function in src/fetchtastic/download/cache.py).
🧹 Nitpick comments (1)
src/fetchtastic/download/cache.py (1)
969-1036:prune_cache_datais well-designed; one minor observation on silent drops.Entries without a
cached_atfield (lines 1008–1009) are silently pruned with no log message. This is fine for the current callers but differs from the explicit debug logging for schema mismatches (lines 1023, 1026–1031). Consider adding a debug log for entries dropped due to missing/unparseablecached_atfor consistency, especially since this method ispublicand may be used by future callers who'd want visibility into why entries disappeared.🔍 Optional: add debug logging for entries without cached_at
if not cached_at_str: + logger.debug("Pruning entry without cached_at: %s", key) continue cached_at = parse_iso_datetime_utc(cached_at_str) if not cached_at: + logger.debug("Pruning entry with unparseable cached_at: %s", key) continue
…story update Removed the defensive invariant violation check that detected prereleases in the stable_releases list and cleared the cache. This simplifies the release history update flow by trusting the upstream filtering mechanism that already separates stable and prerelease candidates. The related test case has also been removed as the invariant is now considered unnecessary overhead.
|
@coderabbitai review |
|
/gemini review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Code Review
This pull request introduces a robust cache schema versioning and validation system, which is a significant improvement for data integrity and handling of cache format changes. The centralization of cache pruning logic into the prune_cache_data method is a great refactoring that enhances maintainability and consistency across different cache types. The new validation steps in read_releases_cache_entry provide strong guarantees against returning stale or malformed data. The accompanying tests are comprehensive, including a valuable integration test that verifies the schema mismatch and refresh flow. Overall, this is a high-quality contribution that significantly strengthens the caching layer.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/fetchtastic/download/android.py (1)
168-200:⚠️ Potential issue | 🟡 MinorDocstring describes removed invariant-check behavior.
The docstring (lines 174–179, 187) still references a "production invariant" check that clears the releases cache and returns
Noneon violation, but the code no longer contains this logic (it was removed per the commit history). TheReturnssection also lists "invariant violation" as a reason for returningNone.📝 Proposed docstring fix
def update_release_history( self, releases: List[Release], *, log_summary: bool = True ) -> Optional[Dict[str, Any]]: """ - Update the on-disk Android release history and optionally emit a summary log. - - Records only stable (non-prerelease) releases from the provided list into the persistent - release history. If no releases are provided or no stable releases are present, the - function returns None and does not modify history. As a defensive measure, if a - production invariant is violated (a prerelease is detected among the stable releases), - the function attempts to clear the releases cache and returns None without updating - the on-disk history. + Update the on-disk Android release history and optionally emit a summary log. + + Records only stable (non-prerelease) releases from the provided list into the persistent + release history. If no releases are provided or no stable releases are present, the + function returns None and does not modify history. Parameters: releases (List[Release]): Releases to record in history. log_summary (bool): When True, emit a concise release status summary to the log. Returns: - Optional[Dict[str, Any]]: The updated history data written to disk, or `None` when - no update was performed (no releases, no stable releases, or invariant violation). + Optional[Dict[str, Any]]: The updated history data written to disk, or `None` when + no update was performed (no releases or no stable releases). """
🧹 Nitpick comments (1)
src/fetchtastic/download/cache.py (1)
1004-1013: Entries withoutcached_atare silently discarded — consider a debug log.Lines 1008–1009 drop entries that have no
cached_at(or a falsy value) without any logging. While acceptable for a cache, adding alogger.debughere would aid diagnosing unexpected pruning, consistent with the debug logs on lines 1023 and 1026–1031 for schema mismatches.💡 Optional: add debug logging for entries dropped due to missing cached_at
if not cached_at_str: + logger.debug("Pruning entry without cached_at timestamp: %s", key) continue cached_at = parse_iso_datetime_utc(cached_at_str) if not cached_at: + logger.debug("Pruning entry with unparseable cached_at: %s", key) continue
|
@codex review |
|
Codex Review: Didn't find any major issues. Keep it up! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@coderabbitai review |
|
/gemini review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Code Review
This pull request introduces significant improvements to the caching system by adding schema versioning and validation, which greatly enhances robustness and maintainability. The centralization of cache pruning logic into a new prune_cache_data utility is a commendable refactoring that simplifies the codebase. The added tests, including a new integration test for schema mismatch, are thorough and provide good coverage for the new functionality. My review includes a couple of points for consideration, one regarding a potential discrepancy between documentation and implementation in the Android downloader, and another about a minor type consistency improvement in the cache module. Overall, this is a high-quality contribution.
…he debugging Remove the defensive prerelease invariant check from release history update in MeshtasticAndroidAppDownloader, simplifying the logic to just return None when no releases or no stable releases are present. Add debug logging to cache pruning to improve observability of entry invalidation, and ensure cache values are converted to lists for consistent data handling.
|
@coderabbitai review |
|
/gemini review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Code Review
This pull request introduces explicit cache schema versioning and validation, which is a great improvement for the robustness of the caching system. The centralization of cache pruning logic into CacheManager.prune_cache_data is a nice refactoring that simplifies the code and improves maintainability. The addition of comprehensive unit and integration tests, especially for schema mismatch scenarios, ensures the new functionality is working as expected. Overall, this is a high-quality contribution that significantly enhances the fetch system.
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
Overview
This PR adds explicit cache schema versioning and validation for the GitHub releases cache, centralizes pruning/normalization logic in the cache manager, replaces a development assert with production-safe behavior in the Android downloader, and updates tests and documentation. The intent is to make cache reads robust against legacy, malformed, or stale entries by treating mismatches/invalid data as cache misses and ensuring writes record the active schema version.
Key changes
Features
Fixes / Safety
Refactors / Misc
Migration / Breaking notes