Class: Ci::BuildTraceChunks::RedisBase

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

Direct Known Subclasses

Redis, RedisTraceChunks

Constant Summary collapse

CHUNK_REDIS_TTL =
1.week
LUA_APPEND_CHUNK =
"local key, new_data, offset = KEYS[1], ARGV[1], ARGV[2]\nlocal length = new_data:len()\nlocal expire = \#{CHUNK_REDIS_TTL.seconds}\nlocal current_size = redis.call(\"strlen\", key)\noffset = tonumber(offset)\n\nif offset == 0 then\n  -- overwrite everything\n  redis.call(\"set\", key, new_data, \"ex\", expire)\n  return redis.call(\"strlen\", key)\nelseif offset > current_size then\n  -- offset range violation\n  return -1\nelseif offset + length >= current_size then\n  -- efficiently append or overwrite and append\n  redis.call(\"expire\", key, expire)\n  return redis.call(\"setrange\", key, offset, new_data)\nelse\n  -- append and truncate\n  local current_data = redis.call(\"get\", key)\n  new_data = current_data:sub(1, offset) .. new_data\n  redis.call(\"set\", key, new_data, \"ex\", expire)\n  return redis.call(\"strlen\", key)\nend\n"

Instance Method Summary collapse

Instance Method Details

#append_data(model, new_data, offset) ⇒ Object



46
47
48
49
50
# File 'app/models/ci/build_trace_chunks/redis_base.rb', line 46

def append_data(model, new_data, offset)
  with_redis do |redis|
    redis.eval(LUA_APPEND_CHUNK, keys: [key(model)], argv: [new_data, offset])
  end
end

#data(model) ⇒ Object



34
35
36
37
38
# File 'app/models/ci/build_trace_chunks/redis_base.rb', line 34

def data(model)
  with_redis do |redis|
    redis.get(key(model))
  end
end

#delete_data(model) ⇒ Object



58
59
60
# File 'app/models/ci/build_trace_chunks/redis_base.rb', line 58

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

#delete_keys(keys) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'app/models/ci/build_trace_chunks/redis_base.rb', line 66

def delete_keys(keys)
  return if keys.empty?

  keys = keys.map { |key| key_raw(*key) }

  with_redis do |redis|
    # https://gitlab.com/gitlab-org/gitlab/-/issues/224171
    Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do
      if Gitlab::Redis::ClusterUtil.cluster?(redis)
        Gitlab::Redis::ClusterUtil.batch_unlink(keys, redis)
      else
        redis.del(keys)
      end
    end
  end
end

#keys(relation) ⇒ Object



62
63
64
# File 'app/models/ci/build_trace_chunks/redis_base.rb', line 62

def keys(relation)
  relation.pluck(:build_id, :chunk_index)
end

#set_data(model, new_data) ⇒ Object



40
41
42
43
44
# File 'app/models/ci/build_trace_chunks/redis_base.rb', line 40

def set_data(model, new_data)
  with_redis do |redis|
    redis.set(key(model), new_data, ex: CHUNK_REDIS_TTL)
  end
end

#size(model) ⇒ Object



52
53
54
55
56
# File 'app/models/ci/build_trace_chunks/redis_base.rb', line 52

def size(model)
  with_redis do |redis|
    redis.strlen(key(model))
  end
end