Skip to content

Silly joliot: Ny Quarkus backend utifrån Go-backend - #1

Open
joelbinn wants to merge 15 commits into
mainfrom
silly-joliot
Open

Silly joliot: Ny Quarkus backend utifrån Go-backend#1
joelbinn wants to merge 15 commits into
mainfrom
silly-joliot

Conversation

@joelbinn

Copy link
Copy Markdown
Contributor

No description provided.

joelbinn and others added 15 commits January 9, 2026 19:04
Implementerar en fullständig testsvit i Quarkus som testar den
existerande Go-backenden. Detta är första fasen av TDD-konvertering
där testerna fungerar som "characterization tests" som dokumenterar
nuvarande beteende.

Teststruktur (49 tester totalt):
- ContestantApiTest (9 tester): CRUD-operationer för contestants
- QueueApiTest (6 tester): Köhantering och filtrering
- GameApiTest (10 tester): Spellivscykel (start, finish, abort)
- LeaderboardApiTest (7 tester): Ledartavla med sortering och uppdateringar
- FullGameFlowIntegrationTest (11 tester): Komplett spelflöde
- WebSocketApiTest (6 tester): WebSocket-notifieringar

Teknisk implementation:
- Java 25 med Records för immutable DTOs
- RestAssured för REST API-testning
- Jakarta WebSocket Client för WebSocket-testning
- MongoDB direktanslutning (localhost:27017)
- JUnit 5 med @QuarkusTest
- AssertJ för fluent assertions

Dokumenterade Go-backend buggar att fixa i Quarkus:
1. GET /contestants returnerar 400 när tom (ska returnera 200 + tom array)
2. DELETE /queue/{timestamp} returnerar 200 för icke-existerande post (ska vara 404)
3. Contestant.name kan vara tom sträng i leaderboard efter deletion

Test-basklasser:
- GoBackendTestBase: Rensar databas mellan varje test
- IntegrationTestBase: Rensar endast före hela testsviten (för ordered tests)

Alla 49 tester är gröna mot Go-backend.
Nästa steg: Implementera Quarkus-backend med samma tester.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Skapar två centrala dokument för migrering Go → Quarkus:

MIGRATION-TO-QUARKUS.PLAN.md:
- Komplett arkitekturplan med Hexagonal Architecture
- Implementation-ordning enligt TDD
- Designprinciper (DDD, SOLID, funktionell stil)
- Dokumenterade Go-backend buggar att fixa
- Teknisk stack och viktiga beslut
- Milstolpar och checkpoint-strategi

MIGRATION-TO-QUARKUS.TODO.md:
- Detaljerad checklist för alla 11 faser
- 76 specifika uppgifter med numrering
- Progress tracking per fas
- Tydliga checkpoints och milstolpar
- Nästa uppgift markerad: Börja med Contestant entity

Fas 1 (testsvit) är komplett med alla 49 tester gröna.
Fas 2-11 är planerade och redo att implementeras enligt TDD.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Skapar omfattande funktionell dokumentation med:

**1. Domänmodell (PlantUML Klassdiagram)**
- Entities: Contestant, QueueItem, LeaderboardEntry
- Value Objects: GameResult, GameState
- Domain Services: GameService, LeaderboardService
- Repository Ports: ContestantRepository, QueueRepository, LeaderboardRepository
- Notification Port: NotificationService
- Kardinalitet och relationer dokumenterade

**2. Use Cases (7 st) med sekvensdiagram:**
- UC1: Lägg till Contestant
- UC2: Lägg till i Kö
- UC3: Starta Spel
- UC4: Avsluta Spel
- UC5: Avbryt Spel
- UC6: Hämta Ledartavla
- UC7: Ta bort Contestant

Varje use case innehåller:
- Pre-/Post-conditions
- PlantUML sekvensdiagram
- State transition diagram

**3. State Machines (PlantUML)**
- Complete Game Flow State Machine
- Contestant Lifecycle
- Queue State Transitions
- Game State Transitions
- Leaderboard Update Decision Flow

**4. WebSocket Notifications**
- Notification flow diagram
- Notification types dokumenterade
- Broadcast-mekanism beskriven

