Preload the work item owner project for the flows list
What does this MR do and why?
The web Sessions list query (getUserAgentFlows) selects workItem { webUrl webPath } per flow. Building that URL loads the work item's owner project through a different path than the one the resolver already preloads, so it ran extra queries per project. This MR adds one preload path so those queries stay flat across pages.
Implementation details
The query lives in ee/app/assets/javascripts/ai/duo_agents_platform/graphql/queries/get_user_agent_flow.query.graphql. WorkItemPresenter#web_url builds the URL from work_item.namespace.owner_entity, the project loaded through the work item's ProjectNamespace. That is a different instance from work_item.project, which the resolver already preloads (from !255902 (merged)). For flows in distinct projects, that project and its namespace route loaded once per project.
The fix is one line in the preloads of ee/app/graphql/resolvers/ai/duo_workflows/workflows_resolver.rb: work_item: { namespace: { project: { namespace: :route } } }. LooksAhead only applies it when workItem is selected.
Measured locally with QueryRecorder, on flows linked to work items and merge requests, each in its own project, comparing a page of 2 to a page of 6: 3.5 extra queries per flow before this change, 2.0 after. The existing spec "batches the preloaded rows across flows in different projects" in ee/spec/requests/api/graphql/ai/duo_workflows/workflows_spec.rb now also compares projects and routes counts, and fails on master.
Remaining per-project queries
Two queries still grow per distinct project, and are out of scope for this MR:
- One
namespace_settingsquery from the cascadingduo_features_enabledread in the Duo policy (CascadingProjectSettingAttribute#locked_ancestor), shared withgetUserWorkflows. - One
work_item_custom_typesquery, becauseWorkItems::TypesFramework::Providercaches its type lookup per project namespace. This is intended, since visibility differs per project.
Both live in shared code outside this resolver.
References
- #629328 (closed) (GraphQL N+1 Triage: getUserAgentFlows)
- !255902 (merged) (earlier fix)
Screenshots or screen recordings
No UI change.
How to set up and validate locally
- On GDK, create flows linked to work items in three different projects. In the rails console:
Each project needs an issue.
user = User.find_by(username: 'root') Project.limit(3).each { |p| Ai::DuoWorkflows::Workflow.create!(user: user, project: p, goal: 'x', workflow_definition: 'software_development', work_item: p.issues.first) } - Open http://gdk.test:3000 and enable the performance bar (
pthenb). - Open the GitLab Duo side panel and switch to the Sessions list.
- Select the
getUserAgentFlowsrequest in the performance bar. On master, theroutesandprojectsquery counts grow by one per project. - On this branch, both counts stay flat, and each row still links its work item.
Also run:
bin/rspec ee/spec/requests/api/graphql/ai/duo_workflows/workflows_spec.rb -e 'the user flows list query'No new query plans are needed here. The added queries are preloader IN-list lookups by primary key (projects.project_namespace_id via has_one, namespaces.id, routes by source), the same shapes the resolver already runs.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.