Class: Ci::BuildTraceChunks::Fog

Inherits:
Object
  • Object
show all
Defined in:
app/models/ci/build_trace_chunks/fog.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.available?Boolean

Returns:

  • (Boolean)

6
7
8
# File 'app/models/ci/build_trace_chunks/fog.rb', line 6

def self.available?
  object_store.enabled
end

.object_storeObject


10
11
12
# File 'app/models/ci/build_trace_chunks/fog.rb', line 10

def self.object_store
  Gitlab.config.artifacts.object_store
end

Instance Method Details

#append_data(model, new_data, offset) ⇒ Object

This is the sequence that causes append_data to be called:

  1. Runner sends a PUT /api/v4/jobs/:id to indicate the job is canceled or finished.

  2. UpdateBuildStateService#accept_build_state! persists all live job logs to object storage (or filesystem).

  3. UpdateBuildStateService#accept_build_state! returns a 202 to the runner.

  4. The runner continues to send PATCH requests with job logs until all logs have been sent and received.

  5. If the last PATCH request arrives after the job log has been persisted, we retrieve the data from object storage to append the remaining lines.


36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'app/models/ci/build_trace_chunks/fog.rb', line 36

def append_data(model, new_data, offset)
  if offset > 0
    truncated_data = data(model).to_s.byteslice(0, offset)
    new_data = append_strings(truncated_data, new_data)
  end

  set_data(model, new_data)
  new_data.bytesize
rescue Encoding::CompatibilityError => e
  Gitlab::ErrorTracking.track_and_raise_exception(
    e,
    build_id: model.build_id,
    chunk_index: model.chunk_index,
    chunk_start_offset: model.start_offset,
    chunk_end_offset: model.end_offset,
    chunk_size: model.size,
    chunk_data_store: model.data_store,
    offset: offset,
    old_data_encoding: truncated_data.encoding.to_s,
    new_data: new_data,
    new_data_size: new_data.bytesize,
    new_data_encoding: new_data.encoding.to_s)
end

#available?Boolean

Returns:

  • (Boolean)

14
15
16
# File 'app/models/ci/build_trace_chunks/fog.rb', line 14

def available?
  self.class.available?
end

#data(model) ⇒ Object


18
19
20
21
22
# File 'app/models/ci/build_trace_chunks/fog.rb', line 18

def data(model)
  files.get(key(model))&.body
rescue Excon::Error::NotFound
  # If the object does not exist in the object storage, this method returns nil.
end

#delete_data(model) ⇒ Object


64
65
66
# File 'app/models/ci/build_trace_chunks/fog.rb', line 64

def delete_data(model)
  delete_keys([[model.build_id, model.chunk_index]])
end

#delete_keys(keys) ⇒ Object


74
75
76
77
78
# File 'app/models/ci/build_trace_chunks/fog.rb', line 74

def delete_keys(keys)
  keys.each do |key|
    files.destroy(key_raw(*key))
  end
end

#keys(relation) ⇒ Object


68
69
70
71
72
# File 'app/models/ci/build_trace_chunks/fog.rb', line 68

def keys(relation)
  return [] unless available?

  relation.pluck(:build_id, :chunk_index)
end

#set_data(model, new_data) ⇒ Object


24
25
26
# File 'app/models/ci/build_trace_chunks/fog.rb', line 24

def set_data(model, new_data)
  files.create(create_attributes(model, new_data))
end

#size(model) ⇒ Object


60
61
62
# File 'app/models/ci/build_trace_chunks/fog.rb', line 60

def size(model)
  data(model).to_s.bytesize
end