Welcome to mirror list, hosted at ThFree Co, Russian Federation.

checksum.rb « trace « ci « gitlab « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 62532ef1cd24cf895bf44ee0ec21a1e03f9fbb2d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# frozen_string_literal: true

module Gitlab
  module Ci
    class Trace
      ##
      # Trace::Checksum class is responsible for calculating a CRC32 checksum
      # of an entire build trace using partial build trace chunks stored in a
      # database.
      #
      # CRC32 checksum can be easily calculated by combining partial checksums
      # in a right order.
      #
      # Then we compare CRC32 checksum provided by a GitLab Runner and expect
      # it to be the same as the CRC32 checksum derived from partial chunks.
      #
      class Checksum
        include Gitlab::Utils::StrongMemoize

        attr_reader :build

        def initialize(build)
          @build = build
        end

        def valid?
          return false unless state_crc32.present?

          state_crc32 == chunks_crc32
        end

        def state_crc32
          strong_memoize(:state_crc32) { build.pending_state&.crc32 }
        end

        def chunks_crc32
          strong_memoize(:chunks_crc32) do
            trace_chunks.reduce(0) do |crc32, chunk|
              Zlib.crc32_combine(crc32, chunk.crc32, chunk_size(chunk))
            end
          end
        end

        def last_chunk
          strong_memoize(:last_chunk) { trace_chunks.max }
        end

        ##
        # Trace chunks will be persisted in a database if an object store is
        # not configured - in that case we do not want to load entire raw data
        # of all the chunks into memory.
        #
        # We ignore `raw_data` attribute instead, and rely on internal build
        # trace chunk database adapter to handle
        # `ActiveModel::MissingAttributeError` exception.
        #
        # Alternative solution would be separating chunk data from chunk
        # metadata on the database level too.
        #
        def trace_chunks
          strong_memoize(:trace_chunks) do
            build.trace_chunks.persisted
              .select(::Ci::BuildTraceChunk.metadata_attributes)
          end
        end

        def chunks_count
          trace_chunks.to_a.size
        end

        private

        def chunk_size(chunk)
          if chunk == last_chunk
            chunk.size
          else
            ::Ci::BuildTraceChunk::CHUNK_SIZE
          end
        end
      end
    end
  end
end