Merge branch '341536-dp-read-at-for-ttl' into 'master'

Add read_at to dependency proxy objects

See merge request gitlab-org/gitlab!73842
This commit is contained in:
Alper Akgun 2021-11-10 17:33:41 +00:00
commit 70145730fb
16 changed files with 76 additions and 18 deletions

View file

@ -113,8 +113,6 @@ def blob_via_workhorse
end end
def send_manifest(manifest, from_cache:) def send_manifest(manifest, from_cache:)
# Technical debt: change to read_at https://gitlab.com/gitlab-org/gitlab/-/issues/341536
manifest.touch
response.headers[DependencyProxy::Manifest::DIGEST_HEADER] = manifest.digest response.headers[DependencyProxy::Manifest::DIGEST_HEADER] = manifest.digest
response.headers['Content-Length'] = manifest.size response.headers['Content-Length'] = manifest.size
response.headers['Docker-Distribution-Api-Version'] = DependencyProxy::DISTRIBUTION_API_VERSION response.headers['Docker-Distribution-Api-Version'] = DependencyProxy::DISTRIBUTION_API_VERSION

View file

@ -5,10 +5,11 @@ module TtlExpirable
included do included do
validates :status, presence: true validates :status, presence: true
default_value_for :read_at, Time.zone.now
enum status: { default: 0, expired: 1, processing: 2, error: 3 } enum status: { default: 0, expired: 1, processing: 2, error: 3 }
scope :updated_before, ->(number_of_days) { where("updated_at <= ?", Time.zone.now - number_of_days.days) } scope :read_before, ->(number_of_days) { where("read_at <= ?", Time.zone.now - number_of_days.days) }
scope :active, -> { where(status: :default) } scope :active, -> { where(status: :default) }
scope :lock_next_by, ->(sort) do scope :lock_next_by, ->(sort) do
@ -17,4 +18,8 @@ module TtlExpirable
.lock('FOR UPDATE SKIP LOCKED') .lock('FOR UPDATE SKIP LOCKED')
end end
end end
def read!
self.update(read_at: Time.zone.now)
end
end end

View file

@ -30,8 +30,7 @@ def execute
blob.save! blob.save!
end end
# Technical debt: change to read_at https://gitlab.com/gitlab-org/gitlab/-/issues/341536 blob.read! if from_cache
blob.touch if from_cache
success(blob: blob, from_cache: from_cache) success(blob: blob, from_cache: from_cache)
end end

View file

@ -58,6 +58,8 @@ def cached_manifest_matches?(head_result)
def respond(from_cache: true) def respond(from_cache: true)
if @manifest if @manifest
@manifest.read!
success(manifest: @manifest, from_cache: from_cache) success(manifest: @manifest, from_cache: from_cache)
else else
error('Failed to download the manifest from the external registry', 503) error('Failed to download the manifest from the external registry', 503)

View file

@ -13,9 +13,8 @@ class ImageTtlGroupPolicyWorker # rubocop:disable Scalability/IdempotentWorker
def perform def perform
DependencyProxy::ImageTtlGroupPolicy.enabled.each do |policy| DependencyProxy::ImageTtlGroupPolicy.enabled.each do |policy|
# Technical Debt: change to read_before https://gitlab.com/gitlab-org/gitlab/-/issues/341536 qualified_blobs = policy.group.dependency_proxy_blobs.active.read_before(policy.ttl)
qualified_blobs = policy.group.dependency_proxy_blobs.active.updated_before(policy.ttl) qualified_manifests = policy.group.dependency_proxy_manifests.active.read_before(policy.ttl)
qualified_manifests = policy.group.dependency_proxy_manifests.active.updated_before(policy.ttl)
enqueue_blob_cleanup_job if expire_artifacts(qualified_blobs, DependencyProxy::Blob) enqueue_blob_cleanup_job if expire_artifacts(qualified_blobs, DependencyProxy::Blob)
enqueue_manifest_cleanup_job if expire_artifacts(qualified_manifests, DependencyProxy::Manifest) enqueue_manifest_cleanup_job if expire_artifacts(qualified_manifests, DependencyProxy::Manifest)

View file

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddReadAtToDependencyProxyManifests < Gitlab::Database::Migration[1.0]
def change
add_column :dependency_proxy_manifests, :read_at, :datetime_with_timezone, null: false, default: -> { 'NOW()' }
end
end

View file

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddReadAtToDependencyProxyBlobs < Gitlab::Database::Migration[1.0]
def change
add_column :dependency_proxy_blobs, :read_at, :datetime_with_timezone, null: false, default: -> { 'NOW()' }
end
end

