Batch update merge_status during refresh_service
What does this MR do and why?
When pushing to a repository, the MergeRequests::RefreshService needs to update the merge_status of all affected merge requests. Currently, this is done via individual mark_as_unchecked calls on each MR which could potentially be thousands of MRs on busy project. Also, since it's possible that it may have to process many merge requests so we're processing 1000 at a time.
While it's not ideal we are by passing the state machine, but I think gain outweighs potential issues. It's gated by batch_merge_status_updates feature flag.
This would likely reduce the number of merge_status update queries significantly and will contribute towards lowering WAL rate generation coming from this query.
References
How to set up and validate locally
- Create several merge requests on a project
- Grep logs to see
merge_statusupdate queries.tail -f log/development.log | grep 'UPDATE "merge_requests" SET "merge_status" =' - Ensure that all merge requests are not in
uncheckedstatusproject = Project.find(YOUR_PROJECT_ID) project.merge_requests.opened.each {|mr| mr.check_mergeability} # Verify the status by examining the `merge_status` of each merge requests project.merge_requests.opened.map {|a| a.reload; p [a.id, a.merge_status, a.title]} - Make a direct code change to the target branch via UI or console and push it up.
- Observe several
merge_statusupdate calls firing vi the log above - Now, In rails console enable the feature flag
Feature.enable(:batch_merge_status_updates) - Follow the same steps as above and observe there are now only 2 batched update queries for new commit to the target branch.
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.
Related to #546431