Compute MR approver-id set once instead of per rule

What does this MR do and why?

On merge requests with many approval rules, the set of users who have approved was recalculated separately for every rule, issuing the same database query once per rule. This set is the same for all rules on a merge request.

This MR computes it once per merge request and reuses the result across all rules, removing the redundant per-rule queries.

Contributes to https://gitlab.com/gitlab-org/gitlab/-/issues/602716

Benchmark results

Measured on a local GDK against a synthetic project (spike-593394/codeowners-bench) with MRs of 100 / 400 / 800 code-owner rules. The benchmark exercises the model-layer widget read (approval_state aggregates + iterating wrapped_approval_rules and resolving approved? / approvals_required / approvals_left / invalid_rule?, which trigger overall_approver_ids), with reset_approval_cache! between iterations to mimic separate requests. "Without" is clean master; "With" is this MR.

Note: this MR isolates a single fix. Wall time is dominated by an unrelated per-rule CODEOWNERS re-parse (addressed in a separate MR), so the signal here is the query count, which becomes independent of rule count.

approvals.user_id pluck count (the targeted N+1)

Scenario Rules Without With
small 100 100 1
medium 400 400 1
large 800 800 1

The pluck is now flat (1) regardless of rule count — the N+1 is eliminated.

Total non-cached SQL queries (model widget read)

Scenario Rules Without With Reduction
small 100 205 106 −99
medium 400 805 406 −399
large 800 1606 807 −799

(The remaining per-rule protected_branches query is addressed in a separate MR; this change removes the approvals.user_id pluck N+1.)

How to set up and validate locally

  1. On a project with code_owner_approval_required = true and a large CODEOWNERS file, open a merge request that triggers many code-owner approval rules.
  2. Query approvalState { rules { approved approvalsRequired } } for that MR and observe the SQL query count (count of SELECT DISTINCT ... approvals.user_id).
  3. Run the model specs: bundle exec rspec ee/spec/models/approval_wrapped_rule_spec.rb (85 examples, 0 failures).

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