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_settings query from the cascading duo_features_enabled read in the Duo policy (CascadingProjectSettingAttribute#locked_ancestor), shared with getUserWorkflows.
  • One work_item_custom_types query, because WorkItems::TypesFramework::Provider caches its type lookup per project namespace. This is intended, since visibility differs per project.

Both live in shared code outside this resolver.

References

Screenshots or screen recordings

No UI change.

How to set up and validate locally

  1. On GDK, create flows linked to work items in three different projects. In the rails console:
    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) }
    Each project needs an issue.
  2. Open http://gdk.test:3000 and enable the performance bar (p then b).
  3. Open the GitLab Duo side panel and switch to the Sessions list.
  4. Select the getUserAgentFlows request in the performance bar. On master, the routes and projects query counts grow by one per project.
  5. 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.

Merge request reports

Loading
Loading