**5. Business Rules**
- 9 valideringsregler med konsekvenser
- Ledartavla-regler med beslutflöde
- Kö-regler (FIFO)

**6. Data Invariants**
- 7 system invariants som alltid måste hålla
- Invariant verification flow

**7. Concurrency & Error Handling**
- Race condition-hantering
- Locking strategy diagram
- HTTP status codes
- Error response format

**8. Migreringsnoteringar**
- Dokumenterade Go-buggar att fixa
- Funktionella förbättringar i Quarkus

Alla diagram är i PlantUML-format och kan renderas till
bilder för enkel visualisering.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implementerar första delarna av domänmodellen enligt Hexagonal Architecture:

**Contestant Entity** (16 unit tests - alla gröna):
- Unik identitet via email
- Immutable class med final fields
- Identity equality (baserat på email)
- Validering: email och name inte null/blank
- withName() method för att skapa uppdaterade instanser
- Fullt testade inkl edge cases

**GameResult Value Object** (18 unit tests - alla gröna):
- Java Record för maximal immutability
- splitTime och endTime med validering
- Business rule: endTime >= splitTime
- isFasterThan() för jämförelse
- getSecondHalfTime() utility method
- Value equality (baserat på attribut)
- Floating point assertions med offset

**QueueItem Entity** (6 unit tests - alla gröna):
- Unik identitet via timestamp
- Immutable med final fields
- Factory method now() för current timestamp
- isOlderThan() för FIFO-sortering
- Identity equality (baserat på timestamp)

**Designprinciper tillämpade:**
- Domain-Driven Design (Entities vs Value Objects)
- Immutability (alla fields final)
- Self-validating domain objects
- Clear separation of identity vs value equality
- Defensive programming med null-checks

**Test-coverage:**
- 40 unit tests totalt
- Alla gröna
- Testar business rules, edge cases, exceptions

Nästa steg: LeaderboardEntry, GameState och Domain Events.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implementerar kompletta domänmodellen med entities och value objects:

**LeaderboardEntry Entity** (13 unit tests):
- Identity via contestant email
- Immutable med final fields
- withResult() för uppdatering (ny instans)
- shouldUpdateWith() för att avgöra om nytt resultat är bättre
- Utility methods: getContestantEmail(), getEndTime()
- Identity equality baserat på contestant

**GameState Value Object** (12 unit tests):
- Java Record med två states: IDLE och IN_PROGRESS
- Factory methods: idle() och inProgress(contestant)
- Business rule validation i compact constructor
- IDLE får inte ha contestant
- IN_PROGRESS måste ha contestant
- Utility methods: isIdle(), isInProgress(), isPlayingContestant()

**Uppdaterad QueueItem**:
- Kompletterade unit tests (total 6 tester)

**Statistik Fas 2:**
- ✅ 5/5 domänmodell-komponenter klara (100%)
- ✅ 65 unit tests totalt - alla gröna
- ✅ 3 Entities: Contestant, QueueItem, LeaderboardEntry
- ✅ 2 Value Objects: GameResult, GameState

**Designprinciper tillämpade:**
- Domain-Driven Design (Entity vs Value Object distinction)
- Immutability (final fields, Records)
- Factory methods för value objects
- Self-validating domain objects
- Business rules enforced i konstruktorer
- Identity vs value equality korrekt implementerat

**Nästa steg:**
- Domain Events (GameStarted, GameFinished, GameAborted)
- Repository Ports (interfaces)
- Domain Services (GameService, LeaderboardService)

Fas 2 (Domänmodell) är nu 100% komplett!

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implementerar domain ports (Hexagonal Architecture) och domain events:

**Repository Ports (4 interfaces):**

1. **ContestantRepository**
   - findAll(), findEnqueued(), findNotEnqueued()
   - findByEmail(), save(), delete(), exists()
   - Collection-like interface för Contestant aggregate

2. **QueueRepository**
   - findAll(), findFirst(), findByTimestamp()
   - save(), delete(), deleteAll()
   - isEmpty(), count()
   - FIFO-semantik garanterad

3. **LeaderboardRepository**
   - findAllSortedByEndTime(), findTopN()
   - findByEmail(), save(), delete()
   - exists(), count()
   - Sorterad efter endTime (bäst först)

