↓Skip to main content
MusicVoting
  1. Technical Docs/

Datenbankschema

··447 words·3 mins·
Developer
Table of Contents

PostgreSQL 16. Das Schema wird beim ersten Start aus musicvoting/backend/setup.sql initialisiert (Hibernate generiert es nicht).

Tabellen
#

party
#

Eine Party (Top-Level-Aggregat).

SpalteTypHinweise
idVARCHAR PKParty-ID
provider_kindVARCHAR NOT NULLspotify / youtube
created_atTIMESTAMPTZDefault NOW()
pinVARCHAR(5)Gast-PIN
host_pinVARCHAR(5)Host-PIN
ended_atTIMESTAMPTZNULL = aktiv
currently_playing_entry_idUUID → queue_entry(id)aktueller Song; ON DELETE SET NULL
playback_started_atTIMESTAMPTZBasis für DB-berechneten Fortschritt
paused_position_msBIGINTPosition bei Pause
default_playlist_idVARCHARStandard-Playlist des Hosts für den Auto-Refill (NULL = keine)
spotify_refresh_tokenTEXTPersistierter Spotify-Refresh-Token – Host-Login übersteht Backend-Neustarts

queue_entry
#

Ein Song in der Warteschlange einer Party.

SpalteTypHinweise
idUUID PKDefault gen_random_uuid()
party_idVARCHAR → party(id)ON DELETE CASCADE
track_uriVARCHAR NOT NULLSpotify-URI
track_nameVARCHAR NOT NULL
artist_nameVARCHAR NOT NULL
album_nameVARCHAR
image_urlTEXTCover
duration_msINTEGER
added_atTIMESTAMPTZDefault NOW() – FIFO-Tiebreak
autofilledBOOLEAN NOT NULLDefault FALSE; TRUE = vom Auto-Refill eingefügt (sortiert unter Gast-Songs)
Note

Es gibt keinen Unique-Constraint auf (party_id, track_uri) mehr. Der gerade laufende Song darf erneut eingereiht werden, dieselbe URI kann also zweimal vorkommen (einmal spielend, einmal wartend). Duplikate unter den wartenden Einträgen verhindert das Backend in SpotifyMusicProvider#addTracksToPlaylist (HTTP 409, „Song ist schon in der Warteschlange.“).

vote
#

Ein Like eines Geräts für einen Queue-Eintrag.

SpalteTypHinweise
idUUID PK
queue_entry_idUUID → queue_entry(id)ON DELETE CASCADE
device_idVARCHAR NOT NULLanonyme Geräte-Identität
voted_atTIMESTAMPTZDefault NOW()
UNIQUE (queue_entry_id, device_id) → ein Like pro Gerät/Song

Beziehungen
#

PlantUML diagram
  • party → queue_entry: ON DELETE CASCADE (Party beenden leert die Queue).
  • queue_entry → vote: ON DELETE CASCADE.
  • party.currently_playing_entry_id → queue_entry: ON DELETE SET NULL (zirkuläre Referenz, wird in setup.sql per ALTER TABLE nach Anlegen von queue_entry ergänzt).

Eindeutige PINs nur für aktive Partys
#

CREATE UNIQUE INDEX party_pin_active_idx      ON party (pin)      WHERE ended_at IS NULL;
CREATE UNIQUE INDEX party_host_pin_active_idx ON party (host_pin) WHERE ended_at IS NULL;

Partielle Unique-Indizes: PINs müssen nur unter aktiven Partys eindeutig sein; eine beendete Party gibt ihren PIN-Slot wieder frei.

Sortierung der Queue
#

Nicht im Schema, sondern beim Lesen berechnet:

  1. der aktuell spielende Eintrag zuerst,
  2. Gast-Songs vor Auto-Refill-Songs (autofilled ASC),
  3. Likes desc,
  4. bei Gleichstand added_at aufsteigend (FIFO). Mit ?deviceId= liefert GET /track/queue zusätzlich hasVoted pro Eintrag.

Aufräum-Lebenszyklus
#

Über den PartyExpiryScheduler:

  • Auto-Ende nach 2 Tagen: Queue leeren, Access-Token im Speicher löschen, ended_at setzen, party-ended-Event.
  • Purge nach 1 Monat (ended_at): party-Zeile löschen → queue_entry/vote kaskadieren.
Warning

Beim Beenden wird spotify_refresh_token derzeit nicht geleert – er bleibt bis zum Purge in der party-Zeile. Laut provider/spec.md sollen beim Party-Ende alle Tokens gelöscht werden.

Schema in Produktion
#

In Kubernetes liegt das Schema nicht in setup.sql, sondern als Kopie in der ConfigMap in deployment/k8s/01-postgres.yaml. Bei jeder Schema-Änderung beide Dateien anpassen. Siehe CI/CD & Deployment.