fix(render): schedule image_url backfill on cache hits #216
No reviewers
Labels
No Label
ai-changes-requested
ai-failed
ai-merged
ai-pr-opened
ai-reviewed
ai-reviewing
ai-working
autonomous
bug
enhancement
evolution
performance
phase-0
phase-1a
phase-1b
phase-1c
phase-1d
security
size:M
size:S
tech-debt
todo
type:feature
type:stability
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: cal/paper-dynasty-database#216
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "fix/variant-image-url-cache"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Variant card rows with
image_url=NULLcould stay NULL forever once their PNG was cached on disk. The cache-hit short-circuit inget_batter_cardreturnedFileResponseimmediately, bypassing the backfillBackgroundTaskat the bottom of the full-render path. Any variant row recreated withimage_url=NULLwhile its PNG was still on disk stayed NULL forever, breaking every downstream consumer that readsbattingcard.image_url/pitchingcard.image_urlfor display.Confirmed today on dev: variant 415156387 on player 6557 (Nick Markakis), battingcard row 6342, has
image_url=NULLeven though the PNG is served athttps://paper-dynasty.s3.us-east-1.amazonaws.com/cards/cardset-012/player-6557/v415156387/battingcard.png. Two render endpoint 200s in dev API logs, zero backfill log lines.Fix
Extract
_schedule_variant_image_backfillhelper and wire it into both the cache-hit path and the full-render path. The helper's internal guards (variant > 0,tier is None, row exists with NULLimage_url) keep happy-path cache hits a no-op. Behavior-neutral for the full-render path.One function under surgery:
get_batter_cardinapp/routers_v2/players.py. No schema changes, no new dependencies.Design context:
docs/superpowers/plans/2026-04-11-variant-image-url-cache-bug.mdImpact
Not dev-only. Prod hits this any time a variant row is regenerated with a pre-existing cached PNG — admin corrections, manual data fixes, and (once PR #215 lands) the dev cleanup rollback endpoint followed by re-test.
Tests
tests/test_players_card_render.py:image_url=None→ backfill scheduledimage_urlpopulated → backfill NOT scheduledDoesNotExist) → no crash, no backfillvariant=0→ backfill NOT scheduledtierquery param set → backfill NOT scheduledDO NOT DEPLOY — Cal is manually testing against the dev API.
AI Code Review
Files Reviewed
app/routers_v2/players.py(modified)tests/test_players_card_render.py(added)Findings
Correctness
No issues found.
FileResponseimmediately without scheduling the backfill, leavingimage_url=NULLpermanently for any variant row recreated while its PNG was cached. The fix correctly calls_schedule_variant_image_backfillbefore returning.if variant > 0 and tier is None. New:if variant == 0 or tier is not None: return False. De Morgan's law — identical semantics.cached_pathextraction is consistent. Both theos.path.isfile()check and theFileResponsecall now use the same variable — eliminates the subtle dual-format-string duplication that was in the old code.CardModel.player_idquery field correct. Matches the existing pattern at line 1063-1064 in the pre-PR file.tier=tierin the cache-hit call is redundant but harmless. The outertier is Nonecondition guaranteestierisNoneat the call site, so the helper'stier is not Noneguard is always False there. Not a bug.Security
No issues found. All query fields (
player_id,variant,card_type,tier) are FastAPI-validated typed parameters — no raw user input in ORM queries.Style & Conventions
logging.info(...)now fires on every cache hit — including base card (variant=0) hits wherebackfill_scheduled=False. For a high-traffic endpoint, this could generate significant log volume. Consider downgrading tologging.debugor guarding:if backfill_scheduled: logging.info(...)._schedule_variant_image_backfilldiscarded in full-render path. Minor asymmetry with the cache-hit path, which capturesbackfill_scheduledfor logging. Not a bug — full-render path never logged this before.Suggestions
image_urlis already populated) is an extra round-trip per request. For popular variant cards that are fully backfilled, every cache hit now queries the DB to confirmimage_url is not None. A future optimization could pass theimage_urlvalue through to avoid the lookup entirely, but this is out of scope for a bug-fix PR.Verdict: COMMENT
Fix is correct, extraction is clean, and the five new tests cover all key scenarios (null backfill, populated no-op, missing row, variant=0, tier override). No blocking issues. Posted as COMMENT due to self-review restriction (PR author = reviewer).
Automated review by Claude PR Reviewer