↓Skip to main content
MusicVoting
  1. Technical Docs/

Architektur

··356 words·2 mins·
Developer
Table of Contents

Überblick
#

MusicVoting besteht aus einem Quarkus-Backend, einem Angular-Frontend (mit drei Rollen-Ansichten), einer PostgreSQL-Datenbank und einer optionalen SwiftUI-iOS-App. Die Musik wird über den Spotify Web Playback SDK im Browser des Monitors/TVs abgespielt.

PlantUML diagram

Komponenten
#

KomponenteTechnologieAufgabe
BackendQuarkus (Java 21), JAX-RS, SSEAPI, Party-Lebenszyklus, Provider-Anbindung
FrontendAngularGuest-, Host- und TV-Ansichten
DatenbankPostgreSQL 16, Hibernate ORM PanachePersistenz von Party, Queue, Votes
MobileSwiftUI (iOS)Native Guest- und Admin-Ansicht (optional)
ProviderSpotify Web API + Web Playback SDKSuche und Wiedergabe

Wichtige Architekturentscheidungen
#

  • DB ist die Quelle der Wahrheit. Queue, aktueller Track und Fortschritt kommen aus der Datenbank, nicht aus Spotify. GET /track/current ruft die Spotify-„currently-playing“-API nicht auf (siehe Datenbankschema und die Playback-Spec).
  • Party vs. PartyEntity. Party ist die In-Memory-Repräsentation in der PartyRegistry, PartyEntity die Panache-Entity der DB-Tabelle party. Sie sind bewusst getrennt und werden nicht zusammengeführt.
  • Restart-fest. Endpunkte lösen eine Party bei Bedarf aus der DB auf, wenn sie nicht in der In-Memory-Registry liegt – ein Backend-Neustart führt nicht zu 404. Auch der Spotify-Login überlebt, weil der Refresh-Token in der DB liegt.
  • Ein Provider pro Party. Über ProviderKind (Spotify implementiert, YouTube vorgesehen), abstrahiert durch das MusicProvider-Interface und die MusicProviderFactory.
  • Live-Updates über SSE, nicht über Polling (siehe Realtime / SSE).
  • Die Musik geht nie aus. Würde die Queue leer, füllt das Backend automatisch einen Song nach (Standard-Playlist → ähnliche Songs → Top-Charts → Suche). Gast-Songs haben immer Vorrang.
  • Der Player treibt das Autoplay. Nur die Startpage kennt das echte Songende (Web Playback SDK) und ruft /track/next auf – über drei unabhängige Erkennungswege, pro Song genau einmal.

Datenfluss (Beispiel: Gast fügt einen Song hinzu)
#

  1. Gast sucht (GET /api/party/{id}/track/search?q=…) → Spotify-Treffer.
  2. Gast tippt „+“ → POST /api/party/{id}/track/addToPlaylist.
  3. Backend schreibt eine queue_entry-Zeile und sendet ein queue-updated-SSE-Event.
  4. Alle verbundenen Clients (TV, Host, andere Gäste) laden die Queue neu.

Hintergrundprozesse
#

  • PartyExpiryScheduler beendet Partys automatisch nach 2 Tagen und löscht beendete Partys 1 Monat nach endedAt (siehe Datenbankschema).

Betriebsvarianten
#

VarianteWoBeschreibung
KubernetesHTL-ClusterProduktiv, per GitHub Actions (siehe CI/CD)
deployment/server/eigener ServerDocker Compose + Caddy (HTTPS via Let’s Encrypt)
deployment/compose/lokalfertige GHCR-Images + PostgreSQL
Quellcodelokalquarkus:dev + npm start + DB aus musicvoting/docker-compose.yaml