Commit 47da223c authored by Grzegorz Bizon's avatar Grzegorz Bizon

Refactor build trace to use generic consistency guarantees

This commit adds `Gitlab::Database::Consistency` helper that makes it
easier to ensure consistent reads in GitLab CE.
parent 6a987b95
......@@ -76,6 +76,20 @@ module Ci
end
end
##
# Sometime we need to ensure that the first read goes to a primary
# database, what is especially important in EE. This method does not
# change the behavior in CE.
#
def with_consistent_reads(project, &block)
return yield unless Feature.enabled?(
:gitlab_ci_trace_read_consistency, project, type: :development, default_enabled: false
)
::Gitlab::Database::Consistency
.with_read_consistency(&block)
end
##
# Sometimes we do not want to read raw data. This method makes it easier
# to find attributes that are just metadata excluding raw data.
......@@ -154,14 +168,7 @@ module Ci
in_lock(lock_key, **lock_params) do # exclusive Redis lock is acquired first
raise FailedToPersistDataError, 'Modifed build trace chunk detected' if has_changes_to_save?
##
# We use primary data source (in EE it is a primary database) and
# reload `lock_version` before we migrate the data to persistent
# storage and update data store location of the chunk.
#
# TODO we also need to stick the chunk to primary
#
::Gitlab::Ci::Trace::Metadata.using_primary_source do
self.class.with_consistent_reads(build.project) do
self.reset.then { |chunk| chunk.unsafe_persist_data! }
end
end
......
---
name: gitlab_ci_trace_read_consistency
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46976
rollout_issue_url:
milestone: '13.9'
type: development
group: group::continuous integration
default_enabled: false
# frozen_string_literal: true
module EE
module Gitlab
module Ci
module Trace
module Metadata
extend ::Gitlab::Utils::Override
##
# In EE we are disabling the database load balancing for requests
# that attempt to read trace metadata before we actually perform a
# write.
#
# This ensures that we are reading the latest build trace chunks,
# pending states and checksums.
#
override :use_primary
def use_primary(&block)
::Gitlab::Database::LoadBalancing::Session
.current.use_primary(&block)
end
end
end
end
end
end
# frozen_string_literal: true
module EE
module Gitlab
module Database
module Consistency
extend ::Gitlab::Utils::Override
##
# In EE we are disabling the database load balancing for calls that
# require read consistency after recent writes.
#
override :use_primary
def use_primary(&block)
::Gitlab::Database::LoadBalancing::Session
.current.use_primary(&block)
end
end
end
end
end
......@@ -31,7 +31,7 @@ module Gitlab
def state_crc32
strong_memoize(:state_crc32) do
Trace::Metadata.using_primary_source do
::Gitlab::Database::Consistency.with_read_consistency do
build.pending_state&.crc32
end
end
......@@ -63,7 +63,7 @@ module Gitlab
#
def trace_chunks
strong_memoize(:trace_chunks) do
Trace::Metadata.using_primary_source do
Ci::BuildTraceChunks.with_read_consistency(build.project) do
build.trace_chunks.persisted
.select(::Ci::BuildTraceChunk.metadata_attributes)
end
......
# frozen_string_literal: true
module Gitlab
module Ci
class Trace
##
# Class that describes CI/CD build logs metadata (chunks, pending
# states, checksums) and their datastore.
#
class Metadata
def self.using_primary_source(&block)
self.new.use_primary(&block)
end
##
# This method is overriden in EE to make sure we can disable database
# load balancing when reading trace metadata. Here, it simply yields.
#
def use_primary(&block)
yield
end
end
end
end
end
::Gitlab::Ci::Trace::Metadata.prepend_if_ee('EE::Gitlab::Ci::Trace::Metadata')
# frozen_string_literal: true
module Gitlab
module Database
##
# This class is used to make it possible to ensure read consistency in
# GitLab EE without the need of overriding a lot of methods / classes /
# modules.
#
# This is a CE class that does nothing in CE, because database load
# balancing is EE-only feature, but you can still use it in CE. It will
# start ensuring read consistency once it is overridden in EE.
#
# Using this class in CE helps to avoid creeping discrepancy between CE /
# EE only to force usage of the primary database in EE.
#
class Consistency
def self.with_read_consistency(&block)
self.new.use_primary(&block)
end
##
# In CE there is no database load balancing, so all reads are expected to
# be consistent by the ACID guarantees of a single PostgreSQL instance.
#
# This method is overridden in EE.
#
def use_primary(&block)
yield
end
end
end
end
::Gitlab::Database::Consistency.prepend_if_ee('EE::Gitlab::Database::Consistency')
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