GET /groups/:id/releases runs queries per release because GroupReleasesFinder discards the preloaded relation

Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.

Summary

Releases::GroupReleasesFinder#execute calls releases.preloaded if preload and drops the relation that call returns (group_releases_finder.rb#L26), so Release.preloaded (release.rb#L51) never applies. The project-level finder assigns it (releases_finder.rb#L25).

GET /groups/:id/releases asks the finder to preload (releases.rb#L452-456), and then loads the author, links, evidences, milestones and project of each release with queries of its own. The GraphQL group releases resolver calls the same finder with its default preload: true.

The call that drops the result came in with !83295 (merged), a refactor of this finder.

Two specs should have caught it and could not:

  • The request spec "include_subgroups avoids N+1 queries" (releases_spec.rb#L1978-1995) requests an empty group while it creates the new releases under group1, and it calls a memoized subject, so only its first request is ever sent.
  • The finder spec (group_releases_finder_spec.rb#L43) checks that Release.preloaded is called, which a scope called on a relation always does, not that the result is used.

Steps to reproduce

  1. In a group, create a project with one release.
  2. Request GET /groups/:id/releases and count the SQL queries (for example with ActiveRecord::QueryRecorder in a request spec).
  3. Add three more releases to the same project, with different authors, and request the list again.

Example Project

Not needed: the count is not visible through the API. The request spec in the linked merge request reproduces it.

What is the current bug behavior?

On master at 797e8e3c, the corrected request spec from the merge request measures 46 queries for one release and 73 for four: about nine more queries for every release in the response.

What is the expected correct behavior?

The number of queries does not grow with the number of releases on the page, as for GET /projects/:id/releases.

Relevant logs and/or screenshots

Failure/Error:
  Expected a maximum of 46 queries, got 73:

Output of checks

Found by reading the code while working on gitlab-mcp-server, which calls this endpoint, and measured on master with the corrected specs from the merge request. Not checked on GitLab.com, where the query count is not visible.

Possible fixes

Assign the relation, as ReleasesFinder does:

-      releases.preloaded if preload
+      releases = releases.preloaded if preload

I have a merge request ready with the fix and with both specs corrected.

Edited by 🤖 GitLab Bot 🤖