Commit f6f29dbd authored by Mike Kozono's avatar Mike Kozono

Add PackageFileRegistryFinder for GraphQL API

But write it generically for the Geo Self-Service Framework. Similar
code will be needed for all Geo registry classes.
parent 191b9600
# frozen_string_literal: true
module Geo
# Used to provide registry data for GraphQL queries.
#
module FrameworkRegistryFinder
extend ActiveSupport::Concern
included do
include Gitlab::Allowable
delegate :registry_class, to: :replicator_class
def initialize(current_user, params = {})
@current_user = current_user
@params = params
end
def execute
return registry_class.none unless can?(current_user, :read_all_geo)
registry_entries = init_collection
registry_entries = by_id(registry_entries)
registry_entries.ordered
end
private
attr_reader :current_user, :params
def replicator_class
Gitlab::Geo::Replicator.for_class_name(self.class.name)
end
def init_collection
registry_class.all
end
def by_id(registry_entries)
return registry_entries if params[:ids].nil?
return registry_class.none if params[:ids].empty?
registry_entries.id_in(params[:ids])
end
end
end
end
# frozen_string_literal: true
module Geo
class PackageFileRegistryFinder
include FrameworkRegistryFinder
end
end
...@@ -16,6 +16,7 @@ class Geo::PackageFileRegistry < Geo::BaseRegistry ...@@ -16,6 +16,7 @@ class Geo::PackageFileRegistry < Geo::BaseRegistry
scope :failed, -> { with_state(:failed) } scope :failed, -> { with_state(:failed) }
scope :synced, -> { with_state(:synced) } scope :synced, -> { with_state(:synced) }
scope :retry_due, -> { where(arel_table[:retry_at].eq(nil).or(arel_table[:retry_at].lt(Time.now))) } scope :retry_due, -> { where(arel_table[:retry_at].eq(nil).or(arel_table[:retry_at].lt(Time.now))) }
scope :ordered, -> { order(:id) }
state_machine :state, initial: :pending do state_machine :state, initial: :pending do
state :pending, value: STATE_VALUES[:pending] state :pending, value: STATE_VALUES[:pending]
......
...@@ -12,6 +12,8 @@ module Gitlab ...@@ -12,6 +12,8 @@ module Gitlab
class Replicator class Replicator
include ::Gitlab::Geo::LogHelpers include ::Gitlab::Geo::LogHelpers
CLASS_SUFFIXES = %w(RegistryFinder RegistriesResolver).freeze
attr_reader :model_record_id attr_reader :model_record_id
delegate :model, to: :class delegate :model, to: :class
...@@ -63,6 +65,10 @@ module Gitlab ...@@ -63,6 +65,10 @@ module Gitlab
const_get("::Geo::#{replicable_name.camelize}Registry", false) const_get("::Geo::#{replicable_name.camelize}Registry", false)
end end
def self.registry_finder_class
const_get("::Geo::#{replicable_name.camelize}RegistryFinder", false)
end
# Given a `replicable_name`, return the corresponding replicator # Given a `replicable_name`, return the corresponding replicator
# #
# @param [String] replicable_name the replicable slug # @param [String] replicable_name the replicable slug
...@@ -89,6 +95,21 @@ module Gitlab ...@@ -89,6 +95,21 @@ module Gitlab
model.count model.count
end end
# @example Given `Geo::PackageFileRegistryFinder`, this returns
# `::Geo::PackageFileReplicator`
# @example Given `Resolver::Geo::PackageFileRegistriesResolver`, this
# returns `::Geo::PackageFileReplicator`
#
# @return [Class] a Replicator subclass
def self.for_class_name(class_name)
name = class_name.demodulize
# Strip suffixes is dumb but will probably work for a while
CLASS_SUFFIXES.each { |suffix| name.delete_suffix!(suffix) }
const_get("::Geo::#{name}Replicator", false)
end
# @param [ActiveRecord::Base] model_record # @param [ActiveRecord::Base] model_record
# @param [Integer] model_record_id # @param [Integer] model_record_id
def initialize(model_record: nil, model_record_id: nil) def initialize(model_record: nil, model_record_id: nil)
......
# frozen_string_literal: true
require 'spec_helper'
describe Geo::PackageFileRegistryFinder do
it_behaves_like 'a framework registry finder', :package_file_registry
end
...@@ -22,9 +22,9 @@ describe Gitlab::Geo::Replicator do ...@@ -22,9 +22,9 @@ describe Gitlab::Geo::Replicator do
context 'with defined events' do context 'with defined events' do
before do before do
stub_const('DummyReplicator', Class.new(Gitlab::Geo::Replicator)) stub_const('Geo::DummyReplicator', Class.new(Gitlab::Geo::Replicator))
DummyReplicator.class_eval do Geo::DummyReplicator.class_eval do
event :test event :test
event :another_test event :another_test
...@@ -37,7 +37,7 @@ describe Gitlab::Geo::Replicator do ...@@ -37,7 +37,7 @@ describe Gitlab::Geo::Replicator do
end end
context 'event DSL' do context 'event DSL' do
subject { DummyReplicator } subject { Geo::DummyReplicator }
describe '.supported_events' do describe '.supported_events' do
it 'expects :test event to be supported' do it 'expects :test event to be supported' do
...@@ -68,7 +68,7 @@ describe Gitlab::Geo::Replicator do ...@@ -68,7 +68,7 @@ describe Gitlab::Geo::Replicator do
include Gitlab::Geo::ReplicableModel include Gitlab::Geo::ReplicableModel
with_replicator DummyReplicator with_replicator Geo::DummyReplicator
end end
end end
...@@ -79,12 +79,12 @@ describe Gitlab::Geo::Replicator do ...@@ -79,12 +79,12 @@ describe Gitlab::Geo::Replicator do
end end
it 'instantiates a replicator into the model' do it 'instantiates a replicator into the model' do
expect(subject.replicator).to be_a(DummyReplicator) expect(subject.replicator).to be_a(Geo::DummyReplicator)
end end
end end
describe '#publish' do describe '#publish' do
subject { DummyReplicator.new } subject { Geo::DummyReplicator.new }
context 'when geo_self_service_framework feature is disabled' do context 'when geo_self_service_framework feature is disabled' do
before do before do
...@@ -120,7 +120,7 @@ describe Gitlab::Geo::Replicator do ...@@ -120,7 +120,7 @@ describe Gitlab::Geo::Replicator do
end end
describe '#consume' do describe '#consume' do
subject { DummyReplicator.new } subject { Geo::DummyReplicator.new }
it 'accepts valid attributes' do it 'accepts valid attributes' do
expect { subject.consume(:test, user: 'something', other: 'something else') }.not_to raise_error expect { subject.consume(:test, user: 'something', other: 'something else') }.not_to raise_error
...@@ -132,5 +132,19 @@ describe Gitlab::Geo::Replicator do ...@@ -132,5 +132,19 @@ describe Gitlab::Geo::Replicator do
subject.consume(:test, user: 'something', other: 'something else') subject.consume(:test, user: 'something', other: 'something else')
end end
end end
describe '.for_class_name' do
context 'when given a Geo RegistryFinder' do
it 'returns the corresponding Replicator class' do
expect(described_class.for_class_name('Geo::DummyRegistryFinder')).to eq(Geo::DummyReplicator)
end
end
context 'when given a Geo RegistriesResolver"' do
it 'returns the corresponding Replicator class' do
expect(described_class.for_class_name('Geo::DummyRegistriesResolver')).to eq(Geo::DummyReplicator)
end
end
end
end end
end end
# frozen_string_literal: true
RSpec.shared_examples 'a framework registry finder' do |registry_factory|
include ::EE::GeoHelpers
let!(:registry1) { create(registry_factory) }
let!(:registry2) { create(registry_factory) }
let!(:registry3) { create(registry_factory) }
let(:params) { {} }
subject(:registries) { described_class.new(user, params).execute }
describe '#execute' do
context 'when user cannot read all Geo' do
let_it_be(:user) { create(:user) }
it { is_expected.to be_empty }
end
context 'when user can read all Geo' do
let_it_be(:user) { create(:user, :admin) }
context 'with an ids param' do
let(:params) { { ids: [registry3.id, registry1.id] } }
it 'returns specified registries' do
expect(registries.to_a).to eq([registry1, registry3])
end
end
context 'without an ids param' do
it 'returns all registries' do
expect(registries.to_a).to eq([registry1, registry2, registry3])
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