Avoid unbounded preload in any_merge_request rules sync
What does this MR do and why?
SyncAnyMergeRequestRulesService preloaded approval_merge_request_rules through approval_policy_rule (preload(approval_policy_rule: :approval_merge_request_rules)).
That association is keyed by approval_policy_rule_id. A single approval policy rule can be linked to thousands of projects, each with hundreds of merge requests, and every one of those merge requests gets an ApprovalMergeRequestRule row referencing the same approval_policy_rule_id. As a result the preload eagerly loaded every approval rule across the whole instance for the policy, which caused timeouts.
The preloaded collection was only used in policy_affected_by_target_branch? to short-circuit the target-branch check by asking whether the policy already had approval rules. That question only needs this merge request's rules, which are already loaded via any_merge_request_rules. We now reuse them through the existing (feature-flag-aware) approval_rules_for_policies matcher and drop the unbounded preloads.
This is also semantically tighter: the check is meant to detect rules that were already created and filtered for this merge request's target branch.
Failures in logs
SyncAnyMergeRequestApprovalRulesWorker is failing in production with ActiveRecord::QueryCanceled (PG::QueryCanceled: canceling statement due to statement timeout). The worker runs on merge request creation (NewMergeRequestWorker → Projects::MergeRequests::CreationsController#create) and spends ~15s entirely in the canceled statement, which is the unbounded preload originating from related_approval_policy_sources:
SELECT "approval_merge_request_rules".*
FROM "approval_merge_request_rules"
WHERE "approval_merge_request_rules"."approval_policy_rule_id" IN ($1, $2, $3, $4)Note the IN clause has only a handful of policy-rule IDs — the timeout comes from the result-set size (one row per merge request, across every linked project), not the number of policy rules.
Logs: https://log.gprd.gitlab.net/app/r/s/npl5i
Changes
- Replace the global
policy.approval_merge_request_rules.any?short-circuit with an MR-scoped check againstany_merge_request_rules. - Remove the
including_approval_merge_request_rulesandpreload_approval_policy_rule_with_merge_request_rulesscopes from the query (only used here), keeping a leanpreload_approval_policy_rule.