Reduce work items list query complexity for anonymous users

What does this MR do and why?

This MR brings the work items list query (specifically getWorkItemsFullEE) under the unauthenticated complexity limit, this is a follow-up of !253748 (merged).

Problem

We have following query complexity limits in place for various user types:

  • root - 300
  • Regular users - 250
  • Anonymous users - 200

With work_item_features_field enabled globally, if an anonymous user would visit a work items list, it would open fine as long as page size is 20 or 50, but the moment they go to page size 100, the getWorkItemsFullEE query would fail as the total complexity of that query became 240, thus breaching the limit of 200 for anonymous users. The listing page still loaded and showed work items, but it missed the additional metadata that is fetched via getWorkItemsFullEE and user would see a failure banner on the page. For logged in users, this never became an issue as query stayed under 250.

Fix

Work Items list currently fires two queries in parallel; getWorkItemsSlimEE and getWorkItemsFullEE, and we were duplicating the fields in full query, even the ones that we already fetched in slim query, in this MR, we've removed those duplicates, resulting in much smaller complexity. And this is fine because Apollo would merge the results when queries are complete so no fields are lost.

Implementation notes

  • Deduplicated get_work_items_full.query.graphql (CE and EE) so it no longer includes fields like iid, author, createdAt, and webUrl that get_work_items_slim.query.graphql already fetches; this is the change that brings the query under the complexity cap.
  • Updated combineWorkItemLists in app/assets/javascripts/work_items/utils.js to spread the slim item response on top of full item.
  • Added the missing @skip(if: $useWorkItemFeatures) directive to the EE slim query's widgets(onlyTypes: [LABELS]) selection, matching CE, since without it EE was loading labels twice on both widgets[] and features sub-trees.
  • Fixed three MSW test suites that assumed slim's fields were a subset of full's: views_spec.js and preferences_spec.js now look up work items by title in the slim fixture instead of full, and we added a real get_work_items_slim_closed fixture instead of aliasing the full closed one.
  • Extended ee/spec/graphql/all_queries_spec.rb to assert the unauthenticated 200-point cap at page sizes 20, 50 and 100, since page size 100 previously only checked the authenticated 250 cap, which is how this complexity breach reached production.
    • The complexity_overrides entries of 360 for both list queries were removed.

Here are updated numbers for complexity

Page size full before full after slim before slim after
20 145 111 68 66
50 180 138 84 82
100 240 183 141 109

183 against a 200 cap for anonymous users

References

Screenshots or screen recordings

Group work items list at ?first_page_size=100, logged out, work_item_features_field enabled.

Before After

How to set up and validate locally

  1. Enable the flag with Feature.enable(:work_item_features_field).
  2. Open a group work items list with ?first_page_size=100 in a logged-out session, for example http://gdk.test:3000/groups/gitlab-org/-/work_items?first_page_size=100.
  3. Confirm the list renders with no error banner and that getWorkItemsFullEE returns no complexity error.
  4. Confirm the cards still show assignees, labels, milestone, iteration, dates, weight, health status, status, comment counts and upvotes.
  5. Repeat signed in as a regular user and as an admin.
  6. Repeat with the flag disabled to check the widgets path still renders the same cards.

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.

Edited by Kushal Pandya

Merge request reports

Loading
Loading