Skip to content

Tag write-path correctness: regenerate-AI bypass, upsert race, trim, transactionality #349

Description

@joestump

Part of #303 (EPIC: Unified Tag Taxonomy Completion). Governing: ADR-0025, SPEC unified-tag-taxonomy REQs "Enricher Integration", "Tag Normalization", "Denormalized Entity Tags Table". Complements #309 (dual-write removal — this story must land first).

Requirements

  • Regenerate-AI bypass (review CONFIRMED + audit CRITICAL): all three regenerate handlers persist only the deprecated ai_tags JSON and discard data.TypedTags, never calling tags.UpsertTagsForEntity — regenerated tags are invisible to the taxonomy until the next background cycle (internal/handlers/tracks.go:343-375, albums.go:406-438, artists.go:548-585; metadata.go:741/1158/1453 shows the correct calls). Extract a shared persistence helper used by both paths
  • Upsert race (review CONFIRMED): query-then-create against the Tag unique index — concurrent enrichment goroutines make the loser's Create fail the whole upsert (internal/tags/upsert.go:40-57). Use dialect-appropriate conflict handling or a not-found→create→conflict→re-query retry
  • Trim stored display name per the normalization REQ (" shoegaze " → name "shoegaze"); currently stored verbatim (upsert.go:51) — audit WARNING
  • Same-transaction semantics: the Ent edge write and the raw entity_tags INSERT run on separate connections; a crash between them desyncs the stores, and no path deletes entity_tags rows on edge removal (upsert.go:63-81) — implement or explicitly amend the spec REQ (state which in the PR)

Acceptance Criteria

  • Regenerating AI tags from any show page immediately reflects in tag browsing/filtering
  • Concurrent upserts of the same (name, type, user) tag both succeed (race test)

Branch

feature/349-tag-write-path-correctness

PR Convention

PR title references the story; body ends with Closes #349, references the parent epic and governing artifacts above.

🤖 Posted on behalf of @joestump by Claude.

Metadata

Metadata

Assignees

No one assigned

    Labels

    backendGo backend codebugSomething isn't workingqueuedIssue is queued for workstoryStory issue

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions