Commit 3af57bae authored by Mikołaj Wawrzyniak's avatar Mikołaj Wawrzyniak

Merge branch '218992-fj-add-snippet-repository-storage-move' into 'master'

Add class SnippetRepositoryStorageMove

See merge request gitlab-org/gitlab!49224
parents 54a319fe 07769624
...@@ -44,6 +44,7 @@ class Snippet < ApplicationRecord ...@@ -44,6 +44,7 @@ class Snippet < ApplicationRecord
has_many :notes, as: :noteable, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_many :notes, as: :noteable, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :user_mentions, class_name: "SnippetUserMention", dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent has_many :user_mentions, class_name: "SnippetUserMention", dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
has_one :snippet_repository, inverse_of: :snippet has_one :snippet_repository, inverse_of: :snippet
has_many :repository_storage_moves, class_name: 'SnippetRepositoryStorageMove', inverse_of: :container
# We need to add the `dependent` in order to call the after_destroy callback # We need to add the `dependent` in order to call the after_destroy callback
has_one :statistics, class_name: 'SnippetStatistics', dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_one :statistics, class_name: 'SnippetStatistics', dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
......
# frozen_string_literal: true
# SnippetRepositoryStorageMove are details of repository storage moves for a
# snippet. For example, moving a snippet to another gitaly node to help
# balance storage capacity.
class SnippetRepositoryStorageMove < ApplicationRecord
extend ::Gitlab::Utils::Override
include RepositoryStorageMovable
belongs_to :container, class_name: 'Snippet', inverse_of: :repository_storage_moves, foreign_key: :snippet_id
alias_attribute :snippet, :container
override :schedule_repository_storage_update_worker
def schedule_repository_storage_update_worker
# TODO https://gitlab.com/gitlab-org/gitlab/-/issues/218991
end
private
override :error_key
def error_key
:snippet
end
end
# frozen_string_literal: true
FactoryBot.define do
factory :snippet_repository_storage_move, class: 'SnippetRepositoryStorageMove' do
container { association(:snippet) }
source_storage_name { 'default' }
trait :scheduled do
state { SnippetRepositoryStorageMove.state_machines[:state].states[:scheduled].value }
end
trait :started do
state { SnippetRepositoryStorageMove.state_machines[:state].states[:started].value }
end
trait :replicated do
state { SnippetRepositoryStorageMove.state_machines[:state].states[:replicated].value }
end
trait :finished do
state { SnippetRepositoryStorageMove.state_machines[:state].states[:finished].value }
end
trait :failed do
state { SnippetRepositoryStorageMove.state_machines[:state].states[:failed].value }
end
end
end
...@@ -107,6 +107,7 @@ snippets: ...@@ -107,6 +107,7 @@ snippets:
- user_mentions - user_mentions
- snippet_repository - snippet_repository
- statistics - statistics
- repository_storage_moves
releases: releases:
- author - author
- project - project
......
...@@ -3,11 +3,33 @@ ...@@ -3,11 +3,33 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe ProjectRepositoryStorageMove, type: :model do RSpec.describe ProjectRepositoryStorageMove, type: :model do
it_behaves_like 'handles repository moves' do let_it_be_with_refind(:project) { create(:project) }
let_it_be_with_refind(:container) { create(:project) }
it_behaves_like 'handles repository moves' do
let(:container) { project }
let(:repository_storage_factory_key) { :project_repository_storage_move } let(:repository_storage_factory_key) { :project_repository_storage_move }
let(:error_key) { :project } let(:error_key) { :project }
let(:repository_storage_worker) { ProjectUpdateRepositoryStorageWorker } let(:repository_storage_worker) { ProjectUpdateRepositoryStorageWorker }
end end
describe 'state transitions' do
let(:storage) { 'test_second_storage' }
before do
stub_storage_settings(storage => { 'path' => 'tmp/tests/extra_storage' })
end
context 'when started' do
subject(:storage_move) { create(:project_repository_storage_move, :started, container: project, destination_storage_name: storage) }
context 'and transits to replicated' do
it 'sets the repository storage and marks the container as writable' do
storage_move.finish_replication!
expect(project.repository_storage).to eq(storage)
expect(project).not_to be_repository_read_only
end
end
end
end
end end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe SnippetRepositoryStorageMove, type: :model do
it_behaves_like 'handles repository moves' do
let_it_be_with_refind(:container) { create(:snippet) }
let(:repository_storage_factory_key) { :snippet_repository_storage_move }
let(:error_key) { :snippet }
let(:repository_storage_worker) { nil } # TODO set to SnippetUpdateRepositoryStorageWorker after https://gitlab.com/gitlab-org/gitlab/-/issues/218991 is implemented
end
end
...@@ -21,6 +21,7 @@ RSpec.describe Snippet do ...@@ -21,6 +21,7 @@ RSpec.describe Snippet do
it { is_expected.to have_many(:user_mentions).class_name("SnippetUserMention") } it { is_expected.to have_many(:user_mentions).class_name("SnippetUserMention") }
it { is_expected.to have_one(:snippet_repository) } it { is_expected.to have_one(:snippet_repository) }
it { is_expected.to have_one(:statistics).class_name('SnippetStatistics').dependent(:destroy) } it { is_expected.to have_one(:statistics).class_name('SnippetStatistics').dependent(:destroy) }
it { is_expected.to have_many(:repository_storage_moves).class_name('SnippetRepositoryStorageMove').inverse_of(:container) }
end end
describe 'validation' do describe 'validation' do
......
...@@ -63,6 +63,7 @@ RSpec.shared_examples 'handles repository moves' do ...@@ -63,6 +63,7 @@ RSpec.shared_examples 'handles repository moves' do
context 'and transits to scheduled' do context 'and transits to scheduled' do
it 'triggers the corresponding repository storage worker' do it 'triggers the corresponding repository storage worker' do
skip unless repository_storage_worker # TODO remove after https://gitlab.com/gitlab-org/gitlab/-/issues/218991 is implemented
expect(repository_storage_worker).to receive(:perform_async).with(container.id, 'test_second_storage', storage_move.id) expect(repository_storage_worker).to receive(:perform_async).with(container.id, 'test_second_storage', storage_move.id)
storage_move.schedule! storage_move.schedule!
...@@ -72,6 +73,7 @@ RSpec.shared_examples 'handles repository moves' do ...@@ -72,6 +73,7 @@ RSpec.shared_examples 'handles repository moves' do
context 'when the transition fails' do context 'when the transition fails' do
it 'does not trigger ProjectUpdateRepositoryStorageWorker and adds an error' do it 'does not trigger ProjectUpdateRepositoryStorageWorker and adds an error' do
skip unless repository_storage_worker # TODO remove after https://gitlab.com/gitlab-org/gitlab/-/issues/218991 is implemented
allow(storage_move.container).to receive(:set_repository_read_only!).and_raise(StandardError, 'foobar') allow(storage_move.container).to receive(:set_repository_read_only!).and_raise(StandardError, 'foobar')
expect(repository_storage_worker).not_to receive(:perform_async) expect(repository_storage_worker).not_to receive(:perform_async)
...@@ -94,10 +96,9 @@ RSpec.shared_examples 'handles repository moves' do ...@@ -94,10 +96,9 @@ RSpec.shared_examples 'handles repository moves' do
subject(:storage_move) { create(repository_storage_factory_key, :started, container: container, destination_storage_name: 'test_second_storage') } subject(:storage_move) { create(repository_storage_factory_key, :started, container: container, destination_storage_name: 'test_second_storage') }
context 'and transits to replicated' do context 'and transits to replicated' do
it 'sets the repository storage and marks the container as writable' do it 'marks the container as writable' do
storage_move.finish_replication! storage_move.finish_replication!
expect(container.repository_storage).to eq('test_second_storage')
expect(container).not_to be_repository_read_only expect(container).not_to be_repository_read_only
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