View file

@ -0,0 +1,27 @@
# frozen_string_literal: true
class UpdateDependencyProxyIndexesWithReadAt < Gitlab::Database::Migration[1.0]
disable_ddl_transaction!
NEW_BLOB_INDEX = 'index_dependency_proxy_blobs_on_group_id_status_read_at_id'
OLD_BLOB_INDEX = 'index_dependency_proxy_blobs_on_group_id_status_and_id'
NEW_MANIFEST_INDEX = 'index_dependency_proxy_manifests_on_group_id_status_read_at_id'
OLD_MANIFEST_INDEX = 'index_dependency_proxy_manifests_on_group_id_status_and_id'
def up
add_concurrent_index :dependency_proxy_blobs, [:group_id, :status, :read_at, :id], name: NEW_BLOB_INDEX
add_concurrent_index :dependency_proxy_manifests, [:group_id, :status, :read_at, :id], name: NEW_MANIFEST_INDEX
remove_concurrent_index_by_name :dependency_proxy_blobs, OLD_BLOB_INDEX
remove_concurrent_index_by_name :dependency_proxy_manifests, OLD_MANIFEST_INDEX
end
def down
add_concurrent_index :dependency_proxy_blobs, [:group_id, :status, :id], name: OLD_BLOB_INDEX
add_concurrent_index :dependency_proxy_manifests, [:group_id, :status, :id], name: OLD_MANIFEST_INDEX
remove_concurrent_index_by_name :dependency_proxy_blobs, NEW_BLOB_INDEX
remove_concurrent_index_by_name :dependency_proxy_manifests, NEW_MANIFEST_INDEX
end
end

View file

@ -0,0 +1 @@
13cf3d164d541df48b6d14d7cc1953113476ba8ea5975d7d0c5f84098e2e0e61

View file

@ -0,0 +1 @@
a48f62bed7e4c4a0e69acd3b340065317aff71602e696970276a4e443f1dcabf

View file

@ -0,0 +1 @@
a2556a3d8b21e59caa6cbf7f83d621fef391904d0c13c77c0e5da713a580b4c9

View file

