Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/database/load_balancing/load_balancer.rb')
-rw-r--r--lib/gitlab/database/load_balancing/load_balancer.rb30
1 files changed, 25 insertions, 5 deletions
diff --git a/lib/gitlab/database/load_balancing/load_balancer.rb b/lib/gitlab/database/load_balancing/load_balancer.rb
index f6144b7b772..9495648d069 100644
--- a/lib/gitlab/database/load_balancing/load_balancer.rb
+++ b/lib/gitlab/database/load_balancing/load_balancer.rb
@@ -8,6 +8,10 @@ module Gitlab
# Each host in the load balancer uses the same credentials as the primary
# database.
class LoadBalancer
+ ANY_CAUGHT_UP = :any
+ ALL_CAUGHT_UP = :all
+ NONE_CAUGHT_UP = :none
+
CACHE_KEY = :gitlab_load_balancer_host
REPLICA_SUFFIX = '_replica'
@@ -178,16 +182,32 @@ module Gitlab
raise 'Failed to determine the write location of the primary database'
end
- # Returns true if there was at least one host that has caught up with the given transaction.
+ # Finds any up to date replica for the given LSN location and stores an up to date replica in the
+ # SafeRequestStore to be used later for read-only queries. It returns a symbol to indicate if :any, :all or
+ # :none were found to be caught up.
def select_up_to_date_host(location)
all_hosts = @host_list.hosts.shuffle
- host = all_hosts.find { |host| host.caught_up?(location) }
+ first_caught_up_host = nil
+
+ # We must loop through all of them so that we know if all are caught up. Some callers only care about finding
+ # one caught up host and storing it in request_cache. But Sticking needs to know if ALL_CAUGHT_UP so that it
+ # can clear the LSN position from Redis and not ask again in future.
+ results = all_hosts.map do |host|
+ caught_up = host.caught_up?(location)
+ first_caught_up_host ||= host if caught_up
+ caught_up
+ end
+
+ ActiveSupport::Notifications.instrument(
+ 'caught_up_replica_pick.load_balancing',
+ { result: first_caught_up_host.present? }
+ )
- return false unless host
+ return NONE_CAUGHT_UP unless first_caught_up_host
- request_cache[CACHE_KEY] = host
+ request_cache[CACHE_KEY] = first_caught_up_host
- true
+ results.all? ? ALL_CAUGHT_UP : ANY_CAUGHT_UP
end
# Yields a block, retrying it upon error using an exponential backoff.