Files
Alexander a1f6701bac feat: initial implementation of metadata aggregator
- gRPC service with MusicBrainz provider
- PostgreSQL schema with migrations
- Service layer with database-first caching
- Repository pattern for data access
- YAML configuration support
- Research documentation for 17 music metadata projects
2026-04-28 16:28:53 +02:00

277 lines
7.2 KiB
Plaintext

@startuml Music Metadata ERD
skinparam linetype ortho
skinparam ranksep 50
skinparam nodesep 30
skinparam entity {
BackgroundColor White
BorderColor #333333
}
skinparam package {
BackgroundColor #FAFAFA
BorderColor #DDDDDD
}
title Music Metadata Aggregator - Internal Structure
' ══════════════════════════════════════════════════════════════
' CORE MUSIC ENTITIES
' ══════════════════════════════════════════════════════════════
package "Core Entities" #E3F2FD {
entity "artists" {
* id : UUID <<PK>>
--
name : TEXT
sort_name : TEXT
artist_type : TEXT
country : TEXT
formed_date : DATE
disbanded_date : DATE
description : TEXT
image_url : TEXT
--
source : TEXT
source_id : TEXT
created_at : TIMESTAMPTZ
updated_at : TIMESTAMPTZ
}
entity "works" {
* id : UUID <<PK>>
--
title : TEXT
work_type : TEXT
language : TEXT
--
source : TEXT
source_id : TEXT
created_at : TIMESTAMPTZ
updated_at : TIMESTAMPTZ
}
entity "tracks" {
* id : UUID <<PK>>
--
work_id : UUID <<FK>>
--
title : TEXT
duration_ms : INT
isrc : TEXT
explicit : BOOLEAN
--
source : TEXT
source_id : TEXT
created_at : TIMESTAMPTZ
updated_at : TIMESTAMPTZ
}
entity "albums" {
* id : UUID <<PK>>
--
label_id : UUID <<FK>>
--
title : TEXT
album_type : TEXT
release_date : DATE
upc : TEXT
total_tracks : INT
total_discs : INT
cover_url : TEXT
--
source : TEXT
source_id : TEXT
created_at : TIMESTAMPTZ
updated_at : TIMESTAMPTZ
}
entity "labels" {
* id : UUID <<PK>>
--
name : TEXT
country : TEXT
founded_date : DATE
--
source : TEXT
source_id : TEXT
created_at : TIMESTAMPTZ
updated_at : TIMESTAMPTZ
}
entity "genres" {
* id : UUID <<PK>>
--
name : TEXT
parent_id : UUID <<FK>>
}
}
' ══════════════════════════════════════════════════════════════
' RELATIONSHIPS
' ══════════════════════════════════════════════════════════════
package "Relationships" #FFF3E0 {
entity "track_artists" {
* track_id : UUID <<FK>>
* artist_id : UUID <<FK>>
--
role : TEXT
position : INT
}
entity "album_artists" {
* album_id : UUID <<FK>>
* artist_id : UUID <<FK>>
--
role : TEXT
position : INT
}
entity "album_tracks" {
* album_id : UUID <<FK>>
* track_id : UUID <<FK>>
--
disc_number : INT
track_number : INT
}
entity "work_artists" {
* work_id : UUID <<FK>>
* artist_id : UUID <<FK>>
--
role : TEXT
}
entity "artist_genres" {
* artist_id : UUID <<FK>>
* genre_id : UUID <<FK>>
}
entity "album_genres" {
* album_id : UUID <<FK>>
* genre_id : UUID <<FK>>
}
entity "similar_artists" {
* artist_id : UUID <<FK>>
* similar_artist_id : UUID <<FK>>
--
score : REAL
}
}
' ══════════════════════════════════════════════════════════════
' CONTENT
' ══════════════════════════════════════════════════════════════
package "Content" #E8F5E9 {
entity "lyrics" {
* id : UUID <<PK>>
--
track_id : UUID <<FK>>
--
content : TEXT
synced_content : JSONB
language : TEXT
--
source : TEXT
source_id : TEXT
created_at : TIMESTAMPTZ
}
entity "playlists" {
* id : UUID <<PK>>
--
name : TEXT
description : TEXT
is_public : BOOLEAN
cover_url : TEXT
--
created_at : TIMESTAMPTZ
updated_at : TIMESTAMPTZ
}
entity "playlist_tracks" {
* playlist_id : UUID <<FK>>
* track_id : UUID <<FK>>
--
position : INT
added_at : TIMESTAMPTZ
}
}
' ══════════════════════════════════════════════════════════════
' EXTERNAL IDS (Cross-platform linking)
' ══════════════════════════════════════════════════════════════
package "External IDs" #FCE4EC {
entity "artist_external_ids" {
* artist_id : UUID <<FK>>
* source : TEXT
* source_id : TEXT
--
url : TEXT
fetched_at : TIMESTAMPTZ
}
entity "album_external_ids" {
* album_id : UUID <<FK>>
* source : TEXT
* source_id : TEXT
--
url : TEXT
fetched_at : TIMESTAMPTZ
}
entity "track_external_ids" {
* track_id : UUID <<FK>>
* source : TEXT
* source_id : TEXT
--
url : TEXT
fetched_at : TIMESTAMPTZ
}
}
' ══════════════════════════════════════════════════════════════
' RELATIONSHIPS DIAGRAM
' ══════════════════════════════════════════════════════════════
' Core relationships
works ||--o{ tracks : "recorded as"
albums ||--o{ album_tracks : "contains"
tracks ||--o{ album_tracks : "appears on"
labels ||--o{ albums : "released by"
genres ||--o{ genres : "parent"
' Artist relationships
artists ||--o{ track_artists : ""
tracks ||--o{ track_artists : ""
artists ||--o{ album_artists : ""
albums ||--o{ album_artists : ""
artists ||--o{ work_artists : ""
works ||--o{ work_artists : ""
' Genre relationships
artists ||--o{ artist_genres : ""
genres ||--o{ artist_genres : ""
albums ||--o{ album_genres : ""
genres ||--o{ album_genres : ""
' Similar artists
artists ||--o{ similar_artists : ""
' Content
tracks ||--o| lyrics : "has"
playlists ||--o{ playlist_tracks : ""
tracks ||--o{ playlist_tracks : ""
' External IDs
artists ||--o{ artist_external_ids : ""
albums ||--o{ album_external_ids : ""
tracks ||--o{ track_external_ids : ""
@enduml