diff --git a/ayon_api/graphql.py b/ayon_api/graphql.py index af0662a97..c35b6c363 100644 --- a/ayon_api/graphql.py +++ b/ayon_api/graphql.py @@ -867,6 +867,9 @@ def reset_cursor(self) -> None: # Reset cursor only for edges self._cursor = None self._need_query = True + # Limit of a nested edge field is counted per parent item, so the + # counter must be reset when parent item changes. + self._fetched_counter = 0 super().reset_cursor() @@ -974,7 +977,9 @@ def get_filters(self) -> dict[str, Any]: # overwritten by another parent from the same outer page. limit_amount = 1 - filters[limit_key] = limit_amount + # Never ask for less than a single item, pagination is stopped + # using 'need_query' when the limit is reached + filters[limit_key] = max(limit_amount, 1) if self._cursor: cursor_key = ( diff --git a/tests/test_graphql_nested_limit.py b/tests/test_graphql_nested_limit.py new file mode 100644 index 000000000..afe60d81c --- /dev/null +++ b/tests/test_graphql_nested_limit.py @@ -0,0 +1,26 @@ +"""Limit of nested edge field is applied per parent item. + +Does not require running AYON server. +""" +from ayon_api.graphql_queries import versions_graphql_query + +from .graphql_fake_server import FakeServer + + +def test_nested_field_limit_is_per_parent(): + data = {"project": {"name": "proj", "versions": [ + {"id": f"v{idx}", "links": [{"id": f"v{idx}-l{n}"} for n in range(5)]} + for idx in range(3) + ]}} + query = versions_graphql_query({"id", "links.id"}) + query.set_variable_value("projectName", "proj") + query.get_field_by_path("project/versions/links").set_limit(2) + server = FakeServer(data) + + output = query.query(server) + + for version in output["project"]["versions"]: + assert len(version["links"]) == 2 + for query_str in server.queries: + assert "first: 0" not in query_str + assert "first: -" not in query_str