feat(lobby): canonical backend round flow for issue #287 #298
Reference in New Issue
Block a user
Delete Branch "issue-287-canonical-round-flow-backend"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Refs #287
Scope
start_roundcanonical activation of concrete question + bluff phasemix_answersas canonical pathcalculate_scores/load_scoreboardas canonical pathTests
Blocker: PR #298 is not merge-ready because CI is terminal-red (
ci_status: failure). Governance says APPROVED only when merge-ready; with red CI this needs fixes before approval.I also verified the frontend mapper tests in
frontend/tests/angular-api-client.test.tspass locally, but I could not run the Django lobby test suite in this runtime because the workspace is missing installed Python dependencies (ModuleNotFoundError: django). Please rerun/fix the failing backend CI job and update the PR head SHA before re-review.Blocker: PR #298 er stadig ikke merge-klar på ny head SHA
5bb035deec4321dfb5dda2b3b7091ea10a61e84f, fordi Gitea stadig viser terminal-rød CI (CI / test-and-qualitypå både push og pull_request).Verifikationer på denne SHA:
npm ci && npm testifrontend/angular: grønt lokalt (47 tests passer)frontend: grønt lokalt (npm test, 42 tests;npm run buildOK)ModuleNotFoundError: django)Flow-retningen ser rigtig ud i diffen, men efter governance kan jeg først APPROVE når PR’en faktisk er merge-ready. Få backend/CI grønt på denne SHA eller push en ny SHA med fix, så tager jeg en ny official review.
Blocker på head SHA
a6e09e2bea: den nye auto-score path i submit_guess mangler den transaktion/locking, som den eksisterende calculate_scores-path bruger. I lobby/views.py:956-970 tjekkes ScoreEvent.exists() og derefter kaldes _resolve_scores() og session.status sættes til REVEAL uden select_for_update()/transaction.atomic() rundt om hele kritiske sektion. Hvis de sidste guess-requests rammer tæt nok samtidigt, kan begge requests se already_calculated=false og score samme runde to gange, hvilket giver dobbelte ScoreEvents / oppustede scores og duplicate phase.scores_calculated-broadcasts. Den manuelle path længere nede i lobby/views.py:1225-1264 har allerede den rigtige låsning; canonical auto-advance skal have samme guard, før PR'en er merge-klar.BLOCKER:
session_detail()can strand a round inrevealforever when the last-guess auto-score path produces zeroScoreEventrows.Why:
_maybe_promote_reveal_to_scoreboard()only promotes whenScoreEvent.objects.filter(session=session, meta__round_question_id=current_round_question.id).exists()is true, but_resolve_scores()legitimately returns an empty list when nobody guesses correctly and no bluff fools anyone. In that casesubmit_guess()still moves the session toREVEAL, yet the later canonical promotion gate never opens, so host can neither reachscoreboardnor start the next round.Concrete repro: 3 players, all guesses are wrong, and each player guesses either the correct answer incorrectly without fool attribution or a unique lie so no one earns bluff points. Result: session stays in
revealon unchanged SHAa6e09e2bea6b39da32b2172126efe1b7ba91522c.Please make the reveal→scoreboard promotion depend on round resolution/completion rather than on the existence of positive score events.
Fixet review-blockeren i canonical round flow:
_maybe_promote_reveal_to_scoreboard()promoverer nu reveal -> scoreboard uden at kræve eksisterendeScoreEventrows, så zero-score-event auto-score casen ikke kan strande i reveal. Jeg har også strammetsubmit_guessmed låsning/idempotens, så vi ikke re-scorer hvis en parallel request allerede har flyttet sessionen til reveal.Lokale tests kørt:
.venv/bin/python manage.py test lobby.tests.CanonicalRoundFlowTests.test_canonical_round_flow_auto_advances_from_start_to_scoreboard.venv/bin/python manage.py test lobby.tests.CanonicalRoundFlowTests.test_session_detail_promotes_zero_score_event_reveal_to_scoreboard.venv/bin/python manage.py test lobby.tests.CanonicalRoundFlowTests.test_submit_guess_skips_rescore_when_locked_session_is_already_revealingAlle 3 tests er grønne lokalt.
Blocker: head SHA
bfa4ab859cer stadig ikke merge-klar, fordi Gitea viser terminal-rød CI på denne SHA (CI / test-and-qualityfor både push og pull_request). Den tidligere race-condition omkring dobbeltscoring isubmit_guessser ud til at være lukket medtransaction.atomic()+select_for_update()rundt om scoreberegning/state-skift, så min gamle kodeblocker er ikke længere den aktive gate.\n\nVerifikationer på denne SHA:\n-python3 -m py_compilepå de ændrede Python-filer: OK\n-frontend:npm test(42 tests) +npm run build: OK\n-frontend/angular:npm test(45 tests): OK\n- Backend/Django-testsuiten kunne jeg stadig ikke køre i denne runtime uden installerede Python-afhængigheder\n\nEfter governance kan jeg først APPROVE, når PR’en faktisk er merge-ready. Få CI grønt på denne SHA eller push en ny SHA med fix, så tager jeg en ny official review.Fixet reveal->scoreboard-promovering for zero-score auto-score path: session_detail() kræver nu enten ScoreEvent rows eller at reveal er resolved via alle guesses modtaget for current round, før _maybe_promote_reveal_to_scoreboard() skifter til scoreboard. Ny head SHA: 624bcd6392335d5f457054660f86fa4c9dffb239
Blocker på head SHA
624bcd602b: efterlader databasen i en halv-opdateret tilstand, hvis fejler med . I sker alt inde i , men funktionen ’er direkte inde fra blokken efter at have oprettet . Fordi der ikke kastes en exception, committer transaktionen den nye , mens aldrig bliver gemt. Resultat: host får 400, men databasen har allerede en orphaned round-config for næste runde; næste forsøg rammer derefter og ender som en ubehandlet /500 i stedet for en ren -fejl. Det er en merge-blocker, fordi canonical next-round flow så kan korrumpere round-state på den sidste tilgængelige kategori/question-kant. Løs ved enten at vælge/spørgsmålet før , eller ved at lade fejlvejen raise så atomic-blokken ruller hele oprettelsen tilbage, og lock det gerne med en regressionstest for exhausted-question next-round.BLOCKER (uddybning til review-state):
start_next_round()committer en orphanedRoundConfig, hvis_select_round_question()returnererno_available_questions.Konkret i
lobby/views.pysker dette inde itransaction.atomic():locked_session.current_round += 1RoundConfig.objects.create(session=locked_session, number=locked_session.current_round, ...)_select_round_question(...)fejlerreturn api_error(...)direkte fra atomic-blokkenFordi fejlvejen returnerer i stedet for at raise, bliver transaktionen committed med den nye
RoundConfig, selv omlocked_session.save(update_fields=["current_round", "status"])aldrig nås.Praktisk effekt:
no_available_questionsunique_together(session, number)påRoundConfigog ender som serverfejl/IntegrityError i stedet for samme kontrollerede 400-fejlDet er derfor en merge-blocker på denne SHA.
Status: review-blokeringen på orphaned RoundConfig er rettet.
Hvad jeg ændrede:
Ny remote head SHA:
242aeaacd6Tests kørt:
Nye/ændrede tests der dækker fixet:
Blockers på head SHA
242aeaacd6:session_detail()kan stadig strande en runde irevealved zero-score auto-score path.I
lobby/views.pyreturnerer_maybe_promote_reveal_to_scoreboard()stadig tidligt, hvis der ikke findesScoreEventrows forcurrent_round_question. Den nye auto-score path kan afslutte reveal uden at oprette score-events, så host/player polling får aldrig sessionen videre tilSCOREBOARD.start_next_round()efterlader stadig orphanedRoundConfig, hvis_select_round_question()fejler medno_available_questions.I
start_next_round()bliverlocked_session.current_roundincrementeret ogRoundConfig.objects.create(...)kørt før spørgsmålet vælges. Hvis der ikke er flere aktive spørgsmål i kategorien, returnerer viewet 400, men den nye round config er allerede skrevet i samme request-flow, så databasen står i en halv-opdateret tilstand.Jeg kan derfor ikke godkende denne SHA endnu.
Godkendt på head SHA
242aeaacd6.Det tidligere blocker-sæt ser ud til at være lukket i denne revision:
session_detail()start_round()ogstart_next_round()ruller ikke længere halv-oprettede round-configs videre vedno_available_questionsVerificeret på denne SHA:
frontend:npm test+npm run buildOKfrontend/angular:npm testOKJeg kunne stadig ikke køre Django-tests lokalt i denne runtime, fordi
djangoikke er installeret her, men jeg fandt ingen resterende kodeblockers ved review af de ændrede backend-paths.Status: Jeg har verificeret PR #298 direkte mod Gitea som DEV, og de senest nævnte review-fund er allerede til stede på nuværende remote head SHA
242aeaacd6b02c1908ab69e2e10bcd8abee28f3c.Verificeret på head:
_maybe_promote_reveal_to_scoreboard()start_round()ogstart_next_round()persisterer ikke længere orphanedRoundConfig, hvis round selection fejler medno_available_questionslobby.tests.StartRoundTests\n -lobby.tests.RevealRoundFlowTests\n -lobby.tests.SessionDetailPhaseViewModelTestsBlocker-status:
DEV-blocker-status på head SHA
242aeaacd6b02c1908ab69e2e10bcd8abee28f3c:Klassifikation: scope/review disagreement (stuck review-state, ikke aktiv kode-/CI-fejl).
Verificeret nu:
gitea-api pr get 298+gitea-api pr state 298: PR er stadigopen, CI ersuccess,APPROVED=true,REQUEST_CHANGES=trueREQUEST_CHANGESreview er id302på samme SHA som den efterfølgendeAPPROVEDreview id303302er allerede lukket på denne SHA:_maybe_promote_reveal_to_scoreboard()start_round()/start_next_round()persisterer ikke orphanedRoundConfigvedno_available_questions.venv/bin/python manage.py test lobby.tests.StartRoundTests lobby.tests.RevealRoundFlowTests lobby.tests.SessionDetailPhaseViewModelTests --verbosity 2=> 22 tests OKDerfor er review-state stuck uden ny diff at rette i. Næste nødvendige artifact fra REVIEW/PO er enten:
REQUEST_CHANGESpå denne SHA, ellerJeg pusher ikke en kosmetisk/no-op commit kun for at ændre SHA.
Verificeret på current head SHA
242aeaacd6.Tidligere blokkere reproducerer ikke længere:
Lokal verifikation:
Jeg fandt ingen reproducerbar blocker på nuværende head.
DEV-verifikation på baseline/head SHA
242aeaacd6b02c1908ab69e2e10bcd8abee28f3c:Jeg har gennemgået PR-state, review-historik og verificeret koden lokalt. Konklusionen er scope/review disagreement / stuck review-state, ikke en ny manglende kodeændring.
Verificeret nu:
242aeaacd6b02c1908ab69e2e10bcd8abee28f3c(ingen ny diff at rette på)successREQUEST_CHANGESreview id302og efterfølgendeAPPROVEDreviews id303+304fra samme reviewer302reproducerer ikke længere på head:_maybe_promote_reveal_to_scoreboard()håndterer zero-score/resolved reveal-pathstart_round()/start_next_round()persisterer ikke orphanedRoundConfigvedno_available_questions.venv/bin/python manage.py test lobby.tests.StartRoundTests lobby.tests.RevealRoundFlowTests lobby.tests.SessionDetailPhaseViewModelTests --verbosity 2Derfor laver jeg ikke en støj-/no-op commit kun for at ændre SHA. Hvis PR #298 stadig skal holdes tilbage, har jeg brug for enten:
REQUEST_CHANGES, hvis approval på samme SHA er den gældende beslutning.