diff options
Diffstat (limited to 'app/models/ci/build_trace_chunks')
-rw-r--r-- | app/models/ci/build_trace_chunks/database.rb | 18 | ||||
-rw-r--r-- | app/models/ci/build_trace_chunks/fog.rb | 20 | ||||
-rw-r--r-- | app/models/ci/build_trace_chunks/redis.rb | 38 |
3 files changed, 72 insertions, 4 deletions
diff --git a/app/models/ci/build_trace_chunks/database.rb b/app/models/ci/build_trace_chunks/database.rb index 73cb8abf381..3b8e23510d9 100644 --- a/app/models/ci/build_trace_chunks/database.rb +++ b/app/models/ci/build_trace_chunks/database.rb @@ -19,8 +19,22 @@ module Ci model.raw_data end - def set_data(model, data) - model.raw_data = data + def set_data(model, new_data) + model.raw_data = new_data + end + + def append_data(model, new_data, offset) + if offset > 0 + truncated_data = data(model).to_s.byteslice(0, offset) + new_data = truncated_data + new_data + end + + model.raw_data = new_data + model.raw_data.to_s.bytesize + end + + def size(model) + data(model).to_s.bytesize end def delete_data(model) diff --git a/app/models/ci/build_trace_chunks/fog.rb b/app/models/ci/build_trace_chunks/fog.rb index a849bd08427..b1e9fd1faeb 100644 --- a/app/models/ci/build_trace_chunks/fog.rb +++ b/app/models/ci/build_trace_chunks/fog.rb @@ -9,10 +9,26 @@ module Ci def data(model) connection.get_object(bucket_name, key(model))[:body] + rescue Excon::Error::NotFound + # If the object does not exist in the object storage, this method returns nil. end - def set_data(model, data) - connection.put_object(bucket_name, key(model), data) + def set_data(model, new_data) + connection.put_object(bucket_name, key(model), new_data) + end + + def append_data(model, new_data, offset) + if offset > 0 + truncated_data = data(model).to_s.byteslice(0, offset) + new_data = truncated_data + new_data + end + + set_data(model, new_data) + new_data.bytesize + end + + def size(model) + data(model).to_s.bytesize end def delete_data(model) diff --git a/app/models/ci/build_trace_chunks/redis.rb b/app/models/ci/build_trace_chunks/redis.rb index c3864f78b01..0ae563f6ce8 100644 --- a/app/models/ci/build_trace_chunks/redis.rb +++ b/app/models/ci/build_trace_chunks/redis.rb @@ -4,6 +4,32 @@ module Ci module BuildTraceChunks class Redis CHUNK_REDIS_TTL = 1.week + LUA_APPEND_CHUNK = <<~EOS.freeze + local key, new_data, offset = KEYS[1], ARGV[1], ARGV[2] + local length = new_data:len() + local expire = #{CHUNK_REDIS_TTL.seconds} + local current_size = redis.call("strlen", key) + offset = tonumber(offset) + + if offset == 0 then + -- overwrite everything + redis.call("set", key, new_data, "ex", expire) + return redis.call("strlen", key) + elseif offset > current_size then + -- offset range violation + return -1 + elseif offset + length >= current_size then + -- efficiently append or overwrite and append + redis.call("expire", key, expire) + return redis.call("setrange", key, offset, new_data) + else + -- append and truncate + local current_data = redis.call("get", key) + new_data = current_data:sub(1, offset) .. new_data + redis.call("set", key, new_data, "ex", expire) + return redis.call("strlen", key) + end + EOS def available? true @@ -21,6 +47,18 @@ module Ci end end + def append_data(model, new_data, offset) + Gitlab::Redis::SharedState.with do |redis| + redis.eval(LUA_APPEND_CHUNK, keys: [key(model)], argv: [new_data, offset]) + end + end + + def size(model) + Gitlab::Redis::SharedState.with do |redis| + redis.strlen(key(model)) + end + end + def delete_data(model) delete_keys([[model.build_id, model.chunk_index]]) end |