Skip to content

fix: backfill a blank canonical image when reusing a canonical artist - #798

Open
sweetmantech wants to merge 2 commits into
mainfrom
feat/backfill-canonical-image
Open

fix: backfill a blank canonical image when reusing a canonical artist#798
sweetmantech wants to merge 2 commits into
mainfrom
feat/backfill-canonical-image

Conversation

@sweetmantech

@sweetmantechsweetmantech commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Row 4 of chat#1911: when resolveOrCreateArtist reuses a canonical artist that has no image, the roster card renders a grey placeholder. Seeding self-heals it ~30s later for new signups (verified live on Grace Ives in the chat#1889 arc), but accounts that already have a catalog never fire seeding — for them the blank is permanent. This backfills the blank at add-time.

Stacked on api#796 — it reuses enrichArtistSpotifyProfile from that PR, so this branch contains #796's commit until it merges. Merge order: api#796 → this.

What it does

In the canonical-reuse path of resolveOrCreateArtist: after linking, if account_info[0].image is blank, call enrichArtistSpotifyProfile (real Spotify avatar + handle + followers) and re-fetch the canonical so the add response itself carries the image — no interim grey window. A canonical with an image is left untouched (filling a blank is not the chat#1866 shared-write problem; overwriting would be). Best-effort: a Spotify outage returns the un-enriched canonical instead of failing the add.

Tests (TDD, red→green)

3 new cases in resolveOrCreateArtist.test.ts (enriches + re-fetches on blank; never touches a canonical with an image; returns the original when the backfill throws). Driving case confirmed RED first. Artists domain: 123 tests green; tsc --noEmit at the 236 pre-existing baseline; eslint clean.

Tracked in chat#1911 row 4.

🤖 Generated with Claude Code


Summary by cubic

Fixes grey placeholders when reusing a canonical artist by backfilling the Spotify avatar at add-time. Also enriches the create-time Spotify attach so verify-socials shows the real handle, followers, and avatar immediately (chat#1911 row 4; chat#1889 row 16).

  • Bug Fixes
    • In resolveOrCreateArtist, when reusing a canonical with no image, call enrichArtistSpotifyProfile and re-fetch the artist; skip if an image exists; never fail the add if Spotify is down.
    • After attaching Spotify on create, call enrichArtistSpotifyProfile to replace the path-based username with real profile data.
    • Added enrichArtistSpotifyProfile helper that fetches the Spotify artist and delegates to enrichSearchedArtistProfile; best-effort and non-throwing.

Written for commit 8d8949f. Summary will update on new commits.

Review in cubic

sweetmantechand others added 2 commits July 29, 2026 15:25
resolveOrCreateArtist's create path saved the URL path segment as the
username, so verify-socials rendered 'Spotify @artist · 0 followers'.
Fetch the real Spotify profile after the attach and reuse
enrichSearchedArtistProfile to write the real handle, follower count
and avatar. chat#1889 row 16.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A reused canonical with no image rendered a grey roster card - forever
for accounts that already have a catalog (no seeding fires), ~30s for
new signups. Enrich from the real Spotify profile at add-time, only
when the image is blank. chat#1911 row 4.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercelBot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
apiReadyReadyPreviewJul 29, 2026 11:07pm

Request Review

@cursor

cursorBot commented Jul 29, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@coderabbitai

Copy link
Copy Markdown

Warning

Review limit reached

@sweetmantech, you've reached your PR review limit, so we couldn't start this review.

Next review available in:18 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 10403352-2686-4680-8180-6db0bd59ee47

📥 Commits

Reviewing files that changed from the base of the PR and between 3bb0ca2 and 8d8949f.

⛔ Files ignored due to path filters (2)
  • lib/artists/__tests__/enrichArtistSpotifyProfile.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/artists/__tests__/resolveOrCreateArtist.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
📒 Files selected for processing (2)
  • lib/artists/enrichArtistSpotifyProfile.ts
  • lib/artists/resolveOrCreateArtist.ts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cubic-dev-aicubic-dev-aiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 4 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.
Architecture diagram
sequenceDiagram
participant Caller as resolveOrCreateArtist Caller
participant ROCA as resolveOrCreateArtist()
participant DB as Database
participant EASP as enrichArtistSpotifyProfile()
participant Spotify as Spotify API
Note over Caller,Spotify: Canonical Reuse Path
Caller->>ROCA: name, accountId, spotifyArtistId
ROCA->>DB: findCanonicalArtistBySpotifyId(spotifyArtistId)
DB-->>ROCA: canonicalId (e.g. "canonical-1")
ROCA->>DB: selectAccountArtistId(accountId, canonicalId)
alt Not already rostered
ROCA->>DB: insertAccountArtistId(accountId, canonicalId)
end
ROCA->>DB: selectAccountWithSocials(canonicalId)
DB-->>ROCA: artist with account_info
alt account_info[0].image is null/blank
Note over ROCA,Spotify: NEW: Backfill blank canonical image
ROCA->>EASP: enrichArtistSpotifyProfile(artistId, spotifyArtistId)
EASP->>Spotify: generateAccessToken()
Spotify-->>EASP: access_token
alt Token minted
EASP->>Spotify: getArtist(spotifyArtistId, token)
Spotify-->>EASP: spotifyArtist (name, followers, images)
alt Artist data returned
EASP->>DB: enrichSearchedArtistProfile(artistId, spotifyArtistId, spotifyArtist)
DB-->>EASP: Done
else No artist data
Note over EASP: Best-effort: skip
end
else Token minting failed
Note over EASP: Best-effort: skip
end
EASP-->>ROCA: void (best-effort, never throws)
ROCA->>DB: CHANGED: selectAccountWithSocials(canonicalId) (re-fetch)
DB-->>ROCA: healed artist (now with image)
else image exists or account_info empty
Note over ROCA: No enrichment (avoid shared-write)
end
ROCA-->>Caller: { artist: healedOrOriginal, created: false }
Note over Caller,Spotify: Create Path
Caller->>ROCA: name, accountId, spotifyArtistId
ROCA->>DB: createArtistInDb(...)
DB-->>ROCA: created artist (new id)
ROCA->>DB: insertAccountArtistId(accountId, newId)
ROCA->>DB: updateArtistSocials({ SPOTIFY: url })
DB-->>ROCA: social attached (path-based username)
ROCA->>EASP: NEW: enrichArtistSpotifyProfile(artistId, spotifyArtistId)
Note over EASP: Same flow as above — fetches real Spotify profile
EASP-->>ROCA: void
ROCA->>DB: selectAccountWithSocials(newId)
DB-->>ROCA: artist with enriched social
ROCA-->>Caller: { artist, created: true }
Loading

Auto-approved: Backfills blank canonical image and enriches create-time profile with real Spotify data, both best-effort and bounded. Tests confirm no overwrite of existing images and safe failure on Spotify outage.

Re-trigger cubic

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@sweetmantech