Fix podcast episode sync: per-show UUID uniqueness and episode creati… - #180
Merged
Merged
Conversation
…on reliability RSS GUIDs are only unique within a single feed, not globally. The previous global unique constraint on PodcastEpisode.episode_uuid caused IntegrityError when two shows shared any GUID, silently aborting all remaining episode creation for the second show. max_length=36 also blocked URL-format GUIDs on PostgreSQL. - Change episode_uuid from globally unique (max_length=36) to unique per show via unique_together, and increase max_length to 500 to accommodate URL GUIDs - Remove cross-show PodcastEpisode.objects.get() lookups in RSS sync paths that prevented episode creation when a GUID existed in any other show - Add per-episode try/except in all episode creation loops so one collision does not abort the entire sync for a show - Improve exception logging from debug to warning for RSS sync failures on the show detail page - Bundle decorator_include module to replace django-decorator-include dependency - Sync Item model with upstream fields: manual_metadata, provider_metadata_status - Sync PodcastEpisode.audio_url max_length with upstream (200 -> 500) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.
Summary
PodcastEpisode.episode_uuidhad a globalunique=Trueconstraint, but RSS GUIDs are only unique within a single feed. When any two shows shared a GUID,IntegrityErrorsilently aborted all remaining episode creation for the second show. Combined withmax_length=36, this also broke entirely on PostgreSQL (URL-format GUIDs are typically 50–200 chars).PodcastEpisode.objects.get(episode_uuid=...)globally — if the GUID existed in any show, the episode was skipped for the current show.Changes
PodcastEpisode.episode_uuid: globalunique=True(max_length=36) →unique_together = [("show", "episode_uuid")](max_length=500)0116_podcastepisode_uuid_fiximplementing the aboveobjects.get()lookups inviews.pyRSS sync pathstry/exceptin all episode creation loops (views.py,events/tasks.py,integrations/imports/pocketcasts.py)debug→warningfor RSS sync failures on show detail pagedecorator_includemodule (replacesdjango-decorator-includepackage dependency)Itemmodel with upstream fields:manual_metadata,provider_metadata_statusPodcastEpisode.audio_urlmax_length synced with upstream (200 → 500)Test plan
reload_calendartask — verify new episodes are added for existing showspython manage.py migrate— verify0116applies cleanly🤖 Generated with Claude Code
##Fixes
Issue #179