Add a method to retrieve projects when selective sync is enabled

This method allow us to enable selective sync support for the
FDW queries.
parent feed78d6
...@@ -14,6 +14,18 @@ module Geo ...@@ -14,6 +14,18 @@ module Geo
has_many :geo_node_namespace_links, class_name: 'Geo::Fdw::GeoNodeNamespaceLink' has_many :geo_node_namespace_links, class_name: 'Geo::Fdw::GeoNodeNamespaceLink'
has_many :namespaces, class_name: 'Geo::Fdw::Namespace', through: :geo_node_namespace_links has_many :namespaces, class_name: 'Geo::Fdw::Namespace', through: :geo_node_namespace_links
def projects
return Geo::Fdw::Project.all unless selective_sync?
if selective_sync_by_namespaces?
projects_for_selected_namespaces
elsif selective_sync_by_shards?
projects_for_selected_shards
else
Geo::Fdw::Project.none
end
end
def project_registries def project_registries
return Geo::ProjectRegistry.all unless selective_sync? return Geo::ProjectRegistry.all unless selective_sync?
...@@ -28,11 +40,25 @@ module Geo ...@@ -28,11 +40,25 @@ module Geo
private private
def projects_for_selected_namespaces
Geo::Fdw::Project
.within_namespaces(selected_namespaces_and_descendants.select(:id))
end
def projects_for_selected_shards
Geo::Fdw::Project.within_shards(selective_sync_shards)
end
def registries_for_selected_namespaces def registries_for_selected_namespaces
Gitlab::Geo::Fdw::ProjectRegistryQueryBuilder.new Gitlab::Geo::Fdw::ProjectRegistryQueryBuilder.new
.within_namespaces(selected_namespaces_and_descendants.select(:id)) .within_namespaces(selected_namespaces_and_descendants.select(:id))
end end
def registries_for_selected_shards
Gitlab::Geo::Fdw::ProjectRegistryQueryBuilder.new
.within_shards(selective_sync_shards)
end
def selected_namespaces_and_descendants def selected_namespaces_and_descendants
relation = selected_namespaces_and_descendants_cte.apply_to(Geo::Fdw::Namespace.all) relation = selected_namespaces_and_descendants_cte.apply_to(Geo::Fdw::Namespace.all)
relation.extend(Gitlab::Database::ReadOnlyRelation) relation.extend(Gitlab::Database::ReadOnlyRelation)
...@@ -56,11 +82,6 @@ module Geo ...@@ -56,11 +82,6 @@ module Geo
cte cte
end end
def registries_for_selected_shards
Gitlab::Geo::Fdw::ProjectRegistryQueryBuilder.new
.within_shards(selective_sync_shards)
end
def fdw_namespaces_table def fdw_namespaces_table
Geo::Fdw::Namespace.arel_table Geo::Fdw::Namespace.arel_table
end end
......
...@@ -8,6 +8,46 @@ RSpec.describe Geo::Fdw::GeoNode, :geo, type: :model do ...@@ -8,6 +8,46 @@ RSpec.describe Geo::Fdw::GeoNode, :geo, type: :model do
it { is_expected.to have_many(:namespaces).class_name('Geo::Fdw::Namespace').through(:geo_node_namespace_links) } it { is_expected.to have_many(:namespaces).class_name('Geo::Fdw::Namespace').through(:geo_node_namespace_links) }
end end
# Disable transactions via :delete method because a foreign table
# can't see changes inside a transaction of a different connection.
describe '#projects', :delete do
before do
skip('FDW is not configured') unless Gitlab::Geo::Fdw.enabled?
end
let(:node) { create(:geo_node) }
let(:group_1) { create(:group) }
let(:group_2) { create(:group) }
let(:nested_group_1) { create(:group, parent: group_1) }
let(:project_1) { create(:project, group: group_1) }
let(:project_2) { create(:project, group: nested_group_1) }
let(:project_3) { create(:project, :broken_storage, group: group_2) }
subject { described_class.find(node.id) }
it 'returns all registries without selective sync' do
expect(subject.projects).to match_ids(project_1, project_2, project_3)
end
it 'returns projects that belong to the namespaces with selective sync by namespace' do
node.update!(selective_sync_type: 'namespaces', namespaces: [group_1])
expect(subject.projects).to match_ids(project_1, project_2)
end
it 'returns projects that belong to the shards with selective sync by shard' do
node.update!(selective_sync_type: 'shards', selective_sync_shards: %w[broken])
expect(subject.projects).to match_ids(project_3)
end
it 'returns nothing if an unrecognised selective sync type is used' do
node.update_attribute(:selective_sync_type, 'unknown')
expect(subject.projects).to be_empty
end
end
# Disable transactions via :delete method because a foreign table # Disable transactions via :delete method because a foreign table
# can't see changes inside a transaction of a different connection. # can't see changes inside a transaction of a different connection.
describe '#project_registries', :delete do describe '#project_registries', :delete do
...@@ -33,15 +73,15 @@ RSpec.describe Geo::Fdw::GeoNode, :geo, type: :model do ...@@ -33,15 +73,15 @@ RSpec.describe Geo::Fdw::GeoNode, :geo, type: :model do
end end
it 'returns registries where projects belong to the namespaces with selective sync by namespace' do it 'returns registries where projects belong to the namespaces with selective sync by namespace' do
node.update!(selective_sync_type: 'namespaces', namespaces: [group_1, nested_group_1]) node.update!(selective_sync_type: 'namespaces', namespaces: [group_1])
expect(subject.project_registries).to match_array([registry_1, registry_2]) expect(subject.project_registries).to match_array([registry_1, registry_2])
end end
it 'returns registries where projects belong to the shards with selective sync by shard' do it 'returns registries where projects belong to the shards with selective sync by shard' do
node.update!(selective_sync_type: 'shards', selective_sync_shards: %w[default bar]) node.update!(selective_sync_type: 'shards', selective_sync_shards: %w[broken])
expect(subject.project_registries).to match_array([registry_1, registry_2]) expect(subject.project_registries).to match_array([registry_3])
end end
it 'returns nothing if an unrecognised selective sync type is used' do it 'returns nothing if an unrecognised selective sync type is used' do
......
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