Commit 872e6dd0 authored by Mike Kozono's avatar Mike Kozono

Apply selective sync to container repo update

For example, if a container repository is excluded by selective sync,
then a sync job should not be enqueued (sync jobs currently do not
double check if a thing should be synced), nor should it create a
registry record (since that will impact counts and eventually cause
another worker to enqueue a sync job for the unsynced registry).
parent 2b0356c9
---
title: 'Geo: Apply selective sync to container repo updates'
merge_request: 39663
author:
type: fixed
......@@ -37,8 +37,8 @@ module Gitlab
yield if healthy_shard_for?(event)
end
def replicable_project?
strong_memoize(:replicable_project) do
def replicable_project?(project_id)
strong_memoize(:"replicable_project_#{project_id}") do
# If a registry exists, then it *should* be replicated. The
# registry will be removed by the delete event or
# RegistryConsistencyWorker if it should no longer be replicated.
......@@ -47,7 +47,7 @@ module Gitlab
# for repository updates which are a large proportion of events.
next true if registry.persisted?
Gitlab::Geo.current_node.projects_include?(event.project_id)
Gitlab::Geo.current_node.projects_include?(project_id)
end
end
......
......@@ -8,17 +8,23 @@ module Gitlab
include BaseEvent
def process
registry.repository_updated!
if should_sync?
registry.repository_updated!
job_id = ::Geo::ContainerRepositorySyncWorker.perform_async(event.container_repository_id)
job_id = ::Geo::ContainerRepositorySyncWorker.perform_async(event.container_repository_id)
end
log_event(job_id)
end
private
def skippable?
!!::Geo::ContainerRepositoryRegistry.replication_enabled?
def should_sync?
strong_memoize(:should_sync) do
::Geo::ContainerRepositoryRegistry.replication_enabled? &&
registry.container_repository &&
replicable_project?(registry.container_repository.project_id)
end
end
# rubocop: disable CodeReuse/ActiveRecord
......@@ -33,8 +39,10 @@ module Gitlab
super(
'Docker Repository update',
container_repository_id: registry.container_repository_id,
skippable: skippable?,
project: registry.container_repository.project_id,
should_sync: should_sync?,
replication_enabled: ::Geo::ContainerRepositoryRegistry.replication_enabled?,
replicable_project: replicable_project?(registry.container_repository.project_id),
project_id: registry.container_repository.project_id,
job_id: job_id)
end
end
......
......@@ -8,7 +8,7 @@ module Gitlab
include BaseEvent
def process
if replicable_project?
if replicable_project?(event.project_id)
registry.repository_created!(event)
job_id = nil
......@@ -31,7 +31,7 @@ module Gitlab
wiki_path: event.wiki_path,
resync_repository: registry.resync_repository,
resync_wiki: registry.resync_wiki,
replicable_project: replicable_project?,
replicable_project: replicable_project?(event.project_id),
job_id: job_id)
end
end
......
......@@ -8,7 +8,7 @@ module Gitlab
include BaseEvent
def process
if replicable_project?
if replicable_project?(event.project_id)
registry.repository_updated!(event.source, scheduled_at)
job_id = enqueue_job_if_shard_healthy(event) do
......@@ -33,7 +33,7 @@ module Gitlab
resync_repository: registry.resync_repository,
resync_wiki: registry.resync_wiki,
scheduled_at: scheduled_at,
replicable_project: replicable_project?,
replicable_project: replicable_project?(event.project_id),
job_id: job_id)
end
......
......@@ -3,11 +3,15 @@
require 'spec_helper'
RSpec.describe Gitlab::Geo::LogCursor::Events::ContainerRepositoryUpdatedEvent, :clean_gitlab_redis_shared_state do
include ::EE::GeoHelpers
let_it_be(:secondary) { create(:geo_node) }
let_it_be(:selective_sync_secondary) { create(:geo_node, selective_sync_type: 'shards', selective_sync_shards: ['non-existent']) }
let(:logger) { Gitlab::Geo::LogCursor::Logger.new(described_class, Logger::INFO) }
let(:event_log) { create(:geo_event_log, :container_repository_updated_event) }
let!(:event_log_state) { create(:geo_event_log_state, event_id: event_log.id - 1) }
let(:container_repository_updated_event) { event_log.container_repository_updated_event }
let(:container_repositoy) { container_repository_updated_event.container_repository }
let(:container_repository) { container_repository_updated_event.container_repository }
subject { described_class.new(container_repository_updated_event, Time.now, logger) }
......@@ -15,18 +19,82 @@ RSpec.describe Gitlab::Geo::LogCursor::Events::ContainerRepositoryUpdatedEvent,
Sidekiq::Testing.fake! { example.run }
end
before do
stub_current_geo_node(secondary)
end
describe '#process' do
it 'does not create a new project registry' do
expect { subject.process }.not_to change(Geo::ProjectRegistry, :count)
end
context 'when container repository replication is enabled' do
before do
stub_config(geo: { registry_replication: { enabled: true } })
end
context 'when a registry does not yet exist' do
context "when the container repository's project is not excluded by selective sync" do
# TODO: Fix the bug and un-x the test https://gitlab.com/gitlab-org/gitlab/-/issues/233514
xit 'creates a registry' do
expect { subject.process }.to change(Geo::ContainerRepositoryRegistry, :count).by(1)
end
it_behaves_like 'event schedules a sync worker', ::Geo::ContainerRepositorySyncWorker do
let(:expected_id) { container_repository.id }
end
it_behaves_like 'logs event source info'
end
context "when the container repository's project is excluded by selective sync" do
before do
stub_current_geo_node(selective_sync_secondary)
end
it 'schedules a Geo::ContainerRepositorySyncWorker' do
expect(::Geo::ContainerRepositorySyncWorker).to receive(:perform_async)
.with(container_repositoy.id)
it_behaves_like 'event does not create a registry', ::Geo::ContainerRepositoryRegistry
it_behaves_like 'event does not schedule a sync worker', ::Geo::ContainerRepositorySyncWorker
it_behaves_like 'logs event source info'
end
end
subject.process
context 'when a registry exists' do
let!(:registry) { create(:geo_container_repository_registry, :synced) }
context "when the container repository's project is not excluded by selective sync" do
# TODO: Fix the bug and un-x the test https://gitlab.com/gitlab-org/gitlab/-/issues/233514
xit 'transitions the registry to pending' do
expect { subject.process }.to change(registry, :pending?).to(true)
end
it_behaves_like 'event schedules a sync worker', ::Geo::ContainerRepositorySyncWorker do
let(:expected_id) { container_repository.id }
end
it_behaves_like 'logs event source info'
end
context "when the container repository's project is excluded by selective sync" do
before do
stub_current_geo_node(selective_sync_secondary)
end
it 'does not transition the registry to pending state' do
expect { subject.process }.not_to change(registry, :pending?)
end
it_behaves_like 'event does not schedule a sync worker', ::Geo::ContainerRepositorySyncWorker
it_behaves_like 'logs event source info'
end
end
end
it_behaves_like 'logs event source info'
context 'when container repository replication is disabled' do
before do
stub_config(geo: { registry_replication: { enabled: false } })
end
context "even when the container repository's project is not excluded by selective sync" do
it_behaves_like 'event does not create a registry', ::Geo::ContainerRepositoryRegistry
it_behaves_like 'event does not schedule a sync worker', ::Geo::ContainerRepositorySyncWorker
it_behaves_like 'logs event source info'
end
end
end
end
# frozen_string_literal: true
RSpec.shared_examples 'event does not create a registry' do |registry_class|
it 'does not create a registry' do
expect { subject.process }.not_to change(registry_class, :count)
end
end
# Let variables required:
#
# - expected_id
#
RSpec.shared_examples 'event schedules a sync worker' do |sync_worker|
it 'schedules a sync worker' do
expect(sync_worker).to receive(:perform_async).with(expected_id)
subject.process
end
end
RSpec.shared_examples 'event does not schedule a sync worker' do |sync_worker|
it 'does not schedule a sync worker' do
expect(sync_worker).not_to receive(:perform_async)
subject.process
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