Silly joliot: Ny Quarkus backend utifrån Go-backend - #1
Open
joelbinn wants to merge 15 commits into
Open
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.