diff options
Diffstat (limited to 'lib/gitlab/checks/matching_merge_request.rb')
-rw-r--r-- | lib/gitlab/checks/matching_merge_request.rb | 60 |
1 files changed, 56 insertions, 4 deletions
diff --git a/lib/gitlab/checks/matching_merge_request.rb b/lib/gitlab/checks/matching_merge_request.rb index 2635ad04770..e37cbc0442b 100644 --- a/lib/gitlab/checks/matching_merge_request.rb +++ b/lib/gitlab/checks/matching_merge_request.rb @@ -3,22 +3,74 @@ module Gitlab module Checks class MatchingMergeRequest + TOTAL_METRIC = :gitlab_merge_request_match_total + STALE_METRIC = :gitlab_merge_request_match_stale_secondary + def initialize(newrev, branch_name, project) @newrev = newrev @branch_name = branch_name @project = project end - # rubocop: disable CodeReuse/ActiveRecord def match? + if ::Gitlab::Database::LoadBalancing.enable? + # When a user merges a merge request, the following sequence happens: + # + # 1. Sidekiq: MergeService runs and updates the merge request in a locked state. + # 2. Gitaly: The UserMergeBranch RPC runs. + # 3. Gitaly (gitaly-ruby): This RPC calls the pre-receive hook. + # 4. Rails: This hook makes an API request to /api/v4/internal/allowed. + # 5. Rails: This API check does a SQL query for locked merge + # requests with a matching SHA. + # + # Since steps 1 and 5 will happen on different database + # sessions, replication lag could erroneously cause step 5 to + # report no matching merge requests. To avoid this, we check + # the write location to ensure the replica can make this query. + track_session_metrics do + ::Gitlab::Database::LoadBalancing::Sticking.select_valid_host(:project, @project.id) + end + end + + # rubocop: disable CodeReuse/ActiveRecord @project.merge_requests .with_state(:locked) .where(in_progress_merge_commit_sha: @newrev, target_branch: @branch_name) .exists? + # rubocop: enable CodeReuse/ActiveRecord + end + + private + + def track_session_metrics + before = ::Gitlab::Database::LoadBalancing::Session.current.use_primary? + + yield + + after = ::Gitlab::Database::LoadBalancing::Session.current.use_primary? + + increment_attempt_count + + if !before && after + increment_stale_secondary_count + end + end + + def increment_attempt_count + total_counter.increment + end + + def increment_stale_secondary_count + stale_counter.increment + end + + def total_counter + @total_counter ||= ::Gitlab::Metrics.counter(TOTAL_METRIC, 'Total number of merge request match attempts') + end + + def stale_counter + @stale_counter ||= ::Gitlab::Metrics.counter(STALE_METRIC, 'Total number of merge request match attempts with lagging secondary') end - # rubocop: enable CodeReuse/ActiveRecord end end end - -Gitlab::Checks::MatchingMergeRequest.prepend_mod_with('Gitlab::Checks::MatchingMergeRequest') |