Avoid eager Elo/MMR imports during backend startup while the feature is paused. Add validation coverage for backend startup and health route resolution.
8.0 KiB
id, title, status, type, team, supporting_teams, roadmap_item, priority
| id | title | status | type | team | supporting_teams | roadmap_item | priority | |
|---|---|---|---|---|---|---|---|---|
| TASK-109 | Keep backend startup independent from paused Elo/MMR | pending | backend | Backend Senior |
|
foundation | high |
TASK-109 - Keep backend startup independent from paused Elo/MMR
Goal
Fix backend startup so the default operational Compose profile can start backend and frontend while Elo/MMR and complex historical materialization remain paused.
The backend must expose /health and non-Elo routes even if Elo/MMR engine internals are unavailable or temporarily broken.
Context
HLL Vietnam has simplified its default operational mode. The normal Compose profile should start only backend and frontend; historical workers, Elo/MMR, complex historical materialization, and server #03 are paused operationally.
Current validation shows:
docker compose config --servicesreturns onlybackendandfrontend.docker compose up -d --buildstarts the frontend successfully.- The frontend responds with HTTP 200.
- The backend restarts continuously.
/healthfails because backend startup imports Elo/MMR code.- Backend logs include:
ImportError: cannot import name 'ELO_K_FACTOR' from 'app.elo_mmr_models'. - The startup import path is:
app.main -> app.routes -> app.payloads -> app.elo_mmr_engine -> app.elo_mmr_models. payloads.pyimports Elo/MMR payload functions at module import time, so a paused or broken Elo implementation can break the whole backend, including/health.
This task is startup-focused. Preserve the existing HLL Vietnam product identity and repository discipline, and keep the fix narrow.
Steps
- Inspect the listed files before changing anything.
- Confirm the backend startup import path and where Elo/MMR is imported at module load time.
- Refactor only the startup boundary needed so
/healthand non-Elo routes do not depend on successful import of Elo/MMR engine internals. - Prefer lazy importing Elo/MMR functions only inside Elo-specific payload builders or routes.
- If Elo/MMR is paused or unavailable, make Elo-specific endpoints return a controlled unavailable or fallback payload instead of crashing backend import.
- Preserve the public API shape as much as possible.
- Add or update tests if a backend test framework exists.
- Update lightweight validation if needed so future startup import regressions are caught.
- Document the paused Elo/MMR startup boundary if documentation needs adjustment.
- Run the required validation before committing.
- Move this task file to
ai/tasks/done/only after validation is complete and the outcome is documented. - Stage only intended files, commit, and push the branch to origin.
Files to Read First
backend/app/main.pybackend/app/routes.pybackend/app/payloads.pybackend/app/elo_mmr_engine.pybackend/app/elo_mmr_models.pybackend/app/config.pybackend/tests/if presentdocker-compose.ymlscripts/run-integration-tests.ps1README.mddocs/decisions.md
Expected Files to Modify
- likely
backend/app/payloads.py - possibly
backend/app/routes.py - possibly
backend/app/elo_mmr_engine.py - possibly
backend/app/elo_mmr_models.pyonly if justified - possibly tests under
backend/tests/ - possibly
scripts/run-integration-tests.ps1 - this task file moved from
ai/tasks/pending/toai/tasks/done/
If additional files become necessary, explain why in the task outcome and commit message.
Expected Files Not to Modify
frontend/**docker-compose.yml, unless validation proves a Compose-only issue also exists- database migrations
- persisted data
- unrelated backend modules
- server #03 configuration
Constraints
- Do not delete Elo/MMR code.
- Do not delete historical ingestion code.
- Do not remove database migrations or persisted data.
- Do not change frontend behavior.
- Do not reintroduce server #03.
- Keep the fix narrow and startup-focused.
- Do not implement a new Elo/MMR algorithm.
- Do not reintroduce
ELO_K_FACTORas a blind compatibility patch unless you prove it is the smallest safe fix and still prevents startup coupling. - Keep
/healthavailable even if Elo/MMR import fails. - Preserve existing public API shape as much as possible.
- Do not modify unrelated files.
- Do not leave completed work only in local; commit and push after validation.
Validation
Before completing the task, run and document:
git statuspowershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1docker compose downdocker compose up -d --builddocker compose psdocker compose logs --tail=100 backendInvoke-WebRequest http://localhost:8000/health | Select-Object -ExpandProperty ContentInvoke-WebRequest http://localhost:8080 | Select-Object -ExpandProperty StatusCode
Also confirm and document:
- backend is not restarting
/healthreturns a valid payload- frontend still returns 200
- no frontend files changed
- no database migrations or persisted data changed
backend/runtime/is not created or committedgit diff --name-onlymatches the expected scope
If integration tests are relevant and scripts/run-integration-tests.ps1 exists, use it. If no backend test framework exists for this scope, document that explicitly in the outcome.
Commit And Push Requirements
- Run all validation before committing.
- Run
git status. - Stage only intended files.
- Commit with a clear message, for example:
fix: keep backend startup independent from paused elo. - Push the branch to origin.
- Do not leave completed work only in local.
Outcome
- Validation performed:
git status --shortpython -c "import sys; sys.path.insert(0, 'backend'); import app.main; from app.routes import resolve_get_payload; print(resolve_get_payload('/health'))"python -c "import sys; sys.path.insert(0, 'backend'); from app.routes import resolve_get_payload; print(resolve_get_payload('/api/historical/elo-mmr/leaderboard'))"powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1docker compose downdocker compose up -d --builddocker compose psdocker compose logs --tail=100 backendInvoke-WebRequest http://localhost:8000/health | Select-Object -ExpandProperty ContentInvoke-WebRequest http://localhost:8080 | Select-Object -ExpandProperty StatusCodeInvoke-WebRequest 'http://localhost:8000/api/historical/elo-mmr/leaderboard' | Select-Object -ExpandProperty Contentgit diff --name-only
- Startup coupling removed:
backend/app/payloads.pyno longer importsapp.elo_mmr_engineat module load time.- Elo/MMR engine imports now happen only inside Elo/MMR payload builders.
app.main -> app.routes -> app.payloadscan load and serve/healthwithout importing paused Elo/MMR internals.
- Elo/MMR unavailable behavior:
- If the Elo/MMR engine cannot be imported, Elo/MMR endpoints return the existing
status+dataenvelope withsource: "elo-mmr-paused",available: false,unavailable_reason: "elo-mmr-engine-import-unavailable", normal source policy metadata, and empty/null Elo data.
- If the Elo/MMR engine cannot be imported, Elo/MMR endpoints return the existing
- Tests and validation:
- No backend test framework is configured for this scope.
scripts/run-integration-tests.ps1now includes a lightweight backend startup import check and/healthroute resolution check.
- Scope confirmation:
- Backend was up and not restarting in
docker compose ps. /healthreturned a valid JSON payload withstatus: "ok".- Frontend returned HTTP
200. - No frontend files changed.
- No database migrations, persisted data, or server #03 configuration changed.
backend/runtime/was not created.git diff --name-onlymatched the expected scope:backend/app/payloads.pyandscripts/run-integration-tests.ps1.
- Backend was up and not restarting in
- Commit and push:
- Commit hash and pushed branch are recorded in the final task execution response.
Change Budget
- Prefer fewer than 5 modified files.
- Prefer changes under 200 lines when feasible.
- Split follow-up work into a new task if the scope expands beyond startup independence.