Commit b63f476d authored by Francisco Javier López's avatar Francisco Javier López Committed by Douglas Barbosa Alexandre

Include group wikis in Geo replication

In this commit, we add the logic to include group wikis in Geo
replication.
parent 50aa76a5
...@@ -20,6 +20,7 @@ ActiveSupport::Inflector.inflections do |inflect| ...@@ -20,6 +20,7 @@ ActiveSupport::Inflector.inflections do |inflect|
event_log event_log
file_registry file_registry
group_view group_view
group_wiki_repository_registry
job_artifact_registry job_artifact_registry
lfs_object_registry lfs_object_registry
package_file_registry package_file_registry
......
...@@ -217,6 +217,12 @@ configuration option in `gitlab.yml`. These metrics are served from the ...@@ -217,6 +217,12 @@ configuration option in `gitlab.yml`. These metrics are served from the
| `geo_snippet_repositories_synced` | Gauge | 13.4 | Number of syncable snippets synced on secondary | `url` | | `geo_snippet_repositories_synced` | Gauge | 13.4 | Number of syncable snippets synced on secondary | `url` |
| `geo_snippet_repositories_failed` | Gauge | 13.4 | Number of syncable snippets failed on secondary | `url` | | `geo_snippet_repositories_failed` | Gauge | 13.4 | Number of syncable snippets failed on secondary | `url` |
| `geo_snippet_repositories_registry` | Gauge | 13.4 | Number of syncable snippets in the registry | `url` | | `geo_snippet_repositories_registry` | Gauge | 13.4 | Number of syncable snippets in the registry | `url` |
| `geo_group_wiki_repositories` | Gauge | 13.10 | Number of group wikis on primary | `url` |
| `geo_group_wiki_repositories_checksummed` | Gauge | 13.10 | Number of group wikis checksummed on primary | `url` |
| `geo_group_wiki_repositories_checksum_failed` | Gauge | 13.10 | Number of group wikis failed to calculate the checksum on primary | `url` |
| `geo_group_wiki_repositories_synced` | Gauge | 13.10 | Number of syncable group wikis synced on secondary | `url` |
| `geo_group_wiki_repositories_failed` | Gauge | 13.10 | Number of syncable group wikis failed on secondary | `url` |
| `geo_group_wiki_repositories_registry` | Gauge | 13.10 | Number of syncable group wikis in the registry | `url` |
| `limited_capacity_worker_running_jobs` | Gauge | 13.5 | Number of running jobs | `worker` | | `limited_capacity_worker_running_jobs` | Gauge | 13.5 | Number of running jobs | `worker` |
| `limited_capacity_worker_max_running_jobs` | Gauge | 13.5 | Maximum number of running jobs | `worker` | | `limited_capacity_worker_max_running_jobs` | Gauge | 13.5 | Maximum number of running jobs | `worker` |
| `limited_capacity_worker_remaining_work_count` | Gauge | 13.5 | Number of jobs waiting to be enqueued | `worker` | | `limited_capacity_worker_remaining_work_count` | Gauge | 13.5 | Number of jobs waiting to be enqueued | `worker` |
......
...@@ -383,7 +383,12 @@ Example response: ...@@ -383,7 +383,12 @@ Example response:
"snippet_repositories_checksum_failed_count": 0, "snippet_repositories_checksum_failed_count": 0,
"snippet_repositories_registry_count": 10, "snippet_repositories_registry_count": 10,
"snippet_repositories_synced_count": 6, "snippet_repositories_synced_count": 6,
"snippet_repositories_failed_count": 3 "snippet_repositories_failed_count": 3,
"group_wiki_repositories_checksummed_count": 10,
"group_wiki_repositories_checksum_failed_count": 0,
"group_wiki_repositories_registry_count": 10,
"group_wiki_repositories_synced_count": 6,
"group_wiki_repositories_failed_count": 3
}, },
{ {
"geo_node_id": 2, "geo_node_id": 2,
...@@ -477,7 +482,12 @@ Example response: ...@@ -477,7 +482,12 @@ Example response:
"snippet_repositories_checksum_failed_count": 0, "snippet_repositories_checksum_failed_count": 0,
"snippet_repositories_registry_count": 10, "snippet_repositories_registry_count": 10,
"snippet_repositories_synced_count": 6, "snippet_repositories_synced_count": 6,
"snippet_repositories_failed_count": 3 "snippet_repositories_failed_count": 3,
"group_wiki_repositories_checksummed_count": 10,
"group_wiki_repositories_checksum_failed_count": 0,
"group_wiki_repositories_registry_count": 10,
"group_wiki_repositories_synced_count": 6,
"group_wiki_repositories_failed_count": 3
} }
] ]
``` ```
......
...@@ -2139,6 +2139,7 @@ Represents an external issue. ...@@ -2139,6 +2139,7 @@ Represents an external issue.
| `containerRepositoriesMaxCapacity` | Int | The maximum concurrency of container repository sync for this secondary node. | | `containerRepositoriesMaxCapacity` | Int | The maximum concurrency of container repository sync for this secondary node. |
| `enabled` | Boolean | Indicates whether this Geo node is enabled. | | `enabled` | Boolean | Indicates whether this Geo node is enabled. |
| `filesMaxCapacity` | Int | The maximum concurrency of LFS/attachment backfill for this secondary node. | | `filesMaxCapacity` | Int | The maximum concurrency of LFS/attachment backfill for this secondary node. |
| `groupWikiRepositoryRegistries` | GroupWikiRepositoryRegistryConnection | Find group wiki repository registries on this Geo node. Available only when feature flag `geo_group_wiki_repository_replication` is enabled. |
| `id` | ID! | ID of this GeoNode. | | `id` | ID! | ID of this GeoNode. |
| `internalUrl` | String | The URL defined on the primary node that secondary nodes should use to contact it. | | `internalUrl` | String | The URL defined on the primary node that secondary nodes should use to contact it. |
| `mergeRequestDiffRegistries` | MergeRequestDiffRegistryConnection | Find merge request diff registries on this Geo node. | | `mergeRequestDiffRegistries` | MergeRequestDiffRegistryConnection | Find merge request diff registries on this Geo node. |
...@@ -2282,6 +2283,21 @@ Contains statistics about a group. ...@@ -2282,6 +2283,21 @@ Contains statistics about a group.
| ----- | ---- | ----------- | | ----- | ---- | ----------- |
| `releaseStats` | GroupReleaseStats | Statistics related to releases within the group. | | `releaseStats` | GroupReleaseStats | Statistics related to releases within the group. |
### `GroupWikiRepositoryRegistry`
Represents the Geo sync and verification state of a group wiki repository.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `createdAt` | Time | Timestamp when the GroupWikiRepositoryRegistry was created |
| `groupWikiRepositoryId` | ID! | ID of the Group Wiki Repository. |
| `id` | ID! | ID of the GroupWikiRepositoryRegistry |
| `lastSyncFailure` | String | Error message during sync of the GroupWikiRepositoryRegistry |
| `lastSyncedAt` | Time | Timestamp of the most recent successful sync of the GroupWikiRepositoryRegistry |
| `retryAt` | Time | Timestamp after which the GroupWikiRepositoryRegistry should be resynced |
| `retryCount` | Int | Number of consecutive failed sync attempts of the GroupWikiRepositoryRegistry |
| `state` | RegistryState | Sync state of the GroupWikiRepositoryRegistry |
### `HttpIntegrationCreatePayload` ### `HttpIntegrationCreatePayload`
Autogenerated return type of HttpIntegrationCreate. Autogenerated return type of HttpIntegrationCreate.
......
# frozen_string_literal: true
module Geo
class GroupWikiRepositoryRegistryFinder
include FrameworkRegistryFinder
end
end
# frozen_string_literal: true
module Resolvers
module Geo
class GroupWikiRepositoryRegistriesResolver < BaseResolver
type ::Types::Geo::GeoNodeType.connection_type, null: true
include RegistriesResolver
end
end
end
...@@ -38,6 +38,11 @@ module Types ...@@ -38,6 +38,11 @@ module Types
null: true, null: true,
resolver: ::Resolvers::Geo::TerraformStateVersionRegistriesResolver, resolver: ::Resolvers::Geo::TerraformStateVersionRegistriesResolver,
description: 'Find terraform state version registries on this Geo node.' description: 'Find terraform state version registries on this Geo node.'
field :group_wiki_repository_registries, ::Types::Geo::GroupWikiRepositoryRegistryType.connection_type,
null: true,
resolver: ::Resolvers::Geo::GroupWikiRepositoryRegistriesResolver,
description: 'Find group wiki repository registries on this Geo node.',
feature_flag: :geo_group_wiki_repository_replication
end end
end end
end end
# frozen_string_literal: true
module Types
module Geo
# rubocop:disable Graphql/AuthorizeTypes because it is included
class GroupWikiRepositoryRegistryType < BaseObject
include ::Types::Geo::RegistryType
graphql_name 'GroupWikiRepositoryRegistry'
description 'Represents the Geo sync and verification state of a group wiki repository'
field :group_wiki_repository_id, GraphQL::ID_TYPE, null: false, description: 'ID of the Group Wiki Repository.'
end
end
end
# frozen_string_literal: true
class Geo::GroupWikiRepositoryRegistry < Geo::BaseRegistry
include Geo::ReplicableRegistry
MODEL_CLASS = ::GroupWikiRepository
MODEL_FOREIGN_KEY = :group_wiki_repository_id
belongs_to :group_wiki_repository, class_name: 'GroupWikiRepository'
end
# frozen_string_literal: true # frozen_string_literal: true
class GroupWikiRepository < ApplicationRecord class GroupWikiRepository < ApplicationRecord
include ::Gitlab::Geo::ReplicableModel
include EachBatch include EachBatch
include Shardable include Shardable
with_replicator Geo::GroupWikiRepositoryReplicator
belongs_to :group belongs_to :group
validates :group, :disk_path, presence: true, uniqueness: true validates :group, :disk_path, presence: true, uniqueness: true
delegate :repository_storage, to: :group
def self.replicables_for_current_secondary(primary_key_in)
node = ::Gitlab::Geo.current_node
replicables = if !node.selective_sync?
all
elsif node.selective_sync_by_namespaces?
group_wiki_repositories_for_selected_namespaces
elsif node.selective_sync_by_shards?
group_wiki_repositories_for_selected_shards
else
self.none
end
replicables.primary_key_in(primary_key_in)
end
def self.group_wiki_repositories_for_selected_namespaces
self.joins(:group).where(group_id: ::Gitlab::Geo.current_node.namespaces_for_group_owned_replicables.select(:id))
end
def self.group_wiki_repositories_for_selected_shards
self.for_repository_storage(::Gitlab::Geo.current_node.selective_sync_shards)
end
def pool_repository
nil
end
def repository
group.wiki.repository
end
end end
# frozen_string_literal: true
module Geo
class GroupWikiRepositoryReplicator < Gitlab::Geo::Replicator
include ::Geo::RepositoryReplicatorStrategy
def self.model
::GroupWikiRepository
end
def self.git_access_class
::Gitlab::GitAccessWiki
end
def repository
model_record.repository
end
def self.replication_enabled_by_default?
false
end
end
end
...@@ -10,7 +10,13 @@ module EE ...@@ -10,7 +10,13 @@ module EE
super.tap do |group| super.tap do |group|
delete_dependency_proxy_blobs(group) delete_dependency_proxy_blobs(group)
log_audit_event unless group&.persisted? unless group&.persisted?
log_audit_event
if ::Gitlab::Geo.primary? && group.group_wiki_repository
group.group_wiki_repository.replicator.handle_after_destroy
end
end
end end
end end
......
...@@ -26,12 +26,13 @@ module EE ...@@ -26,12 +26,13 @@ module EE
def process_wiki_changes(post_received, wiki) def process_wiki_changes(post_received, wiki)
super super
# TODO: Support Geo for group wikis. return unless ::Gitlab::Geo.primary?
# https://gitlab.com/gitlab-org/gitlab/-/issues/208147
return unless wiki.is_a?(ProjectWiki)
if ::Gitlab::Geo.primary? if wiki.is_a?(ProjectWiki)
::Geo::RepositoryUpdatedService.new(wiki.repository).execute ::Geo::RepositoryUpdatedService.new(wiki.repository).execute
else
group_wiki_repository = wiki.group.group_wiki_repository
group_wiki_repository.replicator.handle_after_update if group_wiki_repository
end end
end end
......
...@@ -25,7 +25,8 @@ module Geo ...@@ -25,7 +25,8 @@ module Geo
Geo::ProjectRegistry, Geo::ProjectRegistry,
Geo::TerraformStateVersionRegistry, Geo::TerraformStateVersionRegistry,
Geo::UploadRegistry, Geo::UploadRegistry,
Geo::SnippetRepositoryRegistry Geo::SnippetRepositoryRegistry,
Geo::GroupWikiRepositoryRegistry
].freeze ].freeze
BATCH_SIZE = 10000 BATCH_SIZE = 10000
......
---
title: Include group wikis in Geo replication
merge_request: 54914
author:
type: added
---
name: geo_group_wiki_repository_replication
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54914
rollout_issue_url:
milestone: '13.10'
type: development
group: group::geo
default_enabled: false
# frozen_string_literal: true
class CreateGroupWikiRepositoryRegistry < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
create_table :group_wiki_repository_registry, id: :bigserial, force: :cascade do |t|
t.datetime_with_timezone :retry_at
t.datetime_with_timezone :last_synced_at
t.datetime_with_timezone :created_at, null: false
t.bigint :group_wiki_repository_id, null: false
t.integer :state, default: 0, null: false, limit: 2
t.integer :retry_count, default: 0, limit: 2
t.text :last_sync_failure
t.boolean :force_to_redownload
t.boolean :missing_on_primary
t.index :group_wiki_repository_id, name: :index_g_wiki_repository_registry_on_group_wiki_repository_id, unique: true
t.index :retry_at
t.index :state
end
add_text_limit :group_wiki_repository_registry, :last_sync_failure, 255
end
def down
drop_table :group_wiki_repository_registry
end
end
...@@ -63,6 +63,21 @@ ActiveRecord::Schema.define(version: 2021_02_25_200858) do ...@@ -63,6 +63,21 @@ ActiveRecord::Schema.define(version: 2021_02_25_200858) do
t.index ["success"], name: "index_file_registry_on_success" t.index ["success"], name: "index_file_registry_on_success"
end end
create_table "group_wiki_repository_registry", force: :cascade do |t|
t.datetime_with_timezone "retry_at"
t.datetime_with_timezone "last_synced_at"
t.datetime_with_timezone "created_at", null: false
t.bigint "group_wiki_repository_id", null: false
t.integer "state", limit: 2, default: 0, null: false
t.integer "retry_count", limit: 2, default: 0
t.text "last_sync_failure"
t.boolean "force_to_redownload"
t.boolean "missing_on_primary"
t.index ["group_wiki_repository_id"], name: "index_g_wiki_repository_registry_on_group_wiki_repository_id", unique: true
t.index ["retry_at"], name: "index_group_wiki_repository_registry_on_retry_at"
t.index ["state"], name: "index_group_wiki_repository_registry_on_state"
end
create_table "job_artifact_registry", id: :serial, force: :cascade do |t| create_table "job_artifact_registry", id: :serial, force: :cascade do |t|
t.datetime_with_timezone "created_at" t.datetime_with_timezone "created_at"
t.datetime_with_timezone "retry_at" t.datetime_with_timezone "retry_at"
......
...@@ -57,6 +57,8 @@ module EE ...@@ -57,6 +57,8 @@ module EE
end end
def can_read_group? def can_read_group?
return true if geo?
if user if user
user.can?(:read_group, group) user.can?(:read_group, group)
else else
......
...@@ -23,7 +23,8 @@ module Gitlab ...@@ -23,7 +23,8 @@ module Gitlab
::Geo::MergeRequestDiffReplicator, ::Geo::MergeRequestDiffReplicator,
::Geo::PackageFileReplicator, ::Geo::PackageFileReplicator,
::Geo::TerraformStateVersionReplicator, ::Geo::TerraformStateVersionReplicator,
::Geo::SnippetRepositoryReplicator ::Geo::SnippetRepositoryReplicator,
::Geo::GroupWikiRepositoryReplicator
].freeze ].freeze
def self.current_node def self.current_node
......
# frozen_string_literal: true
FactoryBot.define do
factory :geo_group_wiki_repository_registry, class: 'Geo::GroupWikiRepositoryRegistry' do
group_wiki_repository
state { Geo::GroupWikiRepositoryRegistry.state_value(:pending) }
trait :synced do
state { Geo::GroupWikiRepositoryRegistry.state_value(:synced) }
last_synced_at { 5.days.ago }
end
trait :failed do
state { Geo::GroupWikiRepositoryRegistry.state_value(:failed) }
last_synced_at { 1.day.ago }
retry_count { 2 }
last_sync_failure { 'Random error' }
end
trait :started do
state { Geo::GroupWikiRepositoryRegistry.state_value(:started) }
last_synced_at { 1.day.ago }
retry_count { 0 }
end
end
end
# frozen_string_literal: true
FactoryBot.define do
factory :group_wiki_repository do
group
after(:build) do |group_wiki_repository, _|
group_wiki_repository.shard_name = group_wiki_repository.repository_storage
group_wiki_repository.disk_path = group_wiki_repository.group.wiki.storage.disk_path
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Geo::GroupWikiRepositoryRegistryFinder do
it_behaves_like 'a framework registry finder', :geo_group_wiki_repository_registry
end
...@@ -96,6 +96,18 @@ ...@@ -96,6 +96,18 @@
"snippet_repositories_verification_total_count", "snippet_repositories_verification_total_count",
"snippet_repositories_verified_count", "snippet_repositories_verified_count",
"snippet_repositories_verified_in_percentage", "snippet_repositories_verified_in_percentage",
"group_wiki_repositories_count",
"group_wiki_repositories_checksum_total_count",
"group_wiki_repositories_checksummed_count",
"group_wiki_repositories_checksum_failed_count",
"group_wiki_repositories_synced_count",
"group_wiki_repositories_failed_count",
"group_wiki_repositories_registry_count",
"group_wiki_repositories_verification_total_count",
"group_wiki_repositories_verified_count",
"group_wiki_repositories_verification_failed_count",
"group_wiki_repositories_synced_in_percentage",
"group_wiki_repositories_verified_in_percentage",
"repositories_verified_count", "repositories_verified_count",
"repositories_verification_failed_count", "repositories_verification_failed_count",
"repositories_verification_total_count", "repositories_verification_total_count",
...@@ -229,6 +241,18 @@ ...@@ -229,6 +241,18 @@
"snippet_repositories_verification_total_count": { "type": ["integer", "null"] }, "snippet_repositories_verification_total_count": { "type": ["integer", "null"] },
"snippet_repositories_verified_count": { "type": ["integer", "null"] }, "snippet_repositories_verified_count": { "type": ["integer", "null"] },
"snippet_repositories_verified_in_percentage": { "type": "string" }, "snippet_repositories_verified_in_percentage": { "type": "string" },
"group_wiki_repositories_count": { "type": ["integer", "null"] },
"group_wiki_repositories_checksummed_count": { "type": ["integer", "null"] },
"group_wiki_repositories_checksum_failed_count": { "type": ["integer", "null"] },
"group_wiki_repositories_checksum_total_count": { "type": ["integer", "null"] },
"group_wiki_repositories_registry_count": { "type": ["integer", "null"] },
"group_wiki_repositories_failed_count": { "type": ["integer", "null"] },
"group_wiki_repositories_synced_count": { "type": ["integer", "null"] },
"group_wiki_repositories_synced_in_percentage": { "type": "string" },
"group_wiki_repositories_verification_failed_count": { "type": ["integer", "null"] },
"group_wiki_repositories_verification_total_count": { "type": ["integer", "null"] },
"group_wiki_repositories_verified_count": { "type": ["integer", "null"] },
"group_wiki_repositories_verified_in_percentage": { "type": "string" },
"repositories_verified_count": { "type": ["integer", "null"] }, "repositories_verified_count": { "type": ["integer", "null"] },
"repositories_verification_failed_count": { "type": ["integer", "null"] }, "repositories_verification_failed_count": { "type": ["integer", "null"] },
"repositories_verification_total_count": { "type": ["integer", "null"] }, "repositories_verification_total_count": { "type": ["integer", "null"] },
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Resolvers::Geo::GroupWikiRepositoryRegistriesResolver do
it_behaves_like 'a Geo registries resolver', :geo_group_wiki_repository_registry
end
...@@ -13,7 +13,7 @@ RSpec.describe GitlabSchema.types['GeoNode'] do ...@@ -13,7 +13,7 @@ RSpec.describe GitlabSchema.types['GeoNode'] do
selective_sync_type selective_sync_shards selective_sync_namespaces selective_sync_type selective_sync_shards selective_sync_namespaces
minimum_reverification_interval merge_request_diff_registries minimum_reverification_interval merge_request_diff_registries
package_file_registries snippet_repository_registries package_file_registries snippet_repository_registries
terraform_state_version_registries terraform_state_version_registries group_wiki_repository_registries
] ]
expect(described_class).to have_graphql_fields(*expected_fields) expect(described_class).to have_graphql_fields(*expected_fields)
......
...@@ -108,6 +108,14 @@ RSpec.describe Gitlab::GitAccessWiki do ...@@ -108,6 +108,14 @@ RSpec.describe Gitlab::GitAccessWiki do
end end
end end
context 'when actor is geo' do
let(:user) { :geo }
it 'gives access to download wiki code' do
expect { subject }.not_to raise_error
end
end
context 'the group is public' do context 'the group is public' do
let(:group) { create(:group, :public, :wiki_repo) } let(:group) { create(:group, :public, :wiki_repo) }
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Geo::GroupWikiRepositoryRegistry, :geo, type: :model do
let_it_be(:registry) { create(:geo_group_wiki_repository_registry) }
specify 'factory is valid' do
expect(registry).to be_valid
end
include_examples 'a Geo framework registry'
end
...@@ -1162,6 +1162,7 @@ RSpec.describe GeoNodeStatus, :geo do ...@@ -1162,6 +1162,7 @@ RSpec.describe GeoNodeStatus, :geo do
Geo::PackageFileReplicator | :package_file | :geo_package_file_registry Geo::PackageFileReplicator | :package_file | :geo_package_file_registry
Geo::TerraformStateVersionReplicator | :terraform_state_version | :geo_terraform_state_version_registry Geo::TerraformStateVersionReplicator | :terraform_state_version | :geo_terraform_state_version_registry
Geo::SnippetRepositoryReplicator | :snippet_repository | :geo_snippet_repository_registry Geo::SnippetRepositoryReplicator | :snippet_repository | :geo_snippet_repository_registry
Geo::GroupWikiRepositoryReplicator | :group_wiki_repository | :geo_group_wiki_repository_registry
end end
with_them do with_them do
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe GroupWikiRepository do RSpec.describe GroupWikiRepository, :geo do
describe 'associations' do describe 'associations' do
it { is_expected.to belong_to(:shard) } it { is_expected.to belong_to(:shard) }
it { is_expected.to belong_to(:group) } it { is_expected.to belong_to(:group) }
...@@ -20,4 +20,109 @@ RSpec.describe GroupWikiRepository do ...@@ -20,4 +20,109 @@ RSpec.describe GroupWikiRepository do
it { is_expected.to validate_uniqueness_of(:disk_path) } it { is_expected.to validate_uniqueness_of(:disk_path) }
end end
end end
describe 'Geo Replication' do
include EE::GeoHelpers
let(:node) { create(:geo_node) }
before do
stub_current_geo_node(node)
end
context 'with root group and subgroup wikis' do
let_it_be(:root_group) { create(:group) }
let_it_be(:subgroup) { create(:group, parent: root_group) }
let_it_be(:root_group_wiki_repository) { create(:group_wiki_repository, group: root_group) }
let_it_be(:subgroup_wiki_repository) { create(:group_wiki_repository, group: subgroup) }
let_it_be(:broken_wiki_repository) { create(:group_wiki_repository, shard_name: 'broken') }
describe '#in_replicables_for_current_secondary?' do
it 'all returns true if all are replicated' do
[
root_group_wiki_repository,
subgroup_wiki_repository,
broken_wiki_repository
].each do |repository|
expect(repository.in_replicables_for_current_secondary?).to be true
end
end
context 'with selective sync by namespace' do
before do
node.update!(selective_sync_type: 'namespaces', namespaces: [root_group])
end
it 'returns true for groups' do
expect(root_group_wiki_repository.in_replicables_for_current_secondary?).to be true
end
it 'returns true for subgroups' do
expect(subgroup_wiki_repository.in_replicables_for_current_secondary?).to be true
end
end
context 'with selective sync by shard' do
before do
node.update!(selective_sync_type: 'shards', selective_sync_shards: ['default'])
end
it 'returns true for groups in the shard' do
expect(root_group_wiki_repository.in_replicables_for_current_secondary?).to be true
expect(subgroup_wiki_repository.in_replicables_for_current_secondary?).to be true
end
it 'returns false for group wiki repositories not in an included shard' do
expect(broken_wiki_repository.in_replicables_for_current_secondary?).to be false
end
end
end
describe '#replicables_for_current_secondary' do
it 'returns all group wiki repositories without selective sync' do
expect(described_class.replicables_for_current_secondary(1..described_class.last.id)).to match_array([
root_group_wiki_repository,
subgroup_wiki_repository,
broken_wiki_repository
])
end
context 'with selective sync by namespace' do
it 'returns group wiki repositories that belong to the namespaces and descendants' do
node.update!(selective_sync_type: 'namespaces', namespaces: [root_group])
expect(described_class.replicables_for_current_secondary(1..described_class.last.id)).to match_array([
root_group_wiki_repository,
subgroup_wiki_repository
])
end
it 'returns group wiki repositories that belong to the namespace' do
node.update!(selective_sync_type: 'namespaces', namespaces: [subgroup])
expect(described_class.replicables_for_current_secondary(1..described_class.last.id)).to match_array([
subgroup_wiki_repository
])
end
end
context 'with selective sync by shard' do
it 'returns group wiki repositories that belong to the shards' do
node.update!(selective_sync_type: 'shards', selective_sync_shards: ['default'])
expect(described_class.replicables_for_current_secondary(1..described_class.last.id)).to match_array([
root_group_wiki_repository,
subgroup_wiki_repository
])
end
end
it 'returns nothing if an unrecognised selective sync type is used' do
node.update_attribute(:selective_sync_type, 'unknown')
expect(described_class.replicables_for_current_secondary(1..described_class.last.id)).to be_empty
end
end
end
end
end end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Geo::GroupWikiRepositoryReplicator do
let(:model_record) { build(:group_wiki_repository, group: create(:group)) }
include_examples 'a repository replicator'
end
...@@ -30,4 +30,11 @@ RSpec.describe 'Gets registries' do ...@@ -30,4 +30,11 @@ RSpec.describe 'Gets registries' do
registry_factory: :geo_terraform_state_version_registry, registry_factory: :geo_terraform_state_version_registry,
registry_foreign_key_field_name: 'terraformStateVersionId' registry_foreign_key_field_name: 'terraformStateVersionId'
} }
it_behaves_like 'gets registries for', {
field_name: 'groupWikiRepositoryRegistries',
registry_class_name: 'GroupWikiRepositoryRegistry',
registry_factory: :geo_group_wiki_repository_registry,
registry_foreign_key_field_name: 'groupWikiRepositoryId'
}
end end
...@@ -45,4 +45,36 @@ RSpec.describe Groups::DestroyService do ...@@ -45,4 +45,36 @@ RSpec.describe Groups::DestroyService do
expect { subject.execute }.to change { DependencyProxy::Blob.count }.by(-1) expect { subject.execute }.to change { DependencyProxy::Blob.count }.by(-1)
end end
end end
context 'when on a Geo primary node' do
before do
allow(Gitlab::Geo).to receive(:primary?) { true }
end
context 'when group_wiki_repository does not exist' do
it 'does not call replicator to update Geo' do
expect_next_instance_of(Geo::GroupWikiRepositoryReplicator).never
subject.execute
end
end
it 'calls replicator to update Geo' do
group.wiki.create_wiki_repository
expect(group.group_wiki_repository.replicator).to receive(:handle_after_destroy)
subject.execute
end
end
context 'when not on a Geo primary node' do
it 'does not call replicator to update Geo' do
group.wiki.create_wiki_repository
expect(group.group_wiki_repository.replicator).not_to receive(:handle_after_destroy)
subject.execute
end
end
end end
...@@ -139,12 +139,60 @@ RSpec.describe PostReceive do ...@@ -139,12 +139,60 @@ RSpec.describe PostReceive do
described_class.new.perform(gl_repository, key_id, base64_changes) described_class.new.perform(gl_repository, key_id, base64_changes)
end end
it 'does not call Geo::RepositoryUpdatedService when running on a Geo primary node' do context 'when on a Geo primary node' do
allow(Gitlab::Geo).to receive(:primary?) { true } before do
allow(Gitlab::Geo).to receive(:primary?) { true }
end
expect_next_instance_of(::Geo::RepositoryUpdatedService).never it 'does not call Geo::RepositoryUpdatedService' do
expect_next_instance_of(::Geo::RepositoryUpdatedService).never
described_class.new.perform(gl_repository, key_id, base64_changes) described_class.new.perform(gl_repository, key_id, base64_changes)
end
context 'when wiki is a project wiki' do
let(:wiki) { build(:project_wiki, project: project) }
it 'does not call replicator to update Geo' do
expect_next_instance_of(Geo::GroupWikiRepositoryReplicator).never
described_class.new.perform(gl_repository, key_id, base64_changes)
end
end
context 'when group_wiki_repository does not exist' do
it 'does not call replicator to update Geo' do
expect(group.group_wiki_repository).to be_nil
expect_next_instance_of(Geo::GroupWikiRepositoryReplicator).never
described_class.new.perform(gl_repository, key_id, base64_changes)
end
end
context 'when group_wiki_repository exists' do
it 'calls replicator to update Geo' do
wiki.create_wiki_repository
expect(group.group_wiki_repository).to be_present
expect_next_instance_of(Geo::GroupWikiRepositoryReplicator) do |instance|
expect(instance).to receive(:handle_after_update)
end
described_class.new.perform(gl_repository, key_id, base64_changes)
end
end
end
context 'when not on a Geo primary node' do
it 'does not call replicator to update Geo' do
wiki.create_wiki_repository
expect(group.group_wiki_repository).to be_present
expect_next_instance_of(Geo::GroupWikiRepositoryReplicator).never
described_class.new.perform(gl_repository, key_id, base64_changes)
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