mirror of
https://github.com/gitlabhq/gitlabhq.git
synced 2025-07-23 00:45:28 +00:00
89 lines
2.5 KiB
Ruby
89 lines
2.5 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Ci
|
|
class BuildTraceMetadata < Ci::ApplicationRecord
|
|
include Ci::Partitionable
|
|
|
|
MAX_ATTEMPTS = 5
|
|
self.table_name = :p_ci_build_trace_metadata
|
|
self.primary_key = :build_id
|
|
|
|
before_validation :set_project_id
|
|
|
|
belongs_to :build,
|
|
->(trace_metadata) { in_partition(trace_metadata) },
|
|
class_name: 'Ci::Build',
|
|
partition_foreign_key: :partition_id,
|
|
inverse_of: :trace_metadata
|
|
|
|
belongs_to :trace_artifact, # rubocop:disable Rails/InverseOf -- No clear relation to be used
|
|
->(metadata) { in_partition(metadata) },
|
|
class_name: 'Ci::JobArtifact',
|
|
partition_foreign_key: :partition_id
|
|
|
|
partitionable scope: :build, partitioned: true
|
|
|
|
validates :build, presence: true
|
|
validates :archival_attempts, presence: true
|
|
|
|
def self.find_or_upsert_for!(build_id, partition_id, project_id)
|
|
record = find_by(build_id: build_id, partition_id: partition_id)
|
|
return record if record
|
|
|
|
upsert({ build_id: build_id, partition_id: partition_id, project_id: project_id },
|
|
unique_by: %w[build_id partition_id])
|
|
find_by!(build_id: build_id, partition_id: partition_id)
|
|
end
|
|
|
|
# The job is retried around 5 times during the 7 days retention period for
|
|
# trace chunks as defined in `Ci::BuildTraceChunks::RedisBase::CHUNK_REDIS_TTL`
|
|
def can_attempt_archival_now?
|
|
return false unless archival_attempts_available?
|
|
return true unless last_archival_attempt_at
|
|
|
|
(last_archival_attempt_at + backoff).past?
|
|
end
|
|
|
|
def archival_attempts_available?
|
|
archival_attempts <= MAX_ATTEMPTS
|
|
end
|
|
|
|
def increment_archival_attempts!
|
|
increment!(:archival_attempts, touch: :last_archival_attempt_at)
|
|
end
|
|
|
|
def track_archival!(trace_artifact_id, checksum)
|
|
update!(trace_artifact_id: trace_artifact_id, checksum: checksum, archived_at: Time.current)
|
|
end
|
|
|
|
def archival_attempts_message
|
|
if archival_attempts_available?
|
|
'The job can not be archived right now.'
|
|
else
|
|
'The job is out of archival attempts.'
|
|
end
|
|
end
|
|
|
|
def remote_checksum_valid?
|
|
checksum.present? &&
|
|
checksum == remote_checksum
|
|
end
|
|
|
|
def successfully_archived?
|
|
return false unless archived_at
|
|
|
|
remote_checksum.nil? || remote_checksum_valid?
|
|
end
|
|
|
|
private
|
|
|
|
def backoff
|
|
::Gitlab::Ci::Trace::Backoff.new(archival_attempts).value_with_jitter
|
|
end
|
|
|
|
def set_project_id
|
|
self.project_id ||= build&.project_id
|
|
end
|
|
end
|
|
end
|