audio streaming app plyr.fm
38
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: self-healing logic for missing image URLs (#311)

Implements a check in the track listing endpoint to detect tracks with an 'image_id' but missing 'image_url'. Attempts to resolve the URL from storage; if the file is missing, it clears the 'image_id' to prevent future expensive lookups (ghost reads). This fixes performance issues caused by N+1 storage calls for missing files.

authored by

nate nowack and committed by
GitHub
db9e74e5 3d616e1d

+34
+34
src/backend/api/tracks/listing.py
··· 111 111 # commit any PDS URL updates 112 112 await db.commit() 113 113 114 + # resolve missing image URLs and self-heal invalid image_ids 115 + # this prevents repeated R2 404 checks ("ghost reads") for missing files 116 + tracks_needing_images = [t for t in tracks if t.image_id and not t.image_url] 117 + if tracks_needing_images: 118 + with logfire.span( 119 + "resolve missing images", count=len(tracks_needing_images), _level="debug" 120 + ): 121 + 122 + async def resolve_image(track: Track) -> None: 123 + """Resolve image URL and update track state.""" 124 + try: 125 + url = await track.get_image_url() 126 + if url: 127 + track.image_url = url 128 + else: 129 + # image_id exists but file not found in R2 130 + # clear image_id to prevent future lookups 131 + logfire.warn( 132 + "clearing invalid image_id", 133 + track_id=track.id, 134 + image_id=track.image_id, 135 + ) 136 + track.image_id = None 137 + track.image_url = None 138 + except Exception as e: 139 + logfire.warn( 140 + "failed to resolve image", 141 + track_id=track.id, 142 + error=str(e), 143 + ) 144 + 145 + await asyncio.gather(*[resolve_image(t) for t in tracks_needing_images]) 146 + await db.commit() 147 + 114 148 # fetch all track responses concurrently with like status and counts 115 149 track_responses = await asyncio.gather( 116 150 *[