Skip to content

refactor(queue): replace manual status validation with pytransitions

Greeshma Kanukunta requested to merge fix/transitions_library into develop

Overview

This MR replaces the manual, dictionary-based status transition validation for the consultation queue with a robust, centralized finite state machine using the transitions library. It eliminates scattered imperative checks and replaces them with an automated, scalable state enforcement mechanism.

What does this MR do and why?

Queue status transitions in app/services/consultation_queue_service.py were previously governed by a hardcoded VALID_TRANSITIONS dictionary (~120 LOC) alongside manual validation logic. This approach was error-prone, fragile, and difficult to maintain when adding or modifying states.

By integrating the actively maintained transitions library, we have:

  • Centralized the state definitions (MACHINE_STATES) and transition rules (MACHINE_TRANSITIONS).
  • Delegated the responsibility of strict transition validation entirely to the state machine.
  • Maintained exact backward compatibility with how errors (ValueError) are bubbled up to the API layer when invalid transitions are attempted.

Changes Made

  • Added Dependencies: Added transitions>=0.9.0 to pyproject.toml and updated uv.lock.
  • Modified Service: Refactored app/services/consultation_queue_service.py.
  • Removed Code: Deleted the static VALID_STATUS_TRANSITIONS dictionary entirely.
  • Added Logic: Created a dynamic StateWrapper inside update_queue_status that initializes the Machine on the fly to process the requested status change trigger (advance_to_<status>).

Technical Details

  • Architecture decisions made: Instead of attaching the state machine directly to the SQLAlchemy model (which can cause caching/initialization headaches in FastAPI request lifecycles), we dynamically instantiate a lightweight StateWrapper inside the service function exactly when an update is requested. This ensures total thread safety and predictable validation without polluting the database model.
  • Error Handling: transitions.MachineError is natively caught and translated into the exact ValueError the original code threw, meaning all existing API integrations and frontend clients remain completely unaffected.

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to change)
  • 📝 Documentation update
  • ️ Refactor (no functional changes)
  • Performance improvement
  • 🧪 Test update
  • 🔧 Configuration change
  • 🚨 Security fix
  • 🗑️ Deprecation (removing deprecated code)

Related Issues / References

Screenshots or Screen Recordings

(Not applicable as these are internal service layer logic changes only. No API contracts or UI layouts were modified).

How to Validate Locally

  1. Pull the branch locally and rebuild the Docker container to ensure the new transitions dependency is installed: docker compose up -d --build api
  2. Start the application and log in as a coordinator or doctor.
  3. Valid transition check: Register a patient and assign them to a doctor (moves them to vitals queue). Progress them normally through the frontend UI (e.g. vitals -> know_your_patient -> waiting).
  4. Invalid transition check: Attempt to skip a mandatory state (e.g., trying to force a patient from vitals directly to in_consultation via swagger UI or curl). Verify the API rejects the request with a 400 Bad Request / 500 error containing the ValueError matching the old behavior.

Testing Done

  • Unit tests added/updated
  • API endpoint tests passing

Test Cases Covered:

Scenario Expected Result Status
Valid state transition (vitals -> know_your_patient) Transition success, state updated
Invalid state transition jump (vitals -> in_consultation) Raises ValueError, aborts update
Attempting to transition to current state Ignored/handled gracefully

Test Commands Run:

# Run consultation queue specific tests
uv run pytest tests/test_services/test_consultation_queue_service.py


# Example: Run specific test file
pytest tests/test_api_v1/test_patient_routes.py -v

# Example: Run with coverage
pytest --cov=app

Code Quality Checklist

Code Standards

  • Code follows project conventions (naming, structure, formatting)

  • No debug statements or commented-out code left (unless necessary and intended)

  • No unused imports, variables, or functions

  • No duplicate code (DRY principle followed)

  • Type hints are properly defined (no Any unless justified and no mypy type check errors)

  • Ruff checks pass:

    ruff check .
    ruff format . --check

Python & FastAPI Best Practices

  • Functions follow single-responsibility principle
  • Async/await used correctly (no blocking calls in async functions)
  • Dependency injection used appropriately
  • Pydantic models used for request/response validation
  • SQLAlchemy queries are optimized (no N+1 queries)
  • Error handling is comprehensive (try/except with proper logging)

API Design

  • RESTful conventions followed
  • Proper HTTP status codes returned
  • Input validation implemented
  • Authentication/authorization enforced
  • Role Base access control used for user restriction
  • API documentation (docstrings) updated

Database & Migrations

  • Database migrations created (if schema changed)
  • Database migrations version is pointing to the latest version (and version name follows project conventions)
  • Migrations are reversible (migrations contain downgrade scripts)
  • Indexes added for frequently queried fields
  • No raw SQL queries (using SQLAlchemy ORM)
  • Data integrity constraints maintained

Security

  • No sensitive data logged (passwords, tokens, PII)

  • SQL injection prevention verified (ORM used)

  • Input sanitization implemented

  • Authentication tokens handled securely

  • CORS settings appropriate

  • Security scan passes:

    bandit -r app/

Error Handling

  • Errors are caught and handled gracefully
  • User-friendly error messages returned
  • Errors are logged appropriately
  • HTTP error responses follow API standards

Documentation

  • README.md updated (if setup steps changed)
  • .env.example updated (if new env vars added)
  • API documentation updated (docstrings, OpenAPI specs)
  • CHANGELOG.md will be updated (if applicable)
  • Code comments explain complex logic (not what, but why)

Known Limitations / Technical Debt

Additional Notes


MR Acceptance Checklist

Quality & Correctness

  • Code works as intended and solves the stated problem
  • No bugs introduced (existing functionality not broken)
  • Edge cases handled appropriately

Maintainability

  • Code is readable and well-organized
  • Code is testable and well-tested
  • Follows project patterns and conventions

Acceptance Review

  • Reviewed by at least 1 teammate
  • Reviewed by product owner

Merge request reports

Loading