Commit dece8406 authored by Rémy Coutable's avatar Rémy Coutable

Merge branch '64079-aggregation-schedule-should-keep-lease-until-timeout' into 'master'

Implements `lease_release?` on `NamespaceAggregation`

Closes #64079

See merge request gitlab-org/gitlab-ce!30305
parents f62aa64b d132f73d
...@@ -44,4 +44,12 @@ class Namespace::AggregationSchedule < ApplicationRecord ...@@ -44,4 +44,12 @@ class Namespace::AggregationSchedule < ApplicationRecord
def lease_key def lease_key
"namespace:namespaces_root_statistics:#{namespace_id}" "namespace:namespaces_root_statistics:#{namespace_id}"
end end
# Used by ExclusiveLeaseGuard
# Overriding value as we never release the lease
# before the timeout in order to prevent multiple
# RootStatisticsWorker to start in a short span of time
def lease_release?
false
end
end end
...@@ -53,10 +53,39 @@ RSpec.describe Namespace::AggregationSchedule, :clean_gitlab_redis_shared_state, ...@@ -53,10 +53,39 @@ RSpec.describe Namespace::AggregationSchedule, :clean_gitlab_redis_shared_state,
expect(Namespaces::RootStatisticsWorker) expect(Namespaces::RootStatisticsWorker)
.to receive(:perform_in).once .to receive(:perform_in).once
.with(described_class::DEFAULT_LEASE_TIMEOUT, aggregation_schedule.namespace_id ) .with(described_class::DEFAULT_LEASE_TIMEOUT, aggregation_schedule.namespace_id)
aggregation_schedule.save! aggregation_schedule.save!
end end
it 'does not release the lease' do
stub_exclusive_lease(lease_key, timeout: described_class::DEFAULT_LEASE_TIMEOUT)
aggregation_schedule.save!
exclusive_lease = aggregation_schedule.exclusive_lease
expect(exclusive_lease.exists?).to be_truthy
end
it 'only executes the workers once' do
# Avoid automatic deletion of Namespace::AggregationSchedule
# for testing purposes.
expect(Namespaces::RootStatisticsWorker)
.to receive(:perform_async).once
.and_return(nil)
expect(Namespaces::RootStatisticsWorker)
.to receive(:perform_in).once
.with(described_class::DEFAULT_LEASE_TIMEOUT, aggregation_schedule.namespace_id)
.and_return(nil)
# Scheduling workers for the first time
aggregation_schedule.schedule_root_storage_statistics
# Executing again, this time workers should not be scheduled
# due to the lease not been released.
aggregation_schedule.schedule_root_storage_statistics
end
end end
context 'with a personalized lease timeout' do context 'with a personalized lease timeout' do
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
describe Namespaces::ScheduleAggregationWorker, '#perform' do describe Namespaces::ScheduleAggregationWorker, '#perform', :clean_gitlab_redis_shared_state do
let(:group) { create(:group) } let(:group) { create(:group) }
subject(:worker) { described_class.new } subject(:worker) { described_class.new }
...@@ -10,6 +10,8 @@ describe Namespaces::ScheduleAggregationWorker, '#perform' do ...@@ -10,6 +10,8 @@ describe Namespaces::ScheduleAggregationWorker, '#perform' do
context 'when group is the root ancestor' do context 'when group is the root ancestor' do
context 'when aggregation schedule exists' do context 'when aggregation schedule exists' do
it 'does not create a new one' do it 'does not create a new one' do
stub_aggregation_schedule_statistics
Namespace::AggregationSchedule.safe_find_or_create_by!(namespace_id: group.id) Namespace::AggregationSchedule.safe_find_or_create_by!(namespace_id: group.id)
expect do expect do
...@@ -18,26 +20,25 @@ describe Namespaces::ScheduleAggregationWorker, '#perform' do ...@@ -18,26 +20,25 @@ describe Namespaces::ScheduleAggregationWorker, '#perform' do
end end
end end
context 'when update_statistics_namespace is off' do context 'when aggregation schedule does not exist' do
it 'does not create a new one' do it 'creates one' do
stub_feature_flags(update_statistics_namespace: false, namespace: group) stub_aggregation_schedule_statistics
expect do expect do
worker.perform(group.id) worker.perform(group.id)
end.not_to change(Namespace::AggregationSchedule, :count) end.to change(Namespace::AggregationSchedule, :count).by(1)
expect(group.aggregation_schedule).to be_present
end end
end end
context 'when aggregation schedule does not exist' do context 'when update_statistics_namespace is off' do
it 'creates one' do it 'does not create a new one' do
allow_any_instance_of(Namespace::AggregationSchedule) stub_feature_flags(update_statistics_namespace: false, namespace: group)
.to receive(:schedule_root_storage_statistics).and_return(nil)
expect do expect do
worker.perform(group.id) worker.perform(group.id)
end.to change(Namespace::AggregationSchedule, :count).by(1) end.not_to change(Namespace::AggregationSchedule, :count)
expect(group.aggregation_schedule).to be_present
end end
end end
end end
...@@ -47,8 +48,7 @@ describe Namespaces::ScheduleAggregationWorker, '#perform' do ...@@ -47,8 +48,7 @@ describe Namespaces::ScheduleAggregationWorker, '#perform' do
let(:group) { create(:group, parent: parent_group) } let(:group) { create(:group, parent: parent_group) }
it 'creates an aggregation schedule for the root' do it 'creates an aggregation schedule for the root' do
allow_any_instance_of(Namespace::AggregationSchedule) stub_aggregation_schedule_statistics
.to receive(:schedule_root_storage_statistics).and_return(nil)
worker.perform(group.id) worker.perform(group.id)
...@@ -63,4 +63,15 @@ describe Namespaces::ScheduleAggregationWorker, '#perform' do ...@@ -63,4 +63,15 @@ describe Namespaces::ScheduleAggregationWorker, '#perform' do
worker.perform(12345) worker.perform(12345)
end end
end end
def stub_aggregation_schedule_statistics
# Namespace::Aggregations are deleted by
# Namespace::AggregationSchedule::schedule_root_storage_statistics,
# which is executed async. Stubing the service so instances are not deleted
# while still running the specs.
expect_next_instance_of(Namespace::AggregationSchedule) do |aggregation_schedule|
expect(aggregation_schedule)
.to receive(:schedule_root_storage_statistics)
end
end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment