You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
9.5 KiB
9.5 KiB
2.3 Game Session Service (Port 8080) - Detailed Implementation Plan
Summary
Implement the Game Session Service as the authoritative runtime engine for quiz gameplay (session lifecycle, timer, attempts, hints, scoring, anti-cheat, and question progression), consistent with the decisions used for Question Bank (2.1) and User Service (2.2).
Runtime stack and conventions:
- Fiber HTTP service with shared bootstrap and observability.
- PostgreSQL persistence with
EnsureSchema(ctx)startup DDL. - Redis for active-session/timer state and fast session guards.
- Shared
backend/sharedpackages for auth, errors, validation, logging, tracing, metrics, and readiness.
Decisions Reused from 2.1 and 2.2
- Service composition pattern:
internal/infra/config.FromEnv()- logger/metrics/tracer init in
cmd/main.go - repo init +
EnsureSchema(ctx)at startup /health,/ready,/metricsregistration- route registration via
internal/interfaces/http/routes.go
- Shared infra usage:
- PostgreSQL client.
- Readiness via shared readiness helper with named checks.
- Zitadel middleware via shared middleware factory.
- Error and transport pattern:
- domain/application errors mapped with shared
httputil.SendError. - consistent response envelope style used in other services.
- Test pyramid:
- unit tests for domain/application rules
- HTTP integration tests with in-memory doubles/fakes
- optional DB-backed integration tests gated by env
Objectives
- Provide full game session lifecycle endpoints.
- Enforce 30-minute server-side session duration.
- Enforce per-question rules: max 3 attempts, hint rules, scoring.
- Integrate with Question Bank for question retrieval/answer validation.
- Validate authenticated player identity via User Service at session start.
- Add anti-cheat checks and audit-friendly session event trail.
- Deliver production-ready observability and reliability behavior.
API Endpoints
POST /sessions/startPOST /sessions/endPOST /sessions/:id/answerPOST /sessions/:id/hintGET /sessions/:idGET /sessions/:id/question
Auth and Access Rules
- All
/sessions/*endpoints require authenticated user token. - Caller must own the session (
token.sub == session.player_id) or be admin. - Admin override allowed for support/debug operations.
- No public gameplay endpoints without auth.
Inter-Service Contracts
User Service dependency
Purpose: validate and hydrate player profile at session start.
- Call
GET /users/:idon start (forward caller bearer token). - Expected minimum fields:
id,display_name,email_verified.
Decision:
- hard-block session start when user is not found, soft-deleted, or unauthorized.
- require
email_verified=trueto start.
Question Bank dependency
Purpose: serve questions and validate answers.
- Fetch question:
POST /questions/randomwith exclusion list. - Validate answer:
POST /questions/:id/validate-answer.
Decision:
- use HTTP client adapters now.
- define application interfaces (
QuestionBankClient,UserClient) so transport can be replaced with gRPC later without domain changes.
Domain Model
Aggregate:
GameSession
Value Objects:
SessionStatus(created|active|completed|timed_out|abandoned)AttemptCounter(0..3)SessionTimer(start/end/remaining)QuestionProgress(current question state)
Domain services:
ScoringServiceGameFlowServiceAntiCheatService
Core invariants
- One active session per player.
- Session expires at
start_time + 30m. - Max attempts per question: 3.
- Hint may be requested once per current question.
- Correct answer advances to next question.
- After 3 incorrect attempts, auto-advance to next question.
- No answer/hint after session is
completed|timed_out|abandoned.
Data Model (PostgreSQL)
game_sessions
id UUID PRIMARY KEYplayer_id VARCHAR(128) NOT NULLplayer_name VARCHAR(50) NOT NULLstatus VARCHAR(16) NOT NULLtotal_score INT NOT NULL DEFAULT 0questions_asked INT NOT NULL DEFAULT 0questions_correct INT NOT NULL DEFAULT 0hints_used INT NOT NULL DEFAULT 0current_question_id VARCHAR(64) NULLcurrent_attempts INT NOT NULL DEFAULT 0current_hint_used BOOLEAN NOT NULL DEFAULT FALSEquestion_started_at TIMESTAMPTZ NULLstart_time TIMESTAMPTZ NOT NULLend_time TIMESTAMPTZ NULLcreated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
Indexes:
(player_id, status)(status, start_time DESC)(created_at DESC)
session_attempts
id UUID PRIMARY KEYsession_id UUID NOT NULLquestion_id VARCHAR(64) NOT NULLattempt_number INT NOT NULLprovided_answer VARCHAR(500) NOT NULLis_correct BOOLEAN NOT NULLused_hint BOOLEAN NOT NULLawarded_score INT NOT NULLlatency_ms INT NOT NULLcreated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
Indexes:
(session_id, question_id, attempt_number)(session_id, created_at DESC)
session_events (anti-cheat/audit observability)
id UUID PRIMARY KEYsession_id UUID NOT NULLevent_type VARCHAR(64) NOT NULLmetadata_json JSONB NOT NULL DEFAULT '{}'::jsonbcreated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
Redis Usage
Keys (prefix gs:):
gs:active:{player_id}-> session_idgs:timer:{session_id}-> expiration timestamp + TTLgs:lock:session:{session_id}-> short lock for answer/hint mutation path
Rules:
- Redis is used for fast guards and timer checks.
- PostgreSQL remains source of truth.
- If Redis unavailable:
- service logs warning
- gameplay still works using PostgreSQL timing checks
- readiness reports redis down but not fatal
Endpoint Behavior
POST /sessions/start
Input:
- optional
preferred_theme, optionaldifficulty. Flow:
- auth required; derive
player_idfrom token. - reject if active session exists.
- call User Service to confirm profile and email verification.
- create session row with
activestate and timestamps. - fetch first question from Question Bank.
- set
current_question_id,question_started_at,questions_asked=1. - write Redis active/timer keys. Output:
- session summary + current question payload.
POST /sessions/:id/answer
Input:
answer(1..500 chars). Flow:
- auth/ownership check.
- lock session (best effort).
- ensure session active and not timed out.
- anti-cheat latency check.
- validate answer via Question Bank.
- record attempt.
- update scoring.
- advance question when correct or max attempts reached.
- complete session if no next question. Output:
- correctness, awarded score, attempts remaining, optional next question, session stats.
POST /sessions/:id/hint
Flow:
- auth/ownership + active check.
- reject if hint already used.
- mark hint usage and increment count.
- return hint.
GET /sessions/:id
- return session status and derived remaining time.
GET /sessions/:id/question
- return current question without answer.
POST /sessions/end
Input:
session_id, optionalreason. Flow:- auth/ownership check
- set terminal state
- clear redis keys
- write
session_events
Anti-Cheat Rules (Initial)
- Reject answers before minimum latency threshold.
- Reject answer/hint when session not active.
- Reject answer/hint when current question missing.
- Reject concurrent out-of-order updates using lock.
- Log suspicious events (
rapid_answer,state_mismatch,expired_session_write).
Package Layout
backend/services/game-session-service/cmd/main.gobackend/services/game-session-service/internal/infra/config/config.gobackend/services/game-session-service/internal/domain/session/backend/services/game-session-service/internal/application/session/backend/services/game-session-service/internal/infra/persistence/ent/backend/services/game-session-service/internal/infra/clients/questionbank/backend/services/game-session-service/internal/infra/clients/usersvc/backend/services/game-session-service/internal/interfaces/http/backend/services/game-session-service/tests/
Configuration
Service-specific:
GAME_SESSION_PORT(default8080)GAME_SESSION_DURATION(default30m)GAME_SESSION_MAX_ATTEMPTS(default3)GAME_SESSION_MIN_ANSWER_LATENCY_MS(default300)GAME_SESSION_LOCK_TTL(default3s)GAME_SESSION_ACTIVE_KEY_TTL(default35m)GAME_SESSION_END_REASON_DEFAULT(defaultabandoned)QUESTION_BANK_BASE_URL(defaulthttp://localhost:8081)USER_SERVICE_BASE_URL(defaulthttp://localhost:8082)UPSTREAM_HTTP_TIMEOUT(default3s)
Shared:
POSTGRES_*,REDIS_*,TRACING_*,METRICS_*,LOG_LEVEL,ZITADEL_*
Testing Strategy
- Unit tests:
- state transitions
- scoring matrix
- attempt/hint limits
- anti-cheat threshold behavior
- HTTP integration tests:
- start->answer->hint->end flow
- unauthorized behavior
- metrics endpoint availability
- Repository integration tests (optional env-gated):
- schema creation
- transaction behavior
- active-session constraints
Verification
From backend/services/game-session-service:
go test ./...
go vet ./...
Optional from backend:
go test ./...
Definition of Done
- All endpoints implemented and auth/ownership protected.
- Session lifecycle, timer, attempts, hint and scoring rules enforced server-side.
- Upstream integrations with User Service and Question Bank functional.
/health,/ready,/metricsfunctional with named readiness checks.- Anti-cheat checks implemented and events logged.
go test ./...andgo vet ./...pass for game-session-service.