2021-11-05 15:11:48 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
module Gitlab
|
|
|
|
module ContainerRepository
|
|
|
|
module Tags
|
|
|
|
class Cache
|
|
|
|
def initialize(container_repository)
|
|
|
|
@container_repository = container_repository
|
|
|
|
@cached_tag_names = Set.new
|
|
|
|
end
|
|
|
|
|
|
|
|
def populate(tags)
|
|
|
|
return if tags.empty?
|
|
|
|
|
|
|
|
# This will load all tags in one Redis roundtrip
|
|
|
|
# the maximum number of tags is configurable and is set to 200 by default.
|
|
|
|
# https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/packages/container_registry/index.md#set-cleanup-limits-to-conserve-resources
|
|
|
|
keys = tags.map(&method(:cache_key))
|
|
|
|
cached_tags_count = 0
|
|
|
|
|
|
|
|
::Gitlab::Redis::Cache.with do |redis|
|
|
|
|
tags.zip(redis.mget(keys)).each do |tag, created_at|
|
|
|
|
next unless created_at
|
|
|
|
|
|
|
|
tag.created_at = DateTime.rfc3339(created_at)
|
|
|
|
@cached_tag_names << tag.name
|
|
|
|
cached_tags_count += 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
cached_tags_count
|
|
|
|
end
|
|
|
|
|
|
|
|
def insert(tags, max_ttl_in_seconds)
|
|
|
|
return unless max_ttl_in_seconds
|
|
|
|
return if tags.empty?
|
|
|
|
|
|
|
|
# tags with nil created_at are not cacheable
|
|
|
|
# tags already cached don't need to be cached again
|
|
|
|
cacheable_tags = tags.select do |tag|
|
|
|
|
tag.created_at.present? && !tag.name.in?(@cached_tag_names)
|
|
|
|
end
|
|
|
|
|
|
|
|
return if cacheable_tags.empty?
|
|
|
|
|
|
|
|
now = Time.zone.now
|
|
|
|
|
|
|
|
::Gitlab::Redis::Cache.with do |redis|
|
|
|
|
# we use a pipeline instead of a MSET because each tag has
|
|
|
|
# a specific ttl
|
2022-08-19 15:11:58 +00:00
|
|
|
redis.pipelined do |pipeline|
|
2021-11-05 15:11:48 +00:00
|
|
|
cacheable_tags.each do |tag|
|
|
|
|
created_at = tag.created_at
|
|
|
|
# ttl is the max_ttl_in_seconds reduced by the number
|
|
|
|
# of seconds that the tag has already existed
|
|
|
|
ttl = max_ttl_in_seconds - (now - created_at).seconds
|
|
|
|
ttl = ttl.to_i
|
2022-08-19 15:11:58 +00:00
|
|
|
pipeline.set(cache_key(tag), created_at.rfc3339, ex: ttl) if ttl > 0
|
2021-11-05 15:11:48 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def cache_key(tag)
|
|
|
|
"container_repository:{#{@container_repository.id}}:tag:#{tag.name}:created_at"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|