4. **NotificationService**
   - notifyGameStarted(), notifyGameFinished(), notifyGameAborted()
   - getConnectedClientsCount()
   - Abstraherar WebSocket-implementation

**Domain Events (3 Records):**

1. **GameStartedEvent** - Emitteras när spel startas
   - contestant, timestamp
   - Factory method: now(contestant)

2. **GameFinishedEvent** - Emitteras när spel avslutas
   - result, timestamp
   - Factory method: now(result)

3. **GameAbortedEvent** - Emitteras när spel avbryts
   - timestamp
   - Factory method: now()

**Hexagonal Architecture Principer:**
- Ports definierade i domain-lagret
- Inga dependencies på infrastructure
- Collection-like repository interfaces
- Clear separation of concerns
- Domain language i method names

**Design Decisions:**
- Repository per Aggregate Root
- Business rules dokumenterade i Javadoc
- Optional<T> för safe lookups
- Event names i past tense (händelser)
- Factory methods för convenient event creation

**Nästa steg:**
- MongoDB infrastructure (entities, repositories, mappers)
- Domain Services (GameService, LeaderboardService)
- Application Services (use case orchestration)

Fas 3 (Ports & Events) komplett!

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Skapat:
- 3 Panache entities (ContestantEntity, QueueItemEntity, LeaderboardEntryEntity)
- 3 mappers för domain <-> entity konvertering
- 3 repository implementations med composition pattern

Design decisions:
- Använder composition istället för direkt implements för att undvika
  method name collision mellan domain port och Panache methods
- Inre @ApplicationScoped classes för Panache repository operations
- Denormaliserad data i entities för query performance
- MongoDB client injection för cross-collection queries

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Skapat:
- GameService: Hanterar spellogik (start/finish/abort)
- LeaderboardService: Hanterar ledartavlelogik och uppdateringar

GameService:
- Validerar business rules för game state transitions
- Emitterar domain events (GameStartedEvent, GameFinishedEvent, GameAbortedEvent)
- Skickar notifieringar via NotificationService port
- Returnerar result records med nytt state och event

LeaderboardService:
- Avgör om resultat ska uppdatera ledartavlan (BR-LB1: endast bättre resultat)
- Hanterar både nya entries (ADD) och uppdateringar (UPDATE)
- Pure functions - stateless design
- UpdateDecision record med action och entry info

Design principles:
- Stateless domain services
- Business logic i domain layer (inte application layer)
- Side effects (notifications) explicit via dependency injection
- Immutable return types (records)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Skapat:
- GameApplicationService: Orchestrerar spelflöde (start/finish/abort)
- ContestantApplicationService: Hanterar contestants (create/find/delete)
- QueueApplicationService: Hanterar kön (find/delete)
- LeaderboardApplicationService: Hanterar ledartavla (find/query)

GameApplicationService:
- Håller game state i minnet (singleton @ApplicationScoped)
- Koordinerar mellan repositories och domain services
- Transaktionell hantering per use case
- UC-GS1: Start game (poppa från kö, starta spel)
- UC-GF1: Finish game (avsluta, uppdatera ledartavla)
- UC-GA1: Abort game (avbryt utan resultat)

ContestantApplicationService:
- UC-CC1: Create + enqueue (atomiskt i samma transaktion)
- UC-CF1-4: Find (ALL/ENQUEUED/NOT_ENQUEUED/by email)
- UC-CD1: Delete + dequeue (atomiskt)

QueueApplicationService:
- UC-QF1-2: Find all/first (FIFO-ordning)
- UC-QD1: Delete by timestamp

LeaderboardApplicationService:
- UC-LF1-3: Find all/top-N/by email
- Sorterad efter endTime (bäst först)

Design principles:
- Thin application layer - delegerar till domain layer
- @transactional per use case
- Koordinerar repositories och domain services
- Ingen business logic (finns i domain layer)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Markerat följande faser som kompletta:
- ✅ Fas 4: MongoDB Infrastructure (entities, mappers, repositories)
- ✅ Fas 5: Domain Services (GameService, LeaderboardService)
- ✅ Fas 6: Application Services (4 application services med use case orchestration)