@ -13237,7 +13237,8 @@ CREATE TABLE dependency_proxy_blobs (
file_store integer, file_store integer,
file_name character varying NOT NULL, file_name character varying NOT NULL,
file text NOT NULL, file text NOT NULL,
status smallint DEFAULT 0 NOT NULL status smallint DEFAULT 0 NOT NULL,
read_at timestamp with time zone DEFAULT now() NOT NULL
); );
CREATE SEQUENCE dependency_proxy_blobs_id_seq CREATE SEQUENCE dependency_proxy_blobs_id_seq
@ -13286,6 +13287,7 @@ CREATE TABLE dependency_proxy_manifests (
digest text NOT NULL, digest text NOT NULL,
content_type text, content_type text,
status smallint DEFAULT 0 NOT NULL, status smallint DEFAULT 0 NOT NULL,
read_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT check_079b293a7b CHECK ((char_length(file) <= 255)), CONSTRAINT check_079b293a7b CHECK ((char_length(file) <= 255)),
CONSTRAINT check_167a9a8a91 CHECK ((char_length(content_type) <= 255)), CONSTRAINT check_167a9a8a91 CHECK ((char_length(content_type) <= 255)),
CONSTRAINT check_c579e3f586 CHECK ((char_length(file_name) <= 255)), CONSTRAINT check_c579e3f586 CHECK ((char_length(file_name) <= 255)),
@ -25646,13 +25648,13 @@ CREATE UNIQUE INDEX index_dep_prox_manifests_on_group_id_file_name_and_status ON
CREATE INDEX index_dependency_proxy_blobs_on_group_id_and_file_name ON dependency_proxy_blobs USING btree (group_id, file_name); CREATE INDEX index_dependency_proxy_blobs_on_group_id_and_file_name ON dependency_proxy_blobs USING btree (group_id, file_name);
CREATE INDEX index_dependency_proxy_blobs_on_group_id_status_and_id ON dependency_proxy_blobs USING btree (group_id, status, id); CREATE INDEX index_dependency_proxy_blobs_on_group_id_status_read_at_id ON dependency_proxy_blobs USING btree (group_id, status, read_at, id);
CREATE INDEX index_dependency_proxy_blobs_on_status ON dependency_proxy_blobs USING btree (status); CREATE INDEX index_dependency_proxy_blobs_on_status ON dependency_proxy_blobs USING btree (status);
CREATE INDEX index_dependency_proxy_group_settings_on_group_id ON dependency_proxy_group_settings USING btree (group_id); CREATE INDEX index_dependency_proxy_group_settings_on_group_id ON dependency_proxy_group_settings USING btree (group_id);
CREATE INDEX index_dependency_proxy_manifests_on_group_id_status_and_id ON dependency_proxy_manifests USING btree (group_id, status, id); CREATE INDEX index_dependency_proxy_manifests_on_group_id_status_read_at_id ON dependency_proxy_manifests USING btree (group_id, status, read_at, id);
CREATE INDEX index_dependency_proxy_manifests_on_status ON dependency_proxy_manifests USING btree (status); CREATE INDEX index_dependency_proxy_manifests_on_status ON dependency_proxy_manifests USING btree (status);

View file

@ -39,7 +39,7 @@
let(:blob_sha) { blob.file_name.sub('.gz', '') } let(:blob_sha) { blob.file_name.sub('.gz', '') }
it 'uses cached blob instead of downloading one' do it 'uses cached blob instead of downloading one' do
expect { subject }.to change { blob.reload.updated_at } expect { subject }.to change { blob.reload.read_at }
expect(subject[:status]).to eq(:success) expect(subject[:status]).to eq(:success)
expect(subject[:blob]).to be_a(DependencyProxy::Blob) expect(subject[:blob]).to be_a(DependencyProxy::Blob)

View file

@ -84,7 +84,7 @@
shared_examples 'using the cached manifest' do shared_examples 'using the cached manifest' do
it 'uses cached manifest instead of downloading one', :aggregate_failures do it 'uses cached manifest instead of downloading one', :aggregate_failures do
subject expect { subject }.to change { dependency_proxy_manifest.reload.read_at }
expect(subject[:status]).to eq(:success) expect(subject[:status]).to eq(:success)
expect(subject[:manifest]).to be_a(DependencyProxy::Manifest) expect(subject[:manifest]).to be_a(DependencyProxy::Manifest)

View file

@ -11,18 +11,18 @@
it { is_expected.to validate_presence_of(:status) } it { is_expected.to validate_presence_of(:status) }
end end
describe '.updated_before' do describe '.read_before' do
# rubocop:disable Rails/SaveBang # rubocop:disable Rails/SaveBang
let_it_be_with_reload(:item1) { create(class_symbol) } let_it_be_with_reload(:item1) { create(class_symbol) }
let_it_be(:item2) { create(class_symbol) } let_it_be(:item2) { create(class_symbol) }
# rubocop:enable Rails/SaveBang # rubocop:enable Rails/SaveBang
before do before do
item1.update_column(:updated_at, 1.month.ago) item1.update_column(:read_at, 1.month.ago)
end end
it 'returns items with created at older than the supplied number of days' do it 'returns items with created at older than the supplied number of days' do
expect(described_class.updated_before(10)).to contain_exactly(item1) expect(described_class.read_before(10)).to contain_exactly(item1)
end end
end end
@ -48,4 +48,13 @@
expect(described_class.lock_next_by(:created_at)).to contain_exactly(item3) expect(described_class.lock_next_by(:created_at)).to contain_exactly(item3)
end end
end end
describe '#read', :freeze_time do
let_it_be(:old_read_at) { 1.day.ago }
let_it_be(:item1) { create(class_symbol, read_at: old_read_at) }
it 'updates read_at' do
expect { item1.read! }.to change { item1.reload.read_at }
end
end
end end

View file

@ -12,8 +12,8 @@
subject { worker.perform } subject { worker.perform }
context 'when there are images to expire' do context 'when there are images to expire' do
let_it_be_with_reload(:old_blob) { create(:dependency_proxy_blob, group: group, updated_at: 1.year.ago) } let_it_be_with_reload(:old_blob) { create(:dependency_proxy_blob, group: group, read_at: 1.year.ago) }
let_it_be_with_reload(:old_manifest) { create(:dependency_proxy_manifest, group: group, updated_at: 1.year.ago) } let_it_be_with_reload(:old_manifest) { create(:dependency_proxy_manifest, group: group, read_at: 1.year.ago) }
let_it_be_with_reload(:new_blob) { create(:dependency_proxy_blob, group: group) } let_it_be_with_reload(:new_blob) { create(:dependency_proxy_blob, group: group) }
let_it_be_with_reload(:new_manifest) { create(:dependency_proxy_manifest, group: group) } let_it_be_with_reload(:new_manifest) { create(:dependency_proxy_manifest, group: group) }