-
Notifications
You must be signed in to change notification settings - Fork 2.1k
fix: SDK Doctor repair for intermittent stale cache, improve status badges and tooltips #41875
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
8 files reviewed, no comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes intermittent stale cache issues in SDK Doctor and improves the user experience with better status badges, tooltips, and version detection. It addresses user confusion around version displays and adds auto-refresh logic to detect and handle stale caches.
Key changes:
- Implemented auto-refresh logic to detect stale caches (>26 hours) and trigger background refresh
- Fixed
cachedAttimestamp accuracy by storing actual timestamp when writing to Redis - Added lazy-loading endpoint for release dates of SDK versions not in the main cache
- Improved status badges with amber/green/red color scheme and comprehensive tooltips showing release dates
Reviewed Changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| posthog/urls.py | Added new endpoint for lazy-loading individual SDK version dates |
| posthog/api/team_sdk_versions.py | Updated cache format to include cachedAt timestamp with backward compatibility |
| posthog/api/github_sdk_versions.py | Added SDK version date endpoint with fallback tag format support and SDK repo mapping |
| dags/sdk_doctor/team_sdk_versions.py | Store actual timestamp when caching instead of calculating from TTL later |
| dags/sdk_doctor/github_sdk_versions.py | Added cachedAt timestamp to GitHub SDK version cache data |
| frontend/src/layout/navigation-3000/sidepanel/sidePanelLogic.tsx | Moved Status tab to appear earlier in the tab list |
| frontend/src/layout/navigation-3000/sidepanel/panels/sidePanelSdkDoctorLogic.tsx | Added lazy-loading logic for missing release dates and auto-refresh for stale caches |
| frontend/src/layout/navigation-3000/sidepanel/panels/SidePanelSdkDoctor.tsx | Updated UI with improved tooltips and removed redundant status badges |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const sdkVersion = sdkVersions[sdkType as SdkType] | ||
|
|
||
| // Merge lazy-loaded dates | ||
| const mergedReleaseDates = { ...sdkVersion.releaseDates } |
Copilot
AI
Nov 21, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential null reference error. sdkVersion could be undefined if the SDK type exists in teamSdkVersions but not in sdkVersions. Add a null check before accessing sdkVersion.releaseDates to prevent runtime errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 5th commit
| teamVersions.forEach((versionInfo) => { | ||
| if (typeof versionInfo !== 'object' || !('lib_version' in versionInfo)) { | ||
| return | ||
| } | ||
| const version = versionInfo.lib_version | ||
| // Avoid duplicate API calls for already-loaded dates | ||
| const hasReleaseDate = | ||
| sdkVersion.releaseDates[version] !== undefined || | ||
| values.lazyLoadedDates[`${sdkType}:${version}`] !== undefined | ||
|
|
||
| if (!hasReleaseDate) { | ||
| // Background load updates state when ready | ||
| actions.loadVersionDate({ sdkType: sdkType as SdkType, version }) | ||
| } | ||
| }) | ||
| }) |
Copilot
AI
Nov 21, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The teamVersions variable may not be an array when iterating over teamSdkVersions entries. The code needs to check if teamVersions is an array before calling forEach, similar to the filtering logic in the selector at line 223. This could cause a runtime error if metadata fields like cached or cachedAt are present.
| teamVersions.forEach((versionInfo) => { | |
| if (typeof versionInfo !== 'object' || !('lib_version' in versionInfo)) { | |
| return | |
| } | |
| const version = versionInfo.lib_version | |
| // Avoid duplicate API calls for already-loaded dates | |
| const hasReleaseDate = | |
| sdkVersion.releaseDates[version] !== undefined || | |
| values.lazyLoadedDates[`${sdkType}:${version}`] !== undefined | |
| if (!hasReleaseDate) { | |
| // Background load updates state when ready | |
| actions.loadVersionDate({ sdkType: sdkType as SdkType, version }) | |
| } | |
| }) | |
| }) | |
| if (Array.isArray(teamVersions)) { | |
| teamVersions.forEach((versionInfo) => { | |
| if (typeof versionInfo !== 'object' || !('lib_version' in versionInfo)) { | |
| return | |
| } | |
| const version = versionInfo.lib_version | |
| // Avoid duplicate API calls for already-loaded dates | |
| const hasReleaseDate = | |
| sdkVersion.releaseDates[version] !== undefined || | |
| values.lazyLoadedDates[`${sdkType}:${version}`] !== undefined | |
| if (!hasReleaseDate) { | |
| // Background load updates state when ready | |
| actions.loadVersionDate({ sdkType: sdkType as SdkType, version }) | |
| } | |
| }) | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 4th commit
| github_url = f"https://api.github.com/repos/{repo}/releases/tags/{tag_name}" | ||
| response = requests.get(github_url, timeout=10) |
Copilot
AI
Nov 21, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GitHub API requests are made without authentication, which limits the rate to 60 requests per hour per IP. This could cause issues in production with multiple users triggering lazy-loads. Consider adding GitHub token authentication via headers to increase the rate limit to 5,000 requests per hour.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 4th commit
| response = requests.get(github_url, timeout=10) | ||
|
|
||
| if response.status_code == 200: |
Copilot
AI
Nov 21, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing rate limit handling for GitHub API. When the rate limit is exceeded (status code 403), the endpoint returns a 404 error, which could be misleading. Consider checking for rate limit errors (status 403 with rate limit headers) and returning a more appropriate error message to help with debugging.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 4th commit
| Upgrading is a good idea, but it's not urgent yet. | ||
| </> | ||
| ) : ( | ||
| "Upgrading is a good idea, but it's not urgent yet" |
Copilot
AI
Nov 21, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Inconsistent quotation mark usage. This line uses double quotes while the surrounding JSX uses single quotes. Consider using single quotes for consistency with the rest of the codebase.
| "Upgrading is a good idea, but it's not urgent yet" | |
| 'Upgrading is a good idea, but it\'s not urgent yet' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 4th commit
| except (json.JSONDecodeError, AttributeError): | ||
| pass |
Copilot
AI
Nov 21, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'except' clause does nothing but pass and there is no explanatory comment.
| except (json.JSONDecodeError, AttributeError): | |
| pass | |
| except (json.JSONDecodeError, AttributeError) as e: | |
| logger.warning(f"[SDK Doctor] Failed to decode cachedAt for team {team_id}", error=str(e)) | |
| capture_exception(e) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 4th commit
|
Size Change: 0 B Total Size: 3.4 MB ℹ️ View Unchanged
|
|
Also added fallback for pre-monorepo release dates for node and react-native in the 4th commit. |
This PR addresses SDK Doctor feedback related to some issues with versions, release dates, status badges, and an intermittent stale cache problem we've seen (e.g. what Robbie saw in this slack thread. I've seen it a lot as well when impersonating users while working on support tickets.)
Problem:
Intermittent stale cache problem slack thread
Changes
(some of these also relate to other changes mentioned further below):
cachedAttimestamp accuracy: Store actual timestamp when writing to Redis instead of calculating from TTLcachedAtfield to GitHub SDK versions API responsecachedAtfield to team SDK versions API response with backward compatibility for old cache formatProblem:
Feedback from users confused by versions displayed, badges, lack of release date info, and versions less than a week old flagged as
Outdated(ZD tickets 41473, 41482, and this slack thread)Changes:
Removed redundant badges next to SDK name. Redundant and confusing because we're already Showing
SDK health is goodwith a green box sayingAll caught up...etc, ORTime for an update!with a yellow or red (in dark mode) box sayingAn outdated SDK means...etc., as well as next to the version number. The badge I'm removing here looked as if it was referring to the latest available version, as mentioned in a feedback ticket cited above (more related changes below these first two screenshots):before:
Recent(Related: fixed the problem with newer than github version cache so they are markedCurrent, details further below)≤7days old now markedRecent(was<7days)Releaseslink for versions released since cache timeProblem:
For monorepo SDKs, versions less than a month old had no release date info (because they were already out of reach of the 100 we're caching from GitHub.)
Changes:
Problem:
After using
Scan events, events can include releases newer than the github cache, so the newest version was incorrectly markedRecent.Changes:
Check most recent version against cached
Latest version availableand mark it asCurrent(instead ofRecent) if the semver of the team version is higher that then cached github versionScreenshots of the tooltips (because they make more sense when seen in the UI than when reading the code)...
Hovering over

Latest version available(screenshot taken just after midnight UTC):Hovering over a

Currentbadge:Hovering over a

Recentbadge:Hovering over an

Outdatedbadge of a legacy version format:How did you test this code?
On my local.