Progress: 6/11 faser klara (55%)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Skapat:
- DTOs: Flyttat från test till main (ContestantDTO, QueueItemDTO, GameResultDTO, LeaderboardEntryDTO)
- DTOMapper: Utility för domain ↔ DTO konvertering
- 4 REST Resources med JAX-RS
- InMemoryNotificationService: Stub implementation (ersätts i Fas 8)
- DomainServiceProducer: CDI producer för domain services

REST Resources:
- ContestantResource: GET/POST/DELETE /contestants
  - GET med filter support (ALL/ENQUEUED/NOT_ENQUEUED)
  - POST skapar + enqueues atomiskt, returnerar QueueItemDTO
  - DELETE tar bort contestant + dequeue
  - Go-quirk: 400 Bad Request vid tom lista

- QueueResource: GET/DELETE /queue
  - GET returnerar FIFO-sorterad kö
  - DELETE by timestamp, 404 om inte hittat

- GameResource: POST /game-start, /game-finish, /game-abort
  - game-start: Poppar från kö, returnerar ContestantDTO
  - game-finish: Tar GameResultDTO, uppdaterar ledartavla
  - game-abort: Avbryter utan resultat
  - 400/500 statuskoder enligt Go-behavior

- LeaderboardResource: GET /leaderboard
  - Optional limit query parameter för top-N
  - Sorterad efter endTime (bäst först)

Design decisions:
- Thin presentation layer - delegerar till application services
- DTOMapper för separation mellan layers
- Go-backend compatibility (400 för tom lista, etc.)
- InMemoryNotificationService som temporary stub

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Markerat Fas 7: REST Resources som implementation complete
- ✅ 4 REST Resources implementerade (Contestant, Queue, Game, Leaderboard)
- ✅ DTOs, DTOMapper, InMemoryNotificationService, DomainServiceProducer

Nästa steg: Köra tester och fixa buggar (7.1.2-7.4.3)
Därefter: Fas 8 WebSocket implementation

Progress: 7/11 faser med implementation klar (64%)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Ändrat:
- maven.compiler.source/target: 25 → 21
- Tagit bort --enable-preview flag (inte nödvändig för Java 21)

Motivation:
Quarkus 3.17.7 använder ASM som inte stödjer Java 25 class file version.
Java 21 är LTS och fullt stödd av Quarkus 3.17.7.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fas 8 - WebSocket Implementation (KOMPLETT):
- Implementerat WebSocketNotificationService (@ApplicationScoped CDI bean)
- Skapat GameNotificationWebSocket endpoint (@serverendpoint("/api/v1/ws"))
- Session management med ConcurrentHashMap för thread-safety
- Broadcast notifications till alla anslutna WebSocket-klienter
- Fixat CDI integration (använd CDI.current() i WebSocket endpoint)
- Skapat RestApplication.java för JAX-RS routing (@ApplicationPath("/api/v1"))
- Kommenterat bort @transactional (kräver MongoDB replica set)
- Fixat Jackson serialization (removed isXxx() methods från GameNotificationDTO)
- Fixat database name mismatch i MongoContestantRepository (använd @ConfigProperty)
- Uppdaterat WebSocketApiTest för Quarkus-backend (port 8081, foildb-test)
- Alla 6 WebSocket-tester gröna ✅

Fas 9 - Integration Test (PÅGÅR):
- Uppdaterat IntegrationTestBase till Quarkus-backend (port 8081, foildb-test)
- Uppdaterat GoBackendTestBase till Quarkus-backend (port 8081, foildb-test)
- Injicerar GameApplicationService för game state reset i basklasser
- Uppdaterat FullGameFlowIntegrationTest med state reset
- Fixat GameResource.finishGame() för Go-kompatibilitet:
  * Returnerar nu hela leaderboard-arrayen istället för bara 200 OK
  * Injicerar LeaderboardApplicationService
  * Anropar leaderboardService.findAll() efter finish
- Uppdaterat MIGRATION-TO-QUARKUS.TODO.md med progress
- Status: 38/49 tester verifierade (integration test kvarstår)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Sign up for free to 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