73 lines
2.3 KiB
Ruby
73 lines
2.3 KiB
Ruby
![]() |
# 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
|
||
|
redis.pipelined do
|
||
|
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
|
||
|
redis.set(cache_key(tag), created_at.rfc3339, ex: ttl) if ttl > 0
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
def cache_key(tag)
|
||
|
"container_repository:{#{@container_repository.id}}:tag:#{tag.name}:created_at"
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|