-
-
Notifications
You must be signed in to change notification settings - Fork 2
[SUGGESTION] ENH: streamline controller dependency injection in routes and tests #66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
- Create FastAPI dependency providers for all controllers - Implement singleton pattern using lru_cache for thread-safety - Add type aliases (RocketControllerDep, MotorControllerDep, etc.) - Improves performance by avoiding controller re-instantiation on every request References: - FastAPI Dependencies: https://fastapi.tiangolo.com/tutorial/dependencies/
- Replace manual FlightController instantiation with FlightControllerDep - Apply DI pattern across all flight endpoints (CRUD + simulate + binary) - Maintains backward compatibility with existing API contracts
- Replace manual RocketController instantiation with RocketControllerDep - Apply DI pattern to all rocket endpoints including motor-reference flows
- Replace manual MotorController instantiation with MotorControllerDep - Apply DI pattern to all motor endpoints (CRUD + simulate + binary)
- Replace manual EnvironmentController instantiation with EnvironmentControllerDep - Complete DI migration across all API routes - All controllers now use singleton pattern for optimal performance
- Replace patch from src.routes to src.dependencies for controller mocking - Use AsyncMock for all controller methods (they are async functions) - Clear lru_cache before and after each test to ensure fresh mock instances
|
Warning Rate limit exceeded@GabrielBarberini has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 16 minutes and 1 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (2)
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughAdds a dependency-injection layer ( Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (10)
README.md (1)
18-21: Specify language for fenced code block.The code block at line 19 should specify a language identifier. This improves syntax highlighting and complies with markdown linting standards.
Apply this diff to add the
textlanguage identifier:-``` +```text RuntimeError: uvloop does not support Windows at the moment -``` +```tests/unit/test_routes/test_motors_route.py (1)
28-45: Well-structured fixture for DI-based controller mocking.The fixture correctly:
- Patches
MotorControllerat the dependencies module level- Uses
AsyncMockfor async controller methods- Clears the LRU cache before and after the test to ensure isolation
One minor observation: line 1 still imports
Mockwhich appears unused in this file (onlyAsyncMockis used throughout).-from unittest.mock import patch, AsyncMock, Mock +from unittest.mock import patch, AsyncMocktests/unit/test_routes/test_rockets_route.py (2)
22-25: Minor formatting issue: extra blank line in import block.Line 23 contains only whitespace which creates inconsistent formatting.
) - - + from src.dependencies import get_rocket_controller -
77-96: LGTM! Fixture correctly implements the DI mocking pattern.The fixture follows the same well-structured approach as the motors test, properly handling cache clearing for test isolation.
Similar to motors,
Mockis imported on line 1 but onlyAsyncMockappears to be used.-from unittest.mock import patch, Mock, AsyncMock +from unittest.mock import patch, AsyncMocktests/unit/test_routes/test_environments_route.py (1)
28-46: LGTM! Fixture correctly implements the DI mocking pattern.The fixture properly handles cache clearing for test isolation.
Minor observations:
- Lines 40-41 have two consecutive blank lines (formatting inconsistency)
Mockis imported on line 1 but onlyAsyncMockis usedmock_class.return_value = mock_controller - - + get_environment_controller.cache_clear()tests/unit/test_routes/test_flights_route.py (1)
47-68: LGTM! Comprehensive fixture for flight controller mocking.The fixture correctly mocks all flight controller methods including:
- Standard CRUD operations (
post_flight,get_flight_by_id,put_flight_by_id,delete_flight_by_id)- Simulation and binary endpoints (
get_flight_simulation,get_rocketpy_flight_binary)- Reference-based operations (
create_flight_from_references,update_flight_from_references)- Partial update operations (
update_environment_by_flight_id,update_rocket_by_flight_id)Same minor note:
Mockis imported on line 1 but onlyAsyncMockis used.-from unittest.mock import patch, Mock, AsyncMock +from unittest.mock import patch, AsyncMocksrc/dependencies.py (2)
11-22: Clarify thread-safety claim in docstring.The docstring states "Using lru_cache ensures thread-safe singleton behavior," which is not entirely accurate. While
lru_cacheoperations are thread-safe, there's a subtle race condition: if multiple threads callget_rocket_controller()simultaneously on the first invocation before the cache is populated, multipleRocketController()instances could be created (only one will be cached).In practice, this is acceptable for FastAPI since controllers are typically stateless (as documented), and FastAPI's dependency system handles this gracefully. However, consider clarifying the docstring to avoid confusion.
""" Provides a singleton RocketController instance. - The controller is stateless and can be safely reused across requests. - Using lru_cache ensures thread-safe singleton behavior. + The controller is stateless and can be safely reused across requests, + so even in the unlikely event of duplicate instantiation during startup, + behavior remains correct. Returns: RocketController: Shared controller instance for rocket operations. """
25-55: Inconsistent docstrings across factory functions.
get_rocket_controller()includes explanation about statelessness and reuse, but the other three factories (get_motor_controller,get_environment_controller,get_flight_controller) have minimal docstrings. Consider harmonizing them for consistency.src/routes/flight.py (2)
2-2: Clarify the primary benefit of dependency injection.The docstring mentions "improved performance," but DI's main benefits are testability, maintainability, and lifecycle management rather than performance. Consider revising to reflect the actual benefits.
Apply this diff:
-Flight routes with dependency injection for improved performance. +Flight routes
78-78: Remove trailing whitespace.Several lines contain trailing whitespace which should be removed for consistency with project formatting standards.
Apply this diff:
with tracer.start_as_current_span("read_flight"): return await controller.get_flight_by_id(flight_id) - + @router.put("/{flight_id}", status_code=204)return await controller.update_flight_from_references( flight_id, payload ) - + @router.delete("/{flight_id}", status_code=204)response_class=Response, ) - async def get_rocketpy_flight_binary(rocket=rocket, ) - + @router.get("/{flight_id}/simulate")with tracer.start_as_current_span("get_flight_simulation"): return await controller.get_flight_simulation(flight_id) - +Also applies to: 119-119, 146-146, 212-212, 227-227
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
README.md(1 hunks)src/dependencies.py(1 hunks)src/routes/environment.py(6 hunks)src/routes/flight.py(10 hunks)src/routes/motor.py(5 hunks)src/routes/rocket.py(7 hunks)tests/unit/test_routes/test_environments_route.py(2 hunks)tests/unit/test_routes/test_flights_route.py(2 hunks)tests/unit/test_routes/test_motors_route.py(2 hunks)tests/unit/test_routes/test_rockets_route.py(2 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-02-25T21:53:37.291Z
Learnt from: GabrielBarberini
Repo: RocketPy-Team/Infinity-API PR: 44
File: src/controllers/interface.py:49-56
Timestamp: 2025-02-25T21:53:37.291Z
Learning: In the Infinity-API architecture, controller methods are intentionally named with the model name included (e.g., `get_environment_by_id` rather than just `get_by_id`) to maintain a convention over configuration approach, enable future automatic route generation, prevent method name collisions, and provide self-documenting code.
Applied to files:
src/routes/environment.py
📚 Learning: 2024-11-15T15:12:21.314Z
Learnt from: GabrielBarberini
Repo: RocketPy-Team/Infinity-API PR: 38
File: lib/routes/motor.py:75-75
Timestamp: 2024-11-15T15:12:21.314Z
Learning: When modifying API route paths in `lib/routes/motor.py`, changing from `/rocketpy/{motor_id}` to `/{motor_id}/rocketpy` is acceptable when no external consumers are affected. It's acceptable to introduce this breaking change if the team has decided to adopt the new approach, provided that the `README` and related documentation are updated accordingly.
Applied to files:
src/routes/environment.pytests/unit/test_routes/test_rockets_route.pytests/unit/test_routes/test_motors_route.pysrc/routes/motor.pysrc/routes/flight.pysrc/routes/rocket.py
📚 Learning: 2024-12-07T11:50:08.415Z
Learnt from: GabrielBarberini
Repo: RocketPy-Team/Infinity-API PR: 41
File: tests/test_routes/test_flights_route.py:122-125
Timestamp: 2024-12-07T11:50:08.415Z
Learning: In the project's pytest test files (e.g., `tests/test_routes/test_flights_route.py`), fixtures like `stub_rocket` and `stub_flight` are function-scoped and can be safely modified within tests without causing side effects.
Applied to files:
tests/unit/test_routes/test_environments_route.pytests/unit/test_routes/test_rockets_route.pytests/unit/test_routes/test_flights_route.pytests/unit/test_routes/test_motors_route.pysrc/routes/flight.py
📚 Learning: 2024-11-16T00:03:14.224Z
Learnt from: GabrielBarberini
Repo: RocketPy-Team/Infinity-API PR: 38
File: tests/test_routes/test_motors_route.py:42-100
Timestamp: 2024-11-16T00:03:14.224Z
Learning: In `tests/test_routes/test_motors_route.py`, focus on assessing whether the API has the capability of validating the input schema, rather than testing the extension of Pydantic validations (e.g., testing empty request payloads).
Applied to files:
tests/unit/test_routes/test_motors_route.pysrc/routes/motor.py
🧬 Code graph analysis (9)
src/routes/environment.py (2)
src/services/environment.py (3)
environment(42-43)environment(46-47)EnvironmentService(11-71)src/controllers/environment.py (3)
get_rocketpy_environment_binary(23-41)EnvironmentController(10-61)__init__(19-20)
tests/unit/test_routes/test_environments_route.py (3)
src/dependencies.py (1)
get_environment_controller(37-44)src/routes/environment.py (2)
get_environment_simulation(133-144)get_rocketpy_environment_binary(106-129)src/controllers/environment.py (3)
get_environment_simulation(44-61)get_rocketpy_environment_binary(23-41)EnvironmentController(10-61)
tests/unit/test_routes/test_rockets_route.py (1)
src/dependencies.py (1)
get_rocket_controller(12-22)
tests/unit/test_routes/test_flights_route.py (3)
src/dependencies.py (1)
get_flight_controller(48-55)src/routes/flight.py (4)
get_flight_simulation(215-226)get_rocketpy_flight_binary(147-168)create_flight_from_references(47-62)update_flight_from_references(99-118)src/controllers/flight.py (5)
get_flight_simulation(146-164)get_rocketpy_flight_binary(125-143)create_flight_from_references(53-62)update_flight_from_references(65-78)FlightController(18-164)
src/dependencies.py (5)
src/controllers/rocket.py (1)
RocketController(17-97)src/controllers/motor.py (1)
MotorController(10-59)src/controllers/environment.py (1)
EnvironmentController(10-61)src/controllers/flight.py (1)
FlightController(18-164)src/services/rocket.py (1)
RocketService(26-260)
tests/unit/test_routes/test_motors_route.py (3)
src/dependencies.py (1)
get_motor_controller(26-33)src/routes/motor.py (1)
get_motor_simulation(129-140)src/controllers/motor.py (1)
get_motor_simulation(44-59)
src/routes/motor.py (1)
src/controllers/motor.py (3)
get_rocketpy_motor_binary(23-41)get_motor_simulation(44-59)MotorController(10-59)
src/routes/flight.py (1)
src/controllers/flight.py (5)
create_flight_from_references(53-62)get_rocketpy_flight_binary(125-143)get_flight_simulation(146-164)FlightController(18-164)update_flight_from_references(65-78)
src/routes/rocket.py (5)
src/repositories/rocket.py (1)
create_rocket(21-22)src/services/rocket.py (2)
rocket(99-100)rocket(103-104)src/models/rocket.py (2)
RocketModel(25-111)RocketWithMotorReferenceRequest(147-161)src/views/rocket.py (2)
RocketCreated(67-69)RocketRetrieved(72-74)src/controllers/rocket.py (2)
create_rocket_from_motor_reference(41-46)get_rocketpy_rocket_binary(61-76)
🪛 markdownlint-cli2 (0.18.1)
README.md
19-19: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🔇 Additional comments (9)
tests/unit/test_routes/test_motors_route.py (1)
12-14: LGTM! Import changes align with the new DI pattern.The import of
get_motor_controlleris necessary for cache management in the test fixture.tests/unit/test_routes/test_environments_route.py (1)
13-15: LGTM! Import structure is correct.tests/unit/test_routes/test_flights_route.py (1)
18-20: LGTM! Import structure is correct.src/dependencies.py (2)
1-9: LGTM! Clean imports for the DI module.Appropriate use of
functools.lru_cache,Annotated, andDependsfor FastAPI dependency injection.
57-62: LGTM! Well-defined type aliases for dependency injection.The
Annotatedtype aliases provide clean, reusable dependency declarations for route handlers, following FastAPI best practices.src/routes/environment.py (1)
14-14: Dependency injection pattern correctly applied.All environment endpoints consistently use
EnvironmentControllerDepfor controller injection. The pattern is clean and uniform across CRUD, binary, and simulation endpoints.Also applies to: 32-32, 47-47, 63-63, 83-83, 108-108, 135-135
src/routes/motor.py (1)
14-14: Dependency injection pattern correctly applied.All motor endpoints consistently use
MotorControllerDepfor controller injection, matching the pattern established in environment routes.Also applies to: 30-33, 45-48, 60-64, 79-82, 104-107, 129-132
src/routes/rocket.py (1)
17-17: Dependency injection pattern correctly applied.All rocket endpoints, including the motor-reference flows, consistently use
RocketControllerDepfor controller injection.Also applies to: 33-36, 48-48, 64-67, 79-83, 101-101, 119-122, 144-147, 169-172
src/routes/flight.py (1)
16-16: Dependency injection pattern correctly applied.All flight endpoints, including reference-based and partial-update flows, consistently use
FlightControllerDepfor controller injection.Also applies to: 32-35, 49-49, 66-68, 80-84, 102-102, 121-124, 147-150, 173-176, 193-197, 215-218
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
GabrielBarberini
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent contribution! We used to have stateful controllers in the past and ever since we refactored it with the interface reflection it became stateless and we totally missed the opportunity to introduce dep. inj
Great job
| from src.controllers.environment import EnvironmentController | ||
| from src.controllers.flight import FlightController | ||
|
|
||
| @lru_cache(maxsize=1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MarcosMulari what would you say to the idea of using simple @cache instead?
Since there are no args here maxsize=1 will act as a Noop and cache === lru_cache(maxsize=None)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
tests/unit/test_routes/test_environments_route.py (1)
13-14: Remove extra blank line.Two consecutive blank lines appear before the import statement. Standard convention is one blank line between import groups.
Apply this diff:
) - from src.dependencies import get_environment_controllertests/unit/test_routes/test_rockets_route.py (1)
22-23: Remove extra blank line.Two consecutive blank lines appear before the import statement. Standard convention is one blank line between import groups.
Apply this diff:
) - from src.dependencies import get_rocket_controller
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/routes/flight.py(10 hunks)tests/unit/test_routes/test_environments_route.py(2 hunks)tests/unit/test_routes/test_rockets_route.py(2 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
tests/{unit,integration}/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
tests/{unit,integration}/**/*.py: Tests mirror the src layout undertests/unit/andtests/integration/for focused and end-to-end coverage
Place pure-function tests intests/unit/and API or database flows intests/integration/
Files:
tests/unit/test_routes/test_environments_route.pytests/unit/test_routes/test_rockets_route.py
{src,tests}/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
{src,tests}/**/*.py: Runmake formatwith Black and Ruff autofixes acrosssrc/andtests/
Executemake lintwith Flake8 and Pylint against repository presets
Runmake formatbefore opening a pull request to avoid stylistic churn
Files:
tests/unit/test_routes/test_environments_route.pytests/unit/test_routes/test_rockets_route.pysrc/routes/flight.py
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Target Python 3.12 and enforce 79-character line length using Black, Ruff, and Pylint
Files:
tests/unit/test_routes/test_environments_route.pytests/unit/test_routes/test_rockets_route.pysrc/routes/flight.py
tests/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
tests/**/*.py: Name test filestest_<feature>.pyand group fixtures near usage
Execute pytest with--import-mode=importlibbehavior intact when running integration tests
Files:
tests/unit/test_routes/test_environments_route.pytests/unit/test_routes/test_rockets_route.py
src/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.py: Source code lives insrc/, with FastAPI entrypoints insrc/api.pyand domain layers grouped by concern (controllers/,services/,repositories/,models/,routes/,views/)
Use module-level functions insnake_case, classes inPascalCase, and constants inUPPER_SNAKE_CASE
Usesrc/secrets.pyhelpers for secret access rather than inlining values
Files:
src/routes/flight.py
src/{routes,models}/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Name FastAPI routers
<feature>_routerinsidesrc/routes/and align Pydantic models withCamelCaseclass names undersrc/models/
Files:
src/routes/flight.py
🧠 Learnings (2)
📚 Learning: 2024-12-07T11:50:08.415Z
Learnt from: GabrielBarberini
Repo: RocketPy-Team/Infinity-API PR: 41
File: tests/test_routes/test_flights_route.py:122-125
Timestamp: 2024-12-07T11:50:08.415Z
Learning: In the project's pytest test files (e.g., `tests/test_routes/test_flights_route.py`), fixtures like `stub_rocket` and `stub_flight` are function-scoped and can be safely modified within tests without causing side effects.
Applied to files:
tests/unit/test_routes/test_environments_route.pytests/unit/test_routes/test_rockets_route.pysrc/routes/flight.py
📚 Learning: 2024-11-15T15:12:21.314Z
Learnt from: GabrielBarberini
Repo: RocketPy-Team/Infinity-API PR: 38
File: lib/routes/motor.py:75-75
Timestamp: 2024-11-15T15:12:21.314Z
Learning: When modifying API route paths in `lib/routes/motor.py`, changing from `/rocketpy/{motor_id}` to `/{motor_id}/rocketpy` is acceptable when no external consumers are affected. It's acceptable to introduce this breaking change if the team has decided to adopt the new approach, provided that the `README` and related documentation are updated accordingly.
Applied to files:
tests/unit/test_routes/test_rockets_route.pysrc/routes/flight.py
🧬 Code graph analysis (3)
tests/unit/test_routes/test_environments_route.py (3)
src/dependencies.py (1)
get_environment_controller(37-44)src/routes/environment.py (2)
get_environment_simulation(133-144)get_rocketpy_environment_binary(106-129)src/controllers/environment.py (3)
get_environment_simulation(44-61)get_rocketpy_environment_binary(23-41)EnvironmentController(10-61)
tests/unit/test_routes/test_rockets_route.py (1)
src/dependencies.py (1)
get_rocket_controller(12-22)
src/routes/flight.py (6)
src/repositories/flight.py (1)
create_flight(21-22)src/services/flight.py (2)
flight(47-48)flight(51-52)src/models/flight.py (2)
FlightModel(10-96)FlightWithReferencesRequest(132-147)src/views/flight.py (2)
FlightCreated(148-150)FlightRetrieved(153-155)src/controllers/flight.py (3)
create_flight_from_references(53-62)get_rocketpy_flight_binary(125-143)update_flight_from_references(65-78)tests/unit/test_routes/test_flights_route.py (2)
test_update_rocket_by_flight_id(352-361)mock_controller_instance(45-60)
🔇 Additional comments (6)
tests/unit/test_routes/test_rockets_route.py (1)
77-96: LGTM! Test fixture correctly implements DI pattern.The fixture correctly patches the controller at the dependency layer, uses AsyncMock for async methods, and manages the LRU cache lifecycle. Unlike the environment test file, this fixture correctly yields only once.
src/routes/flight.py (5)
2-2: LGTM! Docstring and import correctly reflect DI refactoring.The updated docstring accurately describes the dependency injection improvement, and the import of
FlightControllerDepfollows the established pattern across other route modules (environment, motor, rocket).Also applies to: 16-16
32-43: LGTM! CRUD endpoints correctly implement DI pattern.All CRUD endpoints (create, read, update, delete) consistently accept the injected
FlightControllerDepparameter and delegate to controller methods. This eliminates per-request controller instantiation and leverages the singleton pattern defined insrc/dependencies.py.Also applies to: 66-77, 80-95, 121-132
47-62: LGTM! Reference-based endpoints correctly implement DI pattern.The reference-based creation and update endpoints correctly accept the injected controller, maintaining consistency with the CRUD endpoints.
Also applies to: 99-118
172-189: LGTM! Component update endpoints correctly implement DI pattern.The environment and rocket update endpoints correctly accept the injected controller, allowing independent updates of flight components while maintaining the DI pattern.
Also applies to: 193-211
147-168: LGTM! Simulation and binary endpoints correctly implement DI pattern.Both the binary download and simulation endpoints correctly accept the injected controller. The blank line at line 146 provides appropriate spacing before the function definition.
Also applies to: 214-225
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| get_environment_controller.cache_clear() | ||
|
|
||
| yield mock_controller | ||
|
|
||
| get_environment_controller.cache_clear() | ||
|
|
||
| get_environment_controller.cache_clear() |
Copilot
AI
Dec 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate cache_clear() calls detected. Lines 40-42 and 46-48 each contain two consecutive cache_clear() calls. Only one cache_clear() call is needed before yielding and one after to properly reset the singleton controller cache between tests.
| get_environment_controller.cache_clear() | |
| yield mock_controller | |
| get_environment_controller.cache_clear() | |
| get_environment_controller.cache_clear() | |
| yield mock_controller | |
| get_environment_controller.cache_clear() | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its a minor but I agree that only one cache clear is necessary, we can assume "permanent regime" in any running environment since memoization lives in runtime
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Changes
Core Implementation
@lru_cache(maxsize=1)for thread-safe controller reuseAnnotated[Controller, Depends(...)]Routes Refactoring
Test Updates
src.dependenciescontrollers instead ofsrc.routesAsyncMockfor all controller methods (they are async functions)lru_cachebefore and after each test to ensure fresh mock instancespatch('src.dependencies.ControllerClass')Related Files
src/dependencies.py- Dependency providerssrc/routes/environment.pysrc/routes/motor.pysrc/routes/rocket.pysrc/routes/flight.pytests/unit/test_routes/test_environments_route.pytests/unit/test_routes/test_motors_route.pytests/unit/test_routes/test_rockets_route.pytests/unit/test_routes/test_flights_route.pyTesting
All route tests updated and passing with the new dependency injection pattern. Controllers are properly mocked and isolated for unit testing.

Testing Strategy Discussion
Initial confusion: I didn't understand why tests call the endpoint through the
clientinstead of directly testing the controller function. Seemed redundant at first.What I learned: This is actually an intentional integration test pattern with specific benefits:
End-to-end verification: By calling through
client.post(), we test the entire request pipeline:Real-world scenarios: The endpoint test simulates actual HTTP usage, catching issues that direct function calls would miss:
Test isolation: Mocking the controller ensures we're testing the route layer independently without touching the actual database/services
Summary by CodeRabbit
Documentation
Refactor
Tests
✏️ Tip: You can customize this high-level summary in your review settings.