From d254e7fc63063e74f999bd935c96e56b51df4fdd Mon Sep 17 00:00:00 2001 From: rayhpeng Date: Wed, 29 Jul 2026 19:58:11 +0800 Subject: [PATCH] refactor(feedback): take the service through an Annotated dependency alias Align the feedback router's dependency injection with the schedule slice's ScheduleServiceDep shape: a FeedbackServiceDep alias in deps.py, handlers declaring the service as a parameter instead of resolving it inline. Swapping the provider is now a one-line change and parameter order stays unconstrained. The two conditional lookups in thread_runs.py deliberately keep the imperative call -- they only need the service when a page actually has an AI message to decorate, and a declared dependency would 503 the whole listing on a memory backend. --- backend/app/gateway/deps.py | 4 ++++ backend/app/gateway/routers/feedback.py | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/backend/app/gateway/deps.py b/backend/app/gateway/deps.py index 120f18872..24c521b72 100644 --- a/backend/app/gateway/deps.py +++ b/backend/app/gateway/deps.py @@ -550,6 +550,10 @@ get_run_event_store: Callable[[Request], RunEventStore] = _require("run_event_st get_feedback_service: Callable[[Request], FeedbackService] = _require("feedback_service", "Feedback") get_run_store: Callable[[Request], RunStore] = _require("run_store", "Run store") +# Same alias shape as ScheduleServiceDep: routes take the service without a +# default argument, and swapping the provider is a one-line change here. +FeedbackServiceDep = Annotated[FeedbackService, Depends(get_feedback_service)] + def get_store(request: Request): """Return the global store (may be ``None`` if not configured).""" diff --git a/backend/app/gateway/routers/feedback.py b/backend/app/gateway/routers/feedback.py index 38d796034..a393a8d64 100644 --- a/backend/app/gateway/routers/feedback.py +++ b/backend/app/gateway/routers/feedback.py @@ -18,7 +18,7 @@ from fastapi import APIRouter, HTTPException, Request from pydantic import BaseModel, Field from app.gateway.authz import require_permission -from app.gateway.deps import get_current_user, get_feedback_service +from app.gateway.deps import FeedbackServiceDep, get_current_user from deerflow.domain.feedback import ( DuplicateFeedbackError, Feedback, @@ -109,10 +109,10 @@ async def upsert_feedback( run_id: str, body: RateRunRequest, request: Request, + service: FeedbackServiceDep, ) -> FeedbackResponse: """Set the current user's rating for a run (idempotent upsert).""" user_id = await get_current_user(request) - service = get_feedback_service(request) try: feedback = await service.rate_run(body.to_command(thread_id, run_id, user_id)) except InvalidRatingError: @@ -134,10 +134,10 @@ async def delete_run_feedback( thread_id: str, run_id: str, request: Request, + service: FeedbackServiceDep, ) -> dict[str, bool]: """Retract the current user's rating for a run.""" user_id = await get_current_user(request) - service = get_feedback_service(request) retracted = await service.retract_run_rating(RetractRunRating(thread_id=thread_id, run_id=run_id, user_id=user_id)) if not retracted: raise HTTPException(status_code=404, detail="No feedback found for this run")