Commit 09a35759 authored by Catalin Irimie's avatar Catalin Irimie

Update strategies used for DB count approximation for read-only DB

With the Tablesample and Reltuple strategies, they both attempt
transactions to stick to the primary DB when load-balancing is used,
which won't work with the loadbalancer enabled by default on read-only
databases (such as Geo), as there is no writeable primary DB.

Changelog: fixed
parent 54e1e329
...@@ -35,7 +35,17 @@ module Gitlab ...@@ -35,7 +35,17 @@ module Gitlab
# #
# @param [Array] # @param [Array]
# @return [Hash] of Model -> count mapping # @return [Hash] of Model -> count mapping
def self.approximate_counts(models, strategies: [TablesampleCountStrategy, ReltuplesCountStrategy, ExactCountStrategy]) def self.approximate_counts(models, strategies: [])
if strategies.empty?
# ExactCountStrategy is the only strategy working on read-only DBs, as others make
# use of tuple stats which use the primary DB to estimate tables size in a transaction.
strategies = if ::Gitlab::Database.read_write?
[TablesampleCountStrategy, ReltuplesCountStrategy, ExactCountStrategy]
else
[ExactCountStrategy]
end
end
strategies.each_with_object({}) do |strategy, counts_by_model| strategies.each_with_object({}) do |strategy, counts_by_model|
models_with_missing_counts = models - counts_by_model.keys models_with_missing_counts = models - counts_by_model.keys
......
...@@ -46,5 +46,49 @@ RSpec.describe Gitlab::Database::Count do ...@@ -46,5 +46,49 @@ RSpec.describe Gitlab::Database::Count do
subject subject
end end
end end
context 'default strategies' do
subject { described_class.approximate_counts(models) }
context 'with a read-only database' do
before do
allow(Gitlab::Database).to receive(:read_only?).and_return(true)
end
it 'only uses the ExactCountStrategy' do
allow_next_instance_of(Gitlab::Database::Count::TablesampleCountStrategy) do |instance|
expect(instance).not_to receive(:count)
end
allow_next_instance_of(Gitlab::Database::Count::ReltuplesCountStrategy) do |instance|
expect(instance).not_to receive(:count)
end
expect_next_instance_of(Gitlab::Database::Count::ExactCountStrategy) do |instance|
expect(instance).to receive(:count).and_return({})
end
subject
end
end
context 'with a read-write database' do
before do
allow(Gitlab::Database).to receive(:read_only?).and_return(false)
end
it 'uses the available strategies' do
[
Gitlab::Database::Count::TablesampleCountStrategy,
Gitlab::Database::Count::ReltuplesCountStrategy,
Gitlab::Database::Count::ExactCountStrategy
].each do |strategy_klass|
expect_next_instance_of(strategy_klass) do |instance|
expect(instance).to receive(:count).and_return({})
end
end
subject
end
end
end
end end
end end
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