Commit b7eea1bb authored by Stan Hu's avatar Stan Hu

Merge branch '326125-improve-load-balancer-all-caught-up' into 'master'

Improve LoadBalancer#all_caught_up? logic [RUN ALL RSPEC] [RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!65248
parents 55822d83 c5dd0858
---
name: load_balancing_improved_caught_up_hosts_check
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65248
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/334989
milestone: '14.1'
type: development
group: group::memory
default_enabled: false
...@@ -147,15 +147,24 @@ module Gitlab ...@@ -147,15 +147,24 @@ module Gitlab
raise 'Failed to determine the write location of the primary database' raise 'Failed to determine the write location of the primary database'
end end
# Returns true if all hosts have caught up to the given transaction # FF disabled: Returns true if all hosts have caught up to the given transaction write location.
# write location. # FF enabled: Returns true if there was at least one host that has caught up with the given transaction and sets it.
def all_caught_up?(location) def all_caught_up?(location)
@host_list.hosts.all? { |host| host.caught_up?(location) } if ::Feature.enabled?(:load_balancing_improved_caught_up_hosts_check)
select_up_to_date_host(location)
else
@host_list.hosts.all? { |host| host.caught_up?(location) }
end
end end
# Returns true if there was at least one host that has caught up with the given transaction. # Returns true if there was at least one host that has caught up with the given transaction.
# #
# In case of a retry, this method also stores the set of hosts that have caught up. # In case of a retry, this method also stores the set of hosts that have caught up.
#
# UPD: `select_caught_up_hosts` seems to have redundant logic managing host list (`:gitlab_load_balancer_valid_hosts`),
# while we only need a single host: https://gitlab.com/gitlab-org/gitlab/-/issues/326125#note_615271604
# Also, shuffling the list afterwards doesn't seem to be necessary.
# This may be improved by merging this method with `select_up_to_date_host`.
def select_caught_up_hosts(location) def select_caught_up_hosts(location)
all_hosts = @host_list.hosts all_hosts = @host_list.hosts
valid_hosts = all_hosts.select { |host| host.caught_up?(location) } valid_hosts = all_hosts.select { |host| host.caught_up?(location) }
...@@ -179,6 +188,8 @@ module Gitlab ...@@ -179,6 +188,8 @@ module Gitlab
# Returns true if there was at least one host that has caught up with the given transaction. # Returns true if there was at least one host that has caught up with the given transaction.
# Similar to `#select_caught_up_hosts`, picks a random host, to rotate replicas we use. # Similar to `#select_caught_up_hosts`, picks a random host, to rotate replicas we use.
# Unlike `#select_caught_up_hosts`, does not iterate over all hosts if finds any. # Unlike `#select_caught_up_hosts`, does not iterate over all hosts if finds any.
#
# It is going to be merged with `select_caught_up_hosts`, because they intend to do the same.
def select_up_to_date_host(location) def select_up_to_date_host(location)
all_hosts = @host_list.hosts.shuffle all_hosts = @host_list.hosts.shuffle
host = all_hosts.find { |host| host.caught_up?(location) } host = all_hosts.find { |host| host.caught_up?(location) }
......
...@@ -307,22 +307,34 @@ RSpec.describe Gitlab::Database::LoadBalancing::LoadBalancer, :request_store do ...@@ -307,22 +307,34 @@ RSpec.describe Gitlab::Database::LoadBalancing::LoadBalancer, :request_store do
end end
describe '#all_caught_up?' do describe '#all_caught_up?' do
it 'returns true if all hosts caught up to the write location' do it 'delegates execution to #select_up_to_date_host' do
expect(lb.host_list.hosts).to all(receive(:caught_up?).with('foo').and_return(true)) expect(lb).to receive(:select_up_to_date_host).with('foo').and_return(true)
expect(lb.all_caught_up?('foo')).to eq(true) expect(lb.all_caught_up?('foo')).to eq(true)
end end
it 'returns false if a host has not yet caught up' do context 'when :load_balancing_improved_caught_up_hosts_check FF is disabled' do
expect(lb.host_list.hosts[0]).to receive(:caught_up?) before do
.with('foo') stub_feature_flags(load_balancing_improved_caught_up_hosts_check: false)
.and_return(true) end
it 'returns true if all hosts caught up to the write location' do
expect(lb.host_list.hosts).to all(receive(:caught_up?).with('foo').and_return(true))
expect(lb.all_caught_up?('foo')).to eq(true)
end
it 'returns false if a host has not yet caught up' do
expect(lb.host_list.hosts[0]).to receive(:caught_up?)
.with('foo')
.and_return(true)
expect(lb.host_list.hosts[1]).to receive(:caught_up?) expect(lb.host_list.hosts[1]).to receive(:caught_up?)
.with('foo') .with('foo')
.and_return(false) .and_return(false)
expect(lb.all_caught_up?('foo')).to eq(false) expect(lb.all_caught_up?('foo')).to eq(false)
end
end end
end end
...@@ -488,7 +500,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::LoadBalancer, :request_store do ...@@ -488,7 +500,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::LoadBalancer, :request_store do
end end
end end
describe '#select_caught_up_hosts' do describe '#select_up_to_date_host' do
let(:location) { 'AB/12345'} let(:location) { 'AB/12345'}
let(:hosts) { lb.host_list.hosts } let(:hosts) { lb.host_list.hosts }
let(:set_host) { RequestStore[described_class::CACHE_KEY] } let(:set_host) { RequestStore[described_class::CACHE_KEY] }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment