Commit c0643689 authored by Douglas Barbosa Alexandre's avatar Douglas Barbosa Alexandre

Merge branch 'lfs-ssf-behind-feature-flag' into 'master'

Add LFS object replication using SSF [RUN ALL RSPEC] [RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!56286
parents 6f8cc9dc db9d7cf6
...@@ -5239,6 +5239,29 @@ The edge type for [`Label`](#label). ...@@ -5239,6 +5239,29 @@ The edge type for [`Label`](#label).
| <a id="labeledgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. | | <a id="labeledgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="labeledgenode"></a>`node` | [`Label`](#label) | The item at the end of the edge. | | <a id="labeledgenode"></a>`node` | [`Label`](#label) | The item at the end of the edge. |
#### `LfsObjectRegistryConnection`
The connection type for [`LfsObjectRegistry`](#lfsobjectregistry).
##### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="lfsobjectregistryconnectionedges"></a>`edges` | [`[LfsObjectRegistryEdge]`](#lfsobjectregistryedge) | A list of edges. |
| <a id="lfsobjectregistryconnectionnodes"></a>`nodes` | [`[LfsObjectRegistry]`](#lfsobjectregistry) | A list of nodes. |
| <a id="lfsobjectregistryconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
#### `LfsObjectRegistryEdge`
The edge type for [`LfsObjectRegistry`](#lfsobjectregistry).
##### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="lfsobjectregistryedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="lfsobjectregistryedgenode"></a>`node` | [`LfsObjectRegistry`](#lfsobjectregistry) | The item at the end of the edge. |
#### `LicenseHistoryEntryConnection` #### `LicenseHistoryEntryConnection`
The connection type for [`LicenseHistoryEntry`](#licensehistoryentry). The connection type for [`LicenseHistoryEntry`](#licensehistoryentry).
...@@ -8317,6 +8340,22 @@ four standard [pagination arguments](#connection-pagination-arguments): ...@@ -8317,6 +8340,22 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- | | ---- | ---- | ----------- |
| <a id="geonodegroupwikirepositoryregistriesids"></a>`ids` | [`[ID!]`](#id) | Filters registries by their ID. | | <a id="geonodegroupwikirepositoryregistriesids"></a>`ids` | [`[ID!]`](#id) | Filters registries by their ID. |
##### `GeoNode.lfsObjectRegistries`
Find LFS object registries on this Geo node. Available only when feature flag `geo_lfs_object_replication` is enabled.
Returns [`LfsObjectRegistryConnection`](#lfsobjectregistryconnection).
This field returns a [connection](#connections). It accepts the
four standard [pagination arguments](#connection-pagination-arguments):
`before: String`, `after: String`, `first: Int`, `last: Int`.
###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="geonodelfsobjectregistriesids"></a>`ids` | [`[ID!]`](#id) | Filters registries by their ID. |
##### `GeoNode.mergeRequestDiffRegistries` ##### `GeoNode.mergeRequestDiffRegistries`
Find merge request diff registries on this Geo node. Find merge request diff registries on this Geo node.
...@@ -9327,6 +9366,23 @@ four standard [pagination arguments](#connection-pagination-arguments): ...@@ -9327,6 +9366,23 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="labeltitle"></a>`title` | [`String!`](#string) | Content of the label. | | <a id="labeltitle"></a>`title` | [`String!`](#string) | Content of the label. |
| <a id="labelupdatedat"></a>`updatedAt` | [`Time!`](#time) | When this label was last updated. | | <a id="labelupdatedat"></a>`updatedAt` | [`Time!`](#time) | When this label was last updated. |
### `LfsObjectRegistry`
Represents the Geo sync and verification state of an LFS object.
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="lfsobjectregistrycreatedat"></a>`createdAt` | [`Time`](#time) | Timestamp when the LfsObjectRegistry was created. |
| <a id="lfsobjectregistryid"></a>`id` | [`ID!`](#id) | ID of the LfsObjectRegistry. |
| <a id="lfsobjectregistrylastsyncfailure"></a>`lastSyncFailure` | [`String`](#string) | Error message during sync of the LfsObjectRegistry. |
| <a id="lfsobjectregistrylastsyncedat"></a>`lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the LfsObjectRegistry. |
| <a id="lfsobjectregistrylfsobjectid"></a>`lfsObjectId` | [`ID!`](#id) | ID of the LFS object. |
| <a id="lfsobjectregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the LfsObjectRegistry should be resynced. |
| <a id="lfsobjectregistryretrycount"></a>`retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the LfsObjectRegistry. |
| <a id="lfsobjectregistrystate"></a>`state` | [`RegistryState`](#registrystate) | Sync state of the LfsObjectRegistry. |
### `LicenseHistoryEntry` ### `LicenseHistoryEntry`
Represents an entry from the Cloud License history. Represents an entry from the Cloud License history.
......
# frozen_string_literal: true
module Geo
class LfsObjectLegacyRegistryFinder < FileRegistryFinder
def registry_class
Geo::LfsObjectRegistry
end
end
end
# frozen_string_literal: true # frozen_string_literal: true
module Geo module Geo
class LfsObjectRegistryFinder < FileRegistryFinder class LfsObjectRegistryFinder
def registry_class include FrameworkRegistryFinder
Geo::LfsObjectRegistry
end
end end
end end
# frozen_string_literal: true
module Resolvers
module Geo
class LfsObjectRegistriesResolver < BaseResolver
type ::Types::Geo::GeoNodeType.connection_type, null: true
include RegistriesResolver
end
end
end
...@@ -42,6 +42,11 @@ module Types ...@@ -42,6 +42,11 @@ module Types
null: true, null: true,
resolver: ::Resolvers::Geo::GroupWikiRepositoryRegistriesResolver, resolver: ::Resolvers::Geo::GroupWikiRepositoryRegistriesResolver,
description: 'Find group wiki repository registries on this Geo node.' description: 'Find group wiki repository registries on this Geo node.'
field :lfs_object_registries, ::Types::Geo::LfsObjectRegistryType.connection_type,
null: true,
resolver: ::Resolvers::Geo::LfsObjectRegistriesResolver,
description: 'Find LFS object registries on this Geo node.',
feature_flag: :geo_lfs_object_replication
field :pipeline_artifact_registries, ::Types::Geo::PipelineArtifactRegistryType.connection_type, field :pipeline_artifact_registries, ::Types::Geo::PipelineArtifactRegistryType.connection_type,
null: true, null: true,
resolver: ::Resolvers::Geo::PipelineArtifactRegistriesResolver, resolver: ::Resolvers::Geo::PipelineArtifactRegistriesResolver,
......
# frozen_string_literal: true
module Types
module Geo
# rubocop:disable Graphql/AuthorizeTypes because it is included
class LfsObjectRegistryType < BaseObject
include ::Types::Geo::RegistryType
graphql_name 'LfsObjectRegistry'
description 'Represents the Geo sync and verification state of an LFS object'
field :lfs_object_id, GraphQL::ID_TYPE, null: false, description: 'ID of the LFS object.'
end
end
end
...@@ -172,14 +172,6 @@ module EE ...@@ -172,14 +172,6 @@ module EE
name: 'wiki', name: 'wiki',
name_plural: 'wikis' name_plural: 'wikis'
}, },
{
data_type: 'blob',
data_type_title: _('File'),
title: _('LFS object'),
title_plural: _('LFS objects'),
name: 'lfs_object',
name_plural: 'lfs_objects'
},
{ {
data_type: 'blob', data_type: 'blob',
data_type_title: _('File'), data_type_title: _('File'),
...@@ -216,6 +208,17 @@ module EE ...@@ -216,6 +208,17 @@ module EE
} }
] ]
if ::Feature.disabled?(:geo_lfs_object_replication)
replicable_types.insert(2, {
data_type: 'blob',
data_type_title: _('File'),
title: _('LFS object'),
title_plural: _('LFS objects'),
name: 'lfs_object',
name_plural: 'lfs_objects'
})
end
# Adds all the SSF Data Types automatically # Adds all the SSF Data Types automatically
enabled_replicator_classes.each do |replicator_class| enabled_replicator_classes.each do |replicator_class|
replicable_types.push( replicable_types.push(
......
...@@ -223,7 +223,9 @@ module Geo ...@@ -223,7 +223,9 @@ module Geo
# #
# @abstract # @abstract
def primary_checksum def primary_checksum
model_record.verification_checksum # If verification is not yet setup, then model_record will not have the verification_checksum
# attribute yet. Returning nil is fine here
model_record.verification_checksum if model_record.respond_to?(:verification_checksum)
end end
def secondary_checksum def secondary_checksum
......
...@@ -11,6 +11,10 @@ module EE ...@@ -11,6 +11,10 @@ module EE
STORE_COLUMN = :file_store STORE_COLUMN = :file_store
prepended do prepended do
include ::Gitlab::Geo::ReplicableModel
with_replicator Geo::LfsObjectReplicator
after_destroy :log_geo_deleted_event after_destroy :log_geo_deleted_event
scope :project_id_in, ->(ids) { joins(:projects).merge(::Project.id_in(ids)) } scope :project_id_in, ->(ids) { joins(:projects).merge(::Project.id_in(ids)) }
...@@ -21,11 +25,23 @@ module EE ...@@ -21,11 +25,23 @@ module EE
# @return [ActiveRecord::Relation<LfsObject>] everything that should be synced to this node, restricted by primary key # @return [ActiveRecord::Relation<LfsObject>] everything that should be synced to this node, restricted by primary key
def replicables_for_current_secondary(primary_key_in) def replicables_for_current_secondary(primary_key_in)
node = ::Gitlab::Geo.current_node node = ::Gitlab::Geo.current_node
local_storage_only = !node.sync_object_storage node.lfs_objects(primary_key_in: primary_key_in)
.merge(selective_sync_scope(node))
.merge(object_storage_scope(node))
end
private
def object_storage_scope(node)
return all if node.sync_object_storage?
with_files_stored_locally
end
def selective_sync_scope(node)
return all unless node.selective_sync?
scope = node.lfs_objects(primary_key_in: primary_key_in) project_id_in(node.projects)
scope = scope.with_files_stored_locally if local_storage_only
scope
end end
end end
......
# frozen_string_literal: true # frozen_string_literal: true
class Geo::LfsObjectRegistry < Geo::BaseRegistry class Geo::LfsObjectRegistry < Geo::BaseRegistry
include ::ShaAttribute
include ::Geo::Syncable include ::Geo::Syncable
include ::Geo::ReplicableRegistry
include ::ShaAttribute
sha_attribute :sha256
MODEL_CLASS = ::LfsObject MODEL_CLASS = ::LfsObject
MODEL_FOREIGN_KEY = :lfs_object_id MODEL_FOREIGN_KEY = :lfs_object_id
sha_attribute :sha256
belongs_to :lfs_object, class_name: 'LfsObject' belongs_to :lfs_object, class_name: 'LfsObject'
def self.registry_consistency_worker_enabled?
if ::Feature.enabled?(:geo_lfs_object_replication)
replicator_class.enabled?
else
true
end
end
def self.failed
if Feature.enabled?(:geo_lfs_object_replication)
with_state(:failed)
else
where(success: false).where.not(retry_count: nil)
end
end
def self.never_attempted_sync
if Feature.enabled?(:geo_lfs_object_replication)
pending.where(last_synced_at: nil)
else
where(success: false, retry_count: nil)
end
end
def self.retry_due
if Feature.enabled?(:geo_lfs_object_replication)
where(arel_table[:retry_at].eq(nil).or(arel_table[:retry_at].lt(Time.current)))
else
where('retry_at is NULL OR retry_at < ?', Time.current)
end
end
def self.synced
if Feature.enabled?(:geo_lfs_object_replication)
with_state(:synced).or(where(success: true))
else
where(success: true)
end
end
# If false, RegistryConsistencyService will frequently check the end of the # If false, RegistryConsistencyService will frequently check the end of the
# table to quickly handle new replicables. # table to quickly handle new replicables.
def self.has_create_events? def self.has_create_events?
......
...@@ -65,9 +65,6 @@ class GeoNodeStatus < ApplicationRecord ...@@ -65,9 +65,6 @@ class GeoNodeStatus < ApplicationRecord
repositories_synced_count repositories_synced_count
repositories_failed_count repositories_failed_count
lfs_objects_replication_enabled lfs_objects_replication_enabled
lfs_objects_count
lfs_objects_synced_count
lfs_objects_failed_count
attachments_replication_enabled attachments_replication_enabled
attachments_count attachments_count
attachments_synced_count attachments_synced_count
...@@ -84,7 +81,6 @@ class GeoNodeStatus < ApplicationRecord ...@@ -84,7 +81,6 @@ class GeoNodeStatus < ApplicationRecord
wikis_verified_count wikis_verified_count
wikis_verification_failed_count wikis_verification_failed_count
wikis_verification_total_count wikis_verification_total_count
lfs_objects_synced_missing_on_primary_count
job_artifacts_synced_missing_on_primary_count job_artifacts_synced_missing_on_primary_count
attachments_synced_missing_on_primary_count attachments_synced_missing_on_primary_count
repositories_checksummed_count repositories_checksummed_count
...@@ -401,7 +397,6 @@ class GeoNodeStatus < ApplicationRecord ...@@ -401,7 +397,6 @@ class GeoNodeStatus < ApplicationRecord
attr_in_percentage :wikis_synced, :wikis_synced_count, :wikis_count attr_in_percentage :wikis_synced, :wikis_synced_count, :wikis_count
attr_in_percentage :wikis_checksummed, :wikis_checksummed_count, :wikis_count attr_in_percentage :wikis_checksummed, :wikis_checksummed_count, :wikis_count
attr_in_percentage :wikis_verified, :wikis_verified_count, :wikis_count attr_in_percentage :wikis_verified, :wikis_verified_count, :wikis_count
attr_in_percentage :lfs_objects_synced, :lfs_objects_synced_count, :lfs_objects_count
attr_in_percentage :job_artifacts_synced, :job_artifacts_synced_count, :job_artifacts_count attr_in_percentage :job_artifacts_synced, :job_artifacts_synced_count, :job_artifacts_count
attr_in_percentage :attachments_synced, :attachments_synced_count, :attachments_count attr_in_percentage :attachments_synced, :attachments_synced_count, :attachments_count
attr_in_percentage :replication_slots_used, :replication_slots_used_count, :replication_slots_count attr_in_percentage :replication_slots_used, :replication_slots_used_count, :replication_slots_count
...@@ -497,6 +492,7 @@ class GeoNodeStatus < ApplicationRecord ...@@ -497,6 +492,7 @@ class GeoNodeStatus < ApplicationRecord
def load_lfs_objects_data def load_lfs_objects_data
return unless lfs_objects_replication_enabled return unless lfs_objects_replication_enabled
return if Feature.enabled?(:geo_lfs_object_replication)
self.lfs_objects_count = lfs_objects_finder.registry_count self.lfs_objects_count = lfs_objects_finder.registry_count
self.lfs_objects_synced_count = lfs_objects_finder.synced_count self.lfs_objects_synced_count = lfs_objects_finder.synced_count
...@@ -624,7 +620,7 @@ class GeoNodeStatus < ApplicationRecord ...@@ -624,7 +620,7 @@ class GeoNodeStatus < ApplicationRecord
end end
def lfs_objects_finder def lfs_objects_finder
@lfs_objects_finder ||= Geo::LfsObjectRegistryFinder.new @lfs_objects_finder ||= Geo::LfsObjectLegacyRegistryFinder.new
end end
def job_artifacts_finder def job_artifacts_finder
......
# frozen_string_literal: true
module Geo
class LfsObjectReplicator < Gitlab::Geo::Replicator
include ::Geo::BlobReplicatorStrategy
def carrierwave_uploader
model_record.file
end
def self.model
::LfsObject
end
def self.replication_enabled_by_default?
false
end
end
end
...@@ -8,7 +8,7 @@ module Geo ...@@ -8,7 +8,7 @@ module Geo
FILE_SERVICE_OBJECT_TYPE = :lfs FILE_SERVICE_OBJECT_TYPE = :lfs
def registry_finder def registry_finder
@registry_finder ||= Geo::LfsObjectRegistryFinder.new @registry_finder ||= Geo::LfsObjectLegacyRegistryFinder.new
end end
end end
end end
......
---
title: Migrate LFS object replication to use self service framework
merge_request: 56286
author:
type: changed
---
name: geo_lfs_object_replication
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56286
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/276694
milestone: '13.11'
type: development
group: group::geo
default_enabled: false
...@@ -36,7 +36,7 @@ module EE ...@@ -36,7 +36,7 @@ module EE
expose :db_replication_lag_seconds expose :db_replication_lag_seconds
expose :attachments_replication_enabled expose :attachments_replication_enabled
expose :lfs_objects_replication_enabled expose :lfs_objects_replication_enabled, if: -> (*) { ::Feature.enabled?(:geo_lfs_object_replication) }
expose :job_artifacts_replication_enabled expose :job_artifacts_replication_enabled
expose :container_repositories_replication_enabled expose :container_repositories_replication_enabled
expose :design_repositories_replication_enabled expose :design_repositories_replication_enabled
......
...@@ -20,6 +20,7 @@ module Gitlab ...@@ -20,6 +20,7 @@ module Gitlab
# solutions can be found at # solutions can be found at
# https://gitlab.com/gitlab-org/gitlab/-/issues/227693 # https://gitlab.com/gitlab-org/gitlab/-/issues/227693
REPLICATOR_CLASSES = [ REPLICATOR_CLASSES = [
::Geo::LfsObjectReplicator,
::Geo::MergeRequestDiffReplicator, ::Geo::MergeRequestDiffReplicator,
::Geo::PackageFileReplicator, ::Geo::PackageFileReplicator,
::Geo::TerraformStateVersionReplicator, ::Geo::TerraformStateVersionReplicator,
......
...@@ -256,6 +256,8 @@ module Gitlab ...@@ -256,6 +256,8 @@ module Gitlab
end end
def print_lfs_objects_status def print_lfs_objects_status
return if Feature.enabled?(:geo_lfs_object_replication)
print 'LFS Objects: '.rjust(GEO_STATUS_COLUMN_WIDTH) print 'LFS Objects: '.rjust(GEO_STATUS_COLUMN_WIDTH)
show_failed_value(current_node_status.lfs_objects_failed_count) show_failed_value(current_node_status.lfs_objects_failed_count)
print "#{current_node_status.lfs_objects_synced_count}/#{current_node_status.lfs_objects_count} " print "#{current_node_status.lfs_objects_synced_count}/#{current_node_status.lfs_objects_count} "
......
# frozen_string_literal: true # frozen_string_literal: true
FactoryBot.define do FactoryBot.define do
factory :geo_lfs_object_registry, class: 'Geo::LfsObjectRegistry' do factory :geo_lfs_object_legacy_registry, class: 'Geo::LfsObjectRegistry' do
sequence(:lfs_object_id) sequence(:lfs_object_id)
success { true } success { true }
...@@ -23,3 +23,28 @@ FactoryBot.define do ...@@ -23,3 +23,28 @@ FactoryBot.define do
end end
end end
end end
FactoryBot.define do
factory :geo_lfs_object_registry, class: 'Geo::LfsObjectRegistry' do
lfs_object
state { Geo::LfsObjectRegistry.state_value(:pending) }
trait :synced do
state { Geo::LfsObjectRegistry.state_value(:synced) }
last_synced_at { 5.days.ago }
end
trait :failed do
state { Geo::LfsObjectRegistry.state_value(:failed) }
last_synced_at { 1.day.ago }
retry_count { 2 }
last_sync_failure { 'Random error' }
end
trait :started do
state { Geo::LfsObjectRegistry.state_value(:started) }
last_synced_at { 1.day_ago }
retry_count { 0 }
end
end
end
...@@ -11,10 +11,6 @@ FactoryBot.define do ...@@ -11,10 +11,6 @@ FactoryBot.define do
attachments_failed_count { 13 } attachments_failed_count { 13 }
attachments_synced_count { 141 } attachments_synced_count { 141 }
attachments_synced_missing_on_primary_count { 89 } attachments_synced_missing_on_primary_count { 89 }
lfs_objects_count { 256 }
lfs_objects_failed_count { 12 }
lfs_objects_synced_count { 123 }
lfs_objects_synced_missing_on_primary_count { 90 }
job_artifacts_count { 580 } job_artifacts_count { 580 }
job_artifacts_failed_count { 3 } job_artifacts_failed_count { 3 }
job_artifacts_synced_count { 577 } job_artifacts_synced_count { 577 }
...@@ -76,7 +72,6 @@ FactoryBot.define do ...@@ -76,7 +72,6 @@ FactoryBot.define do
trait :replicated_and_verified do trait :replicated_and_verified do
attachments_failed_count { 0 } attachments_failed_count { 0 }
lfs_objects_failed_count { 0 }
job_artifacts_failed_count { 0 } job_artifacts_failed_count { 0 }
container_repositories_failed_count { 0 } container_repositories_failed_count { 0 }
design_repositories_failed_count { 0 } design_repositories_failed_count { 0 }
...@@ -97,7 +92,6 @@ FactoryBot.define do ...@@ -97,7 +92,6 @@ FactoryBot.define do
wikis_checksum_total_count { 10 } wikis_checksum_total_count { 10 }
wikis_verified_count { 10 } wikis_verified_count { 10 }
wikis_verification_total_count { 10 } wikis_verification_total_count { 10 }
lfs_objects_synced_count { 10 }
job_artifacts_synced_count { 10 } job_artifacts_synced_count { 10 }
attachments_synced_count { 10 } attachments_synced_count { 10 }
replication_slots_used_count { 10 } replication_slots_used_count { 10 }
...@@ -106,7 +100,6 @@ FactoryBot.define do ...@@ -106,7 +100,6 @@ FactoryBot.define do
repositories_count { 10 } repositories_count { 10 }
wikis_count { 10 } wikis_count { 10 }
lfs_objects_count { 10 }
job_artifacts_count { 10 } job_artifacts_count { 10 }
attachments_count { 10 } attachments_count { 10 }
replication_slots_count { 10 } replication_slots_count { 10 }
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Geo::LfsObjectLegacyRegistryFinder, :geo do
before do
stub_feature_flags(geo_lfs_object_replication: false )
end
it_behaves_like 'a file registry finder' do
before do
stub_lfs_object_storage
end
let_it_be(:replicable_1) { create(:lfs_object) }
let_it_be(:replicable_2) { create(:lfs_object) }
let_it_be(:replicable_3) { create(:lfs_object) }
let_it_be(:replicable_4) { create(:lfs_object) }
let_it_be(:replicable_5) { create(:lfs_object) }
let!(:replicable_6) { create(:lfs_object, :object_storage) }
let!(:replicable_7) { create(:lfs_object, :object_storage) }
let!(:replicable_8) { create(:lfs_object, :object_storage) }
let_it_be(:registry_1) { create(:geo_lfs_object_legacy_registry, :failed, lfs_object_id: replicable_1.id) }
let_it_be(:registry_2) { create(:geo_lfs_object_legacy_registry, lfs_object_id: replicable_2.id, missing_on_primary: true) }
let_it_be(:registry_3) { create(:geo_lfs_object_legacy_registry, :never_synced, lfs_object_id: replicable_3.id) }
let_it_be(:registry_4) { create(:geo_lfs_object_legacy_registry, :failed, lfs_object_id: replicable_4.id) }
let_it_be(:registry_5) { create(:geo_lfs_object_legacy_registry, lfs_object_id: replicable_5.id, missing_on_primary: true, retry_at: 1.day.ago) }
let!(:registry_6) { create(:geo_lfs_object_legacy_registry, :failed, lfs_object_id: replicable_6.id) }
let!(:registry_7) { create(:geo_lfs_object_legacy_registry, :failed, lfs_object_id: replicable_7.id, missing_on_primary: true) }
let!(:registry_8) { create(:geo_lfs_object_legacy_registry, :never_synced, lfs_object_id: replicable_8.id) }
end
end
...@@ -2,28 +2,6 @@ ...@@ -2,28 +2,6 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Geo::LfsObjectRegistryFinder, :geo do RSpec.describe Geo::LfsObjectRegistryFinder do
it_behaves_like 'a file registry finder' do it_behaves_like 'a framework registry finder', :geo_lfs_object_registry
before do
stub_lfs_object_storage
end
let_it_be(:replicable_1) { create(:lfs_object) }
let_it_be(:replicable_2) { create(:lfs_object) }
let_it_be(:replicable_3) { create(:lfs_object) }
let_it_be(:replicable_4) { create(:lfs_object) }
let_it_be(:replicable_5) { create(:lfs_object) }
let!(:replicable_6) { create(:lfs_object, :object_storage) }
let!(:replicable_7) { create(:lfs_object, :object_storage) }
let!(:replicable_8) { create(:lfs_object, :object_storage) }
let_it_be(:registry_1) { create(:geo_lfs_object_registry, :failed, lfs_object_id: replicable_1.id) }
let_it_be(:registry_2) { create(:geo_lfs_object_registry, lfs_object_id: replicable_2.id, missing_on_primary: true) }
let_it_be(:registry_3) { create(:geo_lfs_object_registry, :never_synced, lfs_object_id: replicable_3.id) }
let_it_be(:registry_4) { create(:geo_lfs_object_registry, :failed, lfs_object_id: replicable_4.id) }
let_it_be(:registry_5) { create(:geo_lfs_object_registry, lfs_object_id: replicable_5.id, missing_on_primary: true, retry_at: 1.day.ago) }
let!(:registry_6) { create(:geo_lfs_object_registry, :failed, lfs_object_id: replicable_6.id) }
let!(:registry_7) { create(:geo_lfs_object_registry, :failed, lfs_object_id: replicable_7.id, missing_on_primary: true) }
let!(:registry_8) { create(:geo_lfs_object_registry, :never_synced, lfs_object_id: replicable_8.id) }
end
end end
...@@ -15,7 +15,14 @@ ...@@ -15,7 +15,14 @@
"lfs_objects_count", "lfs_objects_count",
"lfs_objects_failed_count", "lfs_objects_failed_count",
"lfs_objects_synced_count", "lfs_objects_synced_count",
"lfs_objects_synced_missing_on_primary_count", "lfs_objects_checksum_total_count",
"lfs_objects_checksummed_count",
"lfs_objects_checksum_failed_count",
"lfs_objects_registry_count",
"lfs_objects_verification_total_count",
"lfs_objects_verified_count",
"lfs_objects_verified_in_percentage",
"lfs_objects_verification_failed_count",
"job_artifacts_replication_enabled", "job_artifacts_replication_enabled",
"job_artifacts_count", "job_artifacts_count",
"job_artifacts_failed_count", "job_artifacts_failed_count",
...@@ -170,6 +177,14 @@ ...@@ -170,6 +177,14 @@
"lfs_objects_synced_count": { "type": ["integer", "null"] }, "lfs_objects_synced_count": { "type": ["integer", "null"] },
"lfs_objects_synced_missing_on_primary_count": { "type": ["integer", "null"] }, "lfs_objects_synced_missing_on_primary_count": { "type": ["integer", "null"] },
"lfs_objects_synced_in_percentage": { "type": "string" }, "lfs_objects_synced_in_percentage": { "type": "string" },
"lfs_objects_checksum_total_count": { "type": ["integer", "null"] },
"lfs_objects_checksummed_count": { "type": ["integer", "null"] },
"lfs_objects_checksum_failed_count": { "type": ["integer", "null"] },
"lfs_objects_registry_count": { "type": ["integer", "null"] },
"lfs_objects_verification_total_count": { "type": ["integer", "null"] },
"lfs_objects_verified_count": { "type": ["integer", "null"] },
"lfs_objects_verified_in_percentage": { "type": "string" },
"lfs_objects_verification_failed_count": { "type": ["integer", "null"] },
"job_artifacts_replication_enabled": { "type": ["boolean", "null"] }, "job_artifacts_replication_enabled": { "type": ["boolean", "null"] },
"job_artifacts_count": { "type": "integer" }, "job_artifacts_count": { "type": "integer" },
"job_artifacts_failed_count": { "type": ["integer", "null"] }, "job_artifacts_failed_count": { "type": ["integer", "null"] },
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Resolvers::Geo::LfsObjectRegistriesResolver do
it_behaves_like 'a Geo registries resolver', :geo_lfs_object_registry
end
...@@ -14,6 +14,7 @@ RSpec.describe GitlabSchema.types['GeoNode'] do ...@@ -14,6 +14,7 @@ RSpec.describe GitlabSchema.types['GeoNode'] do
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 group_wiki_repository_registries terraform_state_version_registries group_wiki_repository_registries
lfs_object_registries
pipeline_artifact_registries pipeline_artifact_registries
] ]
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['LfsObjectRegistry'] do
it_behaves_like 'a Geo registry type'
it 'has the expected fields (other than those included in RegistryType)' do
expected_fields = %i[lfs_object_id]
expect(described_class).to have_graphql_fields(*expected_fields).at_least
end
end
...@@ -5,7 +5,7 @@ require 'spec_helper' ...@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe EE::API::Entities::GeoNodeStatus do RSpec.describe EE::API::Entities::GeoNodeStatus do
include ::EE::GeoHelpers include ::EE::GeoHelpers
let(:geo_node_status) { build(:geo_node_status) } let!(:geo_node_status) { build(:geo_node_status) }
let(:entity) { described_class.new(geo_node_status, request: double) } let(:entity) { described_class.new(geo_node_status, request: double) }
let(:error) { 'Could not connect to Geo database' } let(:error) { 'Could not connect to Geo database' }
...@@ -66,12 +66,18 @@ RSpec.describe EE::API::Entities::GeoNodeStatus do ...@@ -66,12 +66,18 @@ RSpec.describe EE::API::Entities::GeoNodeStatus do
end end
describe '#lfs_objects_synced_in_percentage' do describe '#lfs_objects_synced_in_percentage' do
it 'formats as percentage' do context 'LFS with SSF is disabled' do
geo_node_status.assign_attributes(lfs_objects_count: 256, before do
lfs_objects_failed_count: 12, stub_feature_flags(geo_lfs_object_replication: false)
lfs_objects_synced_count: 123) end
expect(subject[:lfs_objects_synced_in_percentage]).to eq '48.05%' it 'formats as percentage' do
geo_node_status.assign_attributes(lfs_objects_registry_count: 256,
lfs_objects_failed_count: 12,
lfs_objects_synced_count: 123)
expect(subject[:lfs_objects_synced_in_percentage]).to eq '48.05%'
end
end end
end end
......
...@@ -16,22 +16,28 @@ RSpec.describe Gitlab::Geo::GeoNodeStatusCheck do ...@@ -16,22 +16,28 @@ RSpec.describe Gitlab::Geo::GeoNodeStatusCheck do
allow(Gitlab.config.geo.registry_replication).to receive(:enabled).and_return(true) allow(Gitlab.config.geo.registry_replication).to receive(:enabled).and_return(true)
end end
it 'prints messages for all legacy replication and verification checks' do context 'with legacy replication' do
checks = [ before do
/Repositories: /, stub_feature_flags(geo_lfs_object_replication: false)
/Verified Repositories: /, end
/Wikis: /,
/Verified Wikis: /, it 'prints messages for all legacy replication and verification checks' do
/LFS Objects: /, checks = [
/Attachments: /, /Repositories: /,
/CI job artifacts: /, /Verified Repositories: /,
/Container repositories: /, /Wikis: /,
/Design repositories: /, /Verified Wikis: /,
/Repositories Checked: / /LFS Objects: /,
] /Attachments: /,
/CI job artifacts: /,
checks.each do |text| /Container repositories: /,
expect { subject.print_replication_verification_status }.to output(text).to_stdout /Design repositories: /,
/Repositories Checked: /
]
checks.each do |text|
expect { subject.print_replication_verification_status }.to output(text).to_stdout
end
end end
end end
......
...@@ -6,7 +6,7 @@ RSpec.describe Geo::LfsObjectRegistry, :geo do ...@@ -6,7 +6,7 @@ RSpec.describe Geo::LfsObjectRegistry, :geo do
include EE::GeoHelpers include EE::GeoHelpers
it_behaves_like 'a BulkInsertSafe model', Geo::LfsObjectRegistry do it_behaves_like 'a BulkInsertSafe model', Geo::LfsObjectRegistry do
let(:valid_items_for_bulk_insertion) { build_list(:geo_lfs_object_registry, 10) } let(:valid_items_for_bulk_insertion) { build_list(:geo_lfs_object_legacy_registry, 10) }
let(:invalid_items_for_bulk_insertion) { [] } # class does not have any validations defined let(:invalid_items_for_bulk_insertion) { [] } # class does not have any validations defined
end end
...@@ -41,9 +41,9 @@ RSpec.describe Geo::LfsObjectRegistry, :geo do ...@@ -41,9 +41,9 @@ RSpec.describe Geo::LfsObjectRegistry, :geo do
context 'untracked IDs' do context 'untracked IDs' do
before do before do
create(:geo_lfs_object_registry, lfs_object_id: lfs_object_1.id) create(:geo_lfs_object_legacy_registry, lfs_object_id: lfs_object_1.id)
create(:geo_lfs_object_registry, :failed, lfs_object_id: lfs_object_3.id) create(:geo_lfs_object_legacy_registry, :failed, lfs_object_id: lfs_object_3.id)
create(:geo_lfs_object_registry, lfs_object_id: lfs_object_4.id) create(:geo_lfs_object_legacy_registry, lfs_object_id: lfs_object_4.id)
create(:lfs_objects_project, project: synced_project, lfs_object: lfs_object_1) create(:lfs_objects_project, project: synced_project, lfs_object: lfs_object_1)
create(:lfs_objects_project, project: synced_project_in_nested_group, lfs_object: lfs_object_2) create(:lfs_objects_project, project: synced_project_in_nested_group, lfs_object: lfs_object_2)
...@@ -101,7 +101,7 @@ RSpec.describe Geo::LfsObjectRegistry, :geo do ...@@ -101,7 +101,7 @@ RSpec.describe Geo::LfsObjectRegistry, :geo do
context 'unused tracked IDs' do context 'unused tracked IDs' do
context 'with an orphaned registry' do context 'with an orphaned registry' do
let!(:orphaned) { create(:geo_lfs_object_registry, lfs_object_id: non_existing_record_id) } let!(:orphaned) { create(:geo_lfs_object_legacy_registry, lfs_object_id: non_existing_record_id) }
it 'includes tracked IDs that do not exist in the model table' do it 'includes tracked IDs that do not exist in the model table' do
range = non_existing_record_id..non_existing_record_id range = non_existing_record_id..non_existing_record_id
...@@ -124,7 +124,7 @@ RSpec.describe Geo::LfsObjectRegistry, :geo do ...@@ -124,7 +124,7 @@ RSpec.describe Geo::LfsObjectRegistry, :geo do
let(:secondary) { create(:geo_node, selective_sync_type: 'namespaces', namespaces: [synced_group]) } let(:secondary) { create(:geo_node, selective_sync_type: 'namespaces', namespaces: [synced_group]) }
context 'with a tracked LFS object' do context 'with a tracked LFS object' do
let!(:registry_entry) { create(:geo_lfs_object_registry, lfs_object_id: lfs_object_1.id) } let!(:registry_entry) { create(:geo_lfs_object_legacy_registry, lfs_object_id: lfs_object_1.id) }
let(:range) { lfs_object_1.id..lfs_object_1.id } let(:range) { lfs_object_1.id..lfs_object_1.id }
context 'excluded from selective sync' do context 'excluded from selective sync' do
...@@ -151,7 +151,7 @@ RSpec.describe Geo::LfsObjectRegistry, :geo do ...@@ -151,7 +151,7 @@ RSpec.describe Geo::LfsObjectRegistry, :geo do
let(:secondary) { create(:geo_node, selective_sync_type: 'shards', selective_sync_shards: ['broken']) } let(:secondary) { create(:geo_node, selective_sync_type: 'shards', selective_sync_shards: ['broken']) }
context 'with a tracked LFS object' do context 'with a tracked LFS object' do
let!(:registry_entry) { create(:geo_lfs_object_registry, lfs_object_id: lfs_object_1.id) } let!(:registry_entry) { create(:geo_lfs_object_legacy_registry, lfs_object_id: lfs_object_1.id) }
let(:range) { lfs_object_1.id..lfs_object_1.id } let(:range) { lfs_object_1.id..lfs_object_1.id }
context 'excluded from selective sync' do context 'excluded from selective sync' do
...@@ -180,7 +180,7 @@ RSpec.describe Geo::LfsObjectRegistry, :geo do ...@@ -180,7 +180,7 @@ RSpec.describe Geo::LfsObjectRegistry, :geo do
context 'with a tracked LFS object' do context 'with a tracked LFS object' do
context 'in object storage' do context 'in object storage' do
it 'includes tracked LFS object IDs that are in object storage' do it 'includes tracked LFS object IDs that are in object storage' do
create(:geo_lfs_object_registry, lfs_object_id: lfs_object_remote_1.id) create(:geo_lfs_object_legacy_registry, lfs_object_id: lfs_object_remote_1.id)
range = lfs_object_remote_1.id..lfs_object_remote_1.id range = lfs_object_remote_1.id..lfs_object_remote_1.id
_, unused_tracked_ids = described_class.find_registry_differences(range) _, unused_tracked_ids = described_class.find_registry_differences(range)
...@@ -191,7 +191,7 @@ RSpec.describe Geo::LfsObjectRegistry, :geo do ...@@ -191,7 +191,7 @@ RSpec.describe Geo::LfsObjectRegistry, :geo do
context 'not in object storage' do context 'not in object storage' do
it 'excludes tracked LFS object IDs that are not in object storage' do it 'excludes tracked LFS object IDs that are not in object storage' do
create(:geo_lfs_object_registry, lfs_object_id: lfs_object_1.id) create(:geo_lfs_object_legacy_registry, lfs_object_id: lfs_object_1.id)
range = lfs_object_1.id..lfs_object_1.id range = lfs_object_1.id..lfs_object_1.id
_, unused_tracked_ids = described_class.find_registry_differences(range) _, unused_tracked_ids = described_class.find_registry_differences(range)
...@@ -204,3 +204,13 @@ RSpec.describe Geo::LfsObjectRegistry, :geo do ...@@ -204,3 +204,13 @@ RSpec.describe Geo::LfsObjectRegistry, :geo do
end end
end end
end end
RSpec.describe Geo::LfsObjectRegistry, :geo, type: :model do
let_it_be(:registry) { create(:geo_lfs_object_registry) }
specify 'factory is valid' do
expect(registry).to be_valid
end
include_examples 'a Geo framework registry'
end
...@@ -173,7 +173,7 @@ RSpec.describe GeoNodeStatus, :geo do ...@@ -173,7 +173,7 @@ RSpec.describe GeoNodeStatus, :geo do
describe '#attachments_failed_count' do describe '#attachments_failed_count' do
it 'counts failed avatars, attachment, personal snippets and files' do it 'counts failed avatars, attachment, personal snippets and files' do
# These two should be ignored # These two should be ignored
create(:geo_lfs_object_registry, :with_lfs_object, :failed) create(:geo_lfs_object_legacy_registry, :with_lfs_object, :failed)
create(:geo_upload_registry, :with_file) create(:geo_upload_registry, :with_file)
create(:geo_upload_registry, :with_file, :failed, file_type: :personal_file) create(:geo_upload_registry, :with_file, :failed, file_type: :personal_file)
...@@ -219,60 +219,54 @@ RSpec.describe GeoNodeStatus, :geo do ...@@ -219,60 +219,54 @@ RSpec.describe GeoNodeStatus, :geo do
end end
end end
describe '#lfs_objects_synced_count' do context 'LFS replication with SSF is disabled' do
it 'counts synced LFS objects' do before do
# These four should be ignored stub_feature_flags(geo_lfs_object_replication: false)
create(:geo_upload_registry, :failed)
create(:geo_upload_registry, :avatar)
create(:geo_upload_registry, file_type: :attachment)
create(:geo_lfs_object_registry, :failed)
create(:geo_lfs_object_registry)
expect(subject.lfs_objects_synced_count).to eq(1)
end end
end
describe '#lfs_objects_synced_missing_on_primary_count' do describe '#lfs_objects_synced_count' do
it 'counts LFS objects marked as synced due to file missing on the primary' do it 'counts synced LFS objects' do
# These four should be ignored # These four should be ignored
create(:geo_upload_registry, :failed) create(:geo_upload_registry, :failed)
create(:geo_upload_registry, :avatar, missing_on_primary: true) create(:geo_upload_registry, :avatar)
create(:geo_upload_registry, file_type: :attachment, missing_on_primary: true) create(:geo_upload_registry, file_type: :attachment)
create(:geo_lfs_object_registry, :failed) create(:geo_lfs_object_legacy_registry, :failed)
create(:geo_lfs_object_legacy_registry)
create(:geo_lfs_object_registry, missing_on_primary: true) create(:geo_lfs_object_legacy_registry, missing_on_primary: true)
expect(subject.lfs_objects_synced_missing_on_primary_count).to eq(1) expect(subject.lfs_objects_synced_missing_on_primary_count).to eq(1)
end
end end
end
describe '#lfs_objects_failed_count' do describe '#lfs_objects_failed_count' do
it 'counts failed LFS objects' do it 'counts failed LFS objects' do
# These four should be ignored # These four should be ignored
create(:geo_upload_registry, :failed) create(:geo_upload_registry, :failed)
create(:geo_upload_registry, :avatar, :failed) create(:geo_upload_registry, :avatar, :failed)
create(:geo_upload_registry, :failed, file_type: :attachment) create(:geo_upload_registry, :failed, file_type: :attachment)
create(:geo_lfs_object_registry) create(:geo_lfs_object_legacy_registry)
create(:geo_lfs_object_registry, :failed) create(:geo_lfs_object_legacy_registry, :failed)
expect(subject.lfs_objects_failed_count).to eq(1) expect(subject.lfs_objects_failed_count).to eq(1)
end
end end
end
describe '#lfs_objects_synced_in_percentage' do describe '#lfs_objects_synced_in_percentage' do
it 'returns 0 when there are no registries' do it 'returns 0 when there are no registries' do
expect(subject.lfs_objects_synced_in_percentage).to eq(0) expect(subject.lfs_objects_synced_in_percentage).to eq(0)
end end
it 'returns the right percentage' do it 'returns the right percentage' do
create(:geo_lfs_object_registry) create(:geo_lfs_object_legacy_registry)
create(:geo_lfs_object_registry, :failed) create(:geo_lfs_object_legacy_registry, :failed)
create(:geo_lfs_object_registry, :never_synced) create(:geo_lfs_object_legacy_registry, :never_synced)
create(:geo_lfs_object_registry, :never_synced) create(:geo_lfs_object_legacy_registry, :never_synced)
expect(subject.lfs_objects_synced_in_percentage).to be_within(0.0001).of(25) expect(subject.lfs_objects_synced_in_percentage).to be_within(0.0001).of(25)
end
end end
end end
...@@ -1180,6 +1174,7 @@ RSpec.describe GeoNodeStatus, :geo do ...@@ -1180,6 +1174,7 @@ RSpec.describe GeoNodeStatus, :geo do
context 'Replicator stats' do context 'Replicator stats' do
where(:replicator, :model_factory, :registry_factory) do where(:replicator, :model_factory, :registry_factory) do
Geo::LfsObjectReplicator | :lfs_object | :geo_lfs_object_registry
Geo::MergeRequestDiffReplicator | :external_merge_request_diff | :geo_merge_request_diff_registry Geo::MergeRequestDiffReplicator | :external_merge_request_diff | :geo_merge_request_diff_registry
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
...@@ -1400,7 +1395,7 @@ RSpec.describe GeoNodeStatus, :geo do ...@@ -1400,7 +1395,7 @@ RSpec.describe GeoNodeStatus, :geo do
end end
it 'does not call LfsObjectRegistryFinder#registry_count' do it 'does not call LfsObjectRegistryFinder#registry_count' do
expect_any_instance_of(Geo::LfsObjectRegistryFinder).not_to receive(:registry_count) expect_any_instance_of(Geo::LfsObjectLegacyRegistryFinder).not_to receive(:registry_count)
subject subject
end end
...@@ -1420,7 +1415,8 @@ RSpec.describe GeoNodeStatus, :geo do ...@@ -1420,7 +1415,8 @@ RSpec.describe GeoNodeStatus, :geo do
context 'on the secondary' do context 'on the secondary' do
it 'calls LfsObjectRegistryFinder#registry_count' do it 'calls LfsObjectRegistryFinder#registry_count' do
expect_any_instance_of(Geo::LfsObjectRegistryFinder).to receive(:registry_count).twice stub_feature_flags(geo_lfs_object_replication: false)
expect_any_instance_of(Geo::LfsObjectLegacyRegistryFinder).to receive(:registry_count).twice
subject subject
end end
......
...@@ -5,6 +5,10 @@ require 'spec_helper' ...@@ -5,6 +5,10 @@ require 'spec_helper'
RSpec.describe LfsObject do RSpec.describe LfsObject do
include EE::GeoHelpers include EE::GeoHelpers
before do
stub_feature_flags(geo_lfs_object_replication: false)
end
describe '#destroy' do describe '#destroy' do
subject { create(:lfs_object, :with_file) } subject { create(:lfs_object, :with_file) }
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Geo::LfsObjectReplicator do
let(:model_record) { build(:lfs_object, :with_file) }
it_behaves_like 'a blob replicator'
end
...@@ -38,6 +38,13 @@ RSpec.describe 'Gets registries' do ...@@ -38,6 +38,13 @@ RSpec.describe 'Gets registries' do
registry_foreign_key_field_name: 'groupWikiRepositoryId' registry_foreign_key_field_name: 'groupWikiRepositoryId'
} }
it_behaves_like 'gets registries for', {
field_name: 'lfsObjectRegistries',
registry_class_name: 'LfsObjectRegistry',
registry_factory: :geo_lfs_object_registry,
registry_foreign_key_field_name: 'lfsObjectId'
}
it_behaves_like 'gets registries for', { it_behaves_like 'gets registries for', {
field_name: 'pipelineArtifactRegistries', field_name: 'pipelineArtifactRegistries',
registry_class_name: 'PipelineArtifactRegistry', registry_class_name: 'PipelineArtifactRegistry',
......
...@@ -441,6 +441,10 @@ RSpec.describe Geo::FileDownloadService do ...@@ -441,6 +441,10 @@ RSpec.describe Geo::FileDownloadService do
end end
context 'LFS object' do context 'LFS object' do
before do
stub_feature_flags(geo_lfs_object_replication: false)
end
it_behaves_like "a service that downloads the file and registers the sync result", 'lfs' do it_behaves_like "a service that downloads the file and registers the sync result", 'lfs' do
let(:file) { create(:lfs_object) } let(:file) { create(:lfs_object) }
end end
......
...@@ -317,6 +317,29 @@ RSpec.describe 'geo rake tasks', :geo do ...@@ -317,6 +317,29 @@ RSpec.describe 'geo rake tasks', :geo do
let!(:primary_node) { create(:geo_node, :primary) } let!(:primary_node) { create(:geo_node, :primary) }
let!(:geo_event_log) { create(:geo_event_log) } let!(:geo_event_log) { create(:geo_event_log) }
let!(:geo_node_status) { build(:geo_node_status, :healthy, geo_node: current_node) } let!(:geo_node_status) { build(:geo_node_status, :healthy, geo_node: current_node) }
let(:checks) do
[
/Name: /,
/URL: /,
/GitLab Version: /,
/Geo Role: /,
/Health Status: /,
/Sync Settings: /,
/Database replication lag: /,
/Repositories: /,
/Verified Repositories: /,
/Wikis: /,
/Verified Wikis: /,
/Attachments: /,
/CI job artifacts: /,
/Container repositories: /,
/Design repositories: /,
/Repositories Checked: /,
/Last event ID seen from primary: /,
/Last status report was: /
] + Gitlab::Geo.verification_enabled_replicator_classes.map { |k| /#{k.replicable_title_plural} Verified:/ } +
Gitlab::Geo.enabled_replicator_classes.map { |k| /#{k.replicable_title_plural}:/ }
end
before do before do
stub_licensed_features(geo: true) stub_licensed_features(geo: true)
...@@ -343,32 +366,23 @@ RSpec.describe 'geo rake tasks', :geo do ...@@ -343,32 +366,23 @@ RSpec.describe 'geo rake tasks', :geo do
expect { run_rake_task('geo:status') }.not_to output(/Health Status Summary/).to_stdout expect { run_rake_task('geo:status') }.not_to output(/Health Status Summary/).to_stdout
end end
it 'prints messages for all the checks' do context 'with legacy LFS replication enabled' do
checks = [ before do
/Name: /, stub_feature_flags(geo_lfs_object_replication: false)
/URL: /, end
/GitLab Version: /,
/Geo Role: /, it 'prints messages for all the checks' do
/Health Status: /, (checks << /LFS Objects: /).each do |text|
/Sync Settings: /, expect { run_rake_task('geo:status') }.to output(text).to_stdout
/Database replication lag: /, end
/Repositories: /, end
/Verified Repositories: /, end
/Wikis: /,
/Verified Wikis: /, context 'with SSF LFS replication eneabled' do
/LFS Objects: /, it 'prints messages for all the checks' do
/Attachments: /, checks.each do |text|
/CI job artifacts: /, expect { run_rake_task('geo:status') }.to output(text).to_stdout
/Container repositories: /, end
/Design repositories: /,
/Repositories Checked: /,
/Last event ID seen from primary: /,
/Last status report was: /
] + Gitlab::Geo.verification_enabled_replicator_classes.map { |k| /#{k.replicable_title_plural} Verified:/ } +
Gitlab::Geo.enabled_replicator_classes.map { |k| /#{k.replicable_title_plural}:/ }
checks.each do |text|
expect { run_rake_task('geo:status') }.to output(text).to_stdout
end end
end end
end end
......
...@@ -12,6 +12,7 @@ RSpec.describe Geo::FileDownloadDispatchWorker, :geo, :use_sql_query_cache_for_t ...@@ -12,6 +12,7 @@ RSpec.describe Geo::FileDownloadDispatchWorker, :geo, :use_sql_query_cache_for_t
before do before do
stub_current_geo_node(secondary) stub_current_geo_node(secondary)
stub_exclusive_lease(renew: true) stub_exclusive_lease(renew: true)
stub_feature_flags(geo_lfs_object_replication: false)
allow_next_instance_of(described_class) do |instance| allow_next_instance_of(described_class) do |instance|
allow(instance).to receive(:over_time?).and_return(false) allow(instance).to receive(:over_time?).and_return(false)
end end
...@@ -47,8 +48,8 @@ RSpec.describe Geo::FileDownloadDispatchWorker, :geo, :use_sql_query_cache_for_t ...@@ -47,8 +48,8 @@ RSpec.describe Geo::FileDownloadDispatchWorker, :geo, :use_sql_query_cache_for_t
it 'does not schedule duplicated jobs' do it 'does not schedule duplicated jobs' do
lfs_object_1 = create(:lfs_object, :with_file) lfs_object_1 = create(:lfs_object, :with_file)
lfs_object_2 = create(:lfs_object, :with_file) lfs_object_2 = create(:lfs_object, :with_file)
create(:geo_lfs_object_registry, :never_synced, lfs_object: lfs_object_1) create(:geo_lfs_object_legacy_registry, :never_synced, lfs_object: lfs_object_1)
create(:geo_lfs_object_registry, :failed, lfs_object: lfs_object_2) create(:geo_lfs_object_legacy_registry, :failed, lfs_object: lfs_object_2)
stub_const('Geo::Scheduler::SchedulerWorker::DB_RETRIEVE_BATCH_SIZE', 5) stub_const('Geo::Scheduler::SchedulerWorker::DB_RETRIEVE_BATCH_SIZE', 5)
secondary.update!(files_max_capacity: 4) secondary.update!(files_max_capacity: 4)
...@@ -65,9 +66,9 @@ RSpec.describe Geo::FileDownloadDispatchWorker, :geo, :use_sql_query_cache_for_t ...@@ -65,9 +66,9 @@ RSpec.describe Geo::FileDownloadDispatchWorker, :geo, :use_sql_query_cache_for_t
lfs_object_1 = create(:lfs_object, :with_file) lfs_object_1 = create(:lfs_object, :with_file)
lfs_object_2 = create(:lfs_object, :with_file) lfs_object_2 = create(:lfs_object, :with_file)
lfs_object_3 = create(:lfs_object, :with_file) lfs_object_3 = create(:lfs_object, :with_file)
create(:geo_lfs_object_registry, :never_synced, lfs_object: lfs_object_1) create(:geo_lfs_object_legacy_registry, :never_synced, lfs_object: lfs_object_1)
create(:geo_lfs_object_registry, :never_synced, lfs_object: lfs_object_2) create(:geo_lfs_object_legacy_registry, :never_synced, lfs_object: lfs_object_2)
create(:geo_lfs_object_registry, :never_synced, lfs_object: lfs_object_3) create(:geo_lfs_object_legacy_registry, :never_synced, lfs_object: lfs_object_3)
stub_const('Geo::Scheduler::SchedulerWorker::DB_RETRIEVE_BATCH_SIZE', 3) stub_const('Geo::Scheduler::SchedulerWorker::DB_RETRIEVE_BATCH_SIZE', 3)
secondary.update!(files_max_capacity: 6) secondary.update!(files_max_capacity: 6)
...@@ -205,8 +206,8 @@ RSpec.describe Geo::FileDownloadDispatchWorker, :geo, :use_sql_query_cache_for_t ...@@ -205,8 +206,8 @@ RSpec.describe Geo::FileDownloadDispatchWorker, :geo, :use_sql_query_cache_for_t
context 'with lfs_object_registry entries' do context 'with lfs_object_registry entries' do
before do before do
create(:geo_lfs_object_registry, :never_synced, lfs_object: lfs_object_local_store) create(:geo_lfs_object_legacy_registry, :never_synced, lfs_object: lfs_object_local_store)
create(:geo_lfs_object_registry, :failed, lfs_object: lfs_object_remote_store) create(:geo_lfs_object_legacy_registry, :failed, lfs_object: lfs_object_remote_store)
Geo::LfsObjectRegistry.create!(lfs_object_id: lfs_object_file_missing_on_primary.id, bytes: 1234, success: true, missing_on_primary: true) Geo::LfsObjectRegistry.create!(lfs_object_id: lfs_object_file_missing_on_primary.id, bytes: 1234, success: true, missing_on_primary: true)
end end
...@@ -372,7 +373,7 @@ RSpec.describe Geo::FileDownloadDispatchWorker, :geo, :use_sql_query_cache_for_t ...@@ -372,7 +373,7 @@ RSpec.describe Geo::FileDownloadDispatchWorker, :geo, :use_sql_query_cache_for_t
result_object = double(:result, success: true, bytes_downloaded: 100, primary_missing_file: false) result_object = double(:result, success: true, bytes_downloaded: 100, primary_missing_file: false)
allow_any_instance_of(::Gitlab::Geo::Replication::BaseTransfer).to receive(:download_from_primary).and_return(result_object) allow_any_instance_of(::Gitlab::Geo::Replication::BaseTransfer).to receive(:download_from_primary).and_return(result_object)
create_list(:geo_lfs_object_registry, 2, :with_lfs_object, :never_synced) create_list(:geo_lfs_object_legacy_registry, 2, :with_lfs_object, :never_synced)
create_list(:geo_upload_registry, 2, :avatar, :with_file, :never_synced) create_list(:geo_upload_registry, 2, :avatar, :with_file, :never_synced)
create_list(:geo_upload_registry, 2, :attachment, :with_file, :never_synced) create_list(:geo_upload_registry, 2, :attachment, :with_file, :never_synced)
create(:geo_upload_registry, :favicon, :with_file, :never_synced) create(:geo_upload_registry, :favicon, :with_file, :never_synced)
......
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