diff options
Diffstat (limited to 'lib/gitlab/database/load_balancing/load_balancer.rb')
-rw-r--r-- | lib/gitlab/database/load_balancing/load_balancer.rb | 30 |
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. |