From 33645a63ab7c01275df45695cd44f59db137b3e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Bournhonesque?= Date: Fri, 6 Dec 2024 15:16:45 +0100 Subject: [PATCH] fix: support votes on GET /api/v1/insights route (#1488) --- robotoff/app/api.py | 27 +++++++++++++++++++-------- robotoff/app/core.py | 2 ++ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/robotoff/app/api.py b/robotoff/app/api.py index de16154c31..d6952d8c99 100644 --- a/robotoff/app/api.py +++ b/robotoff/app/api.py @@ -134,15 +134,19 @@ def get_countries_from_req(req: falcon.Request) -> Optional[list[Country]]: ) -def _get_skip_voted_on( - auth: Optional[OFFAuthentication], device_id: str -) -> SkipVotedOn: - """Helper function for constructing SkipVotedOn objects based on request - params.""" +def _get_skip_voted_on(auth: OFFAuthentication | None, device_id: str) -> SkipVotedOn: + """Create a SkipVotedOn object based on request params. + This object is used to determine if the user has already voted on the insight. + + If the user is not authenticated, the device_id (either an ID sent by the client or + the IP address as fallback) is used. + + If the user is authenticated, the username is used. + """ if not auth: return SkipVotedOn(SkipVotedType.DEVICE_ID, device_id) - username: Optional[str] = auth.get_username() + username: str | None = auth.get_username() if not username: return SkipVotedOn(SkipVotedType.DEVICE_ID, device_id) @@ -225,6 +229,12 @@ def on_get(self, req: falcon.Request, resp: falcon.Response): # Limit the number of brands to prevent slow SQL queries brands = brands[:10] + device_id = device_id_from_request(req) + auth: OFFAuthentication | None = parse_auth(req) + avoid_voted_on = _get_skip_voted_on(auth, device_id) + # Counting the number of insights that match the vote + # criteria can be very costly, so we limit the count to 100 + max_count = 100 get_insights_ = functools.partial( get_insights, server_type=server_type, @@ -238,6 +248,8 @@ def on_get(self, req: falcon.Request, resp: falcon.Response): predictor=predictor, order_by=order_by, campaigns=campaigns, + avoid_voted_on=avoid_voted_on, + max_count=max_count, ) offset: int = (page - 1) * count @@ -1476,8 +1488,7 @@ def get_questions_resource_on_get( avoid_voted_on = _get_skip_voted_on(auth, device_id) # Counting the number of insights that match the vote # criteria can be very costly, so we limit the count to 100 - # if avoid_voted_on is not None - max_count = 100 if avoid_voted_on is not None else None + max_count = 100 get_insights_ = functools.partial( get_insights, server_type=server_type, diff --git a/robotoff/app/core.py b/robotoff/app/core.py index 344aff94e6..6a8c611bd2 100644 --- a/robotoff/app/core.py +++ b/robotoff/app/core.py @@ -121,6 +121,8 @@ def get_insights( defaults to None. If provided, the count will be limited to this value. It allows to dramatically speed up the count query. If not provided, an exact count will be returned. + :param max_count: an upper bound on the number of insights to return when + asking for the count (`count=True`), defaults to None (no limit). :param avoid_voted_on: a SkipVotedOn used to remove results insights the user previously ignored, defaults to None :param group_by_value_tag: if True, group results by value_tag, defaults