Commit 7a503767 authored by Etienne Baqué's avatar Etienne Baqué

Merge branch 'invalidate-namespace-user-cap-reached-cache' into 'master'

Invalidate namespace_user_cap_reached Cache

See merge request gitlab-org/gitlab!72657
parents c547531d d6132fb2
...@@ -24,7 +24,7 @@ module EE ...@@ -24,7 +24,7 @@ module EE
end end
def user_cap_reached?(root_namespace) def user_cap_reached?(root_namespace)
Rails.cache.fetch("namespace_user_cap_reached:#{root_namespace.id}", expires_in: 2.hours) do Rails.cache.fetch(root_namespace.namespace_user_cap_reached_cache_key, expires_in: 2.hours) do
root_namespace.user_cap_reached? root_namespace.user_cap_reached?
end end
end end
......
...@@ -490,6 +490,10 @@ module EE ...@@ -490,6 +490,10 @@ module EE
user_cap <= root_ancestor.billable_members_count(requested_hosted_plan) user_cap <= root_ancestor.billable_members_count(requested_hosted_plan)
end end
def namespace_user_cap_reached_cache_key
"namespace_user_cap_reached:#{root_ancestor.id}"
end
private private
override :post_create_hook override :post_create_hook
......
...@@ -30,6 +30,8 @@ module EE ...@@ -30,6 +30,8 @@ module EE
before_create :set_membership_activation before_create :set_membership_activation
after_commit :invalidate_namespace_user_cap_cache
scope :with_csv_entity_associations, -> do scope :with_csv_entity_associations, -> do
includes(:user, source: [:route, :parent]) includes(:user, source: [:route, :parent])
end end
...@@ -149,5 +151,11 @@ module EE ...@@ -149,5 +151,11 @@ module EE
self.state = group.user_cap_reached? ? STATE_AWAITING : STATE_ACTIVE self.state = group.user_cap_reached? ? STATE_AWAITING : STATE_ACTIVE
end end
def invalidate_namespace_user_cap_cache
return unless group && ::Feature.enabled?(:saas_user_caps, group.root_ancestor, default_enabled: :yaml)
Rails.cache.delete(group.namespace_user_cap_reached_cache_key)
end
end end
end end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe EE::NamespaceUserCapReachedAlertHelper do
describe '#display_namespace_user_cap_reached_alert?' do
let_it_be(:group, refind: true) do
create(:group, :public,
namespace_settings: create(:namespace_settings, new_user_signups_cap: 1))
end
let_it_be(:subgroup) { create(:group, parent: group) }
let_it_be(:owner) { create(:user) }
let_it_be(:developer) { create(:user) }
before_all do
group.add_owner(owner)
group.add_developer(developer)
end
before do
allow(helper).to receive(:can?).with(owner, :admin_namespace, group).and_return(true)
allow(helper).to receive(:can?).with(developer, :admin_namespace, group).and_return(false)
end
it 'returns true when the user cap is reached for a user who can admin the namespace' do
sign_in(owner)
expect(helper.display_namespace_user_cap_reached_alert?(group)).to be true
end
it 'returns false when the user cap is reached for a user who cannot admin the namespace' do
sign_in(developer)
expect(helper.display_namespace_user_cap_reached_alert?(group)).to be false
end
it 'caches the result' do
sign_in(owner)
expect(Rails.cache).to receive(:fetch).with("namespace_user_cap_reached:#{group.id}", expires_in: 2.hours)
helper.display_namespace_user_cap_reached_alert?(group)
end
it 'caches the result for a subgroup' do
sign_in(owner)
expect(Rails.cache).to receive(:fetch).with("namespace_user_cap_reached:#{group.id}", expires_in: 2.hours)
helper.display_namespace_user_cap_reached_alert?(subgroup)
end
def sign_in(user)
allow(helper).to receive(:current_user).and_return(user)
end
end
end
...@@ -249,4 +249,80 @@ RSpec.describe Member, type: :model do ...@@ -249,4 +249,80 @@ RSpec.describe Member, type: :model do
end end
end end
end end
describe '#invalidate_namespace_user_cap_cache' do
let_it_be(:other_user) { create(:user) }
context 'when the :saas_user_caps feature flag is enabled for the root group' do
before do
stub_feature_flags(saas_user_caps: group)
end
it 'invalidates the namespace user cap reached cache when adding a member to a group' do
expect(Rails.cache).to receive(:delete).with("namespace_user_cap_reached:#{group.id}")
group.add_developer(other_user)
end
it 'invalidates the cache when adding a member to a subgroup' do
expect(Rails.cache).to receive(:delete).with("namespace_user_cap_reached:#{group.id}")
sub_group.add_developer(other_user)
end
it 'invalidates the cache when adding a member to a project' do
expect(Rails.cache).to receive(:delete).with("namespace_user_cap_reached:#{group.id}")
project.add_developer(other_user)
end
it 'invalidates the cache when removing a member from a group' do
expect(Rails.cache).to receive(:delete).with("namespace_user_cap_reached:#{group.id}")
member.destroy!
end
it 'invalidates the cache when removing a member from a project' do
project_member = project.add_developer(other_user)
expect(Rails.cache).to receive(:delete).with("namespace_user_cap_reached:#{group.id}")
project_member.destroy!
end
it 'invalidates the cache when changing the access level' do
guest_member = create(:group_member, :guest, group: group, user: other_user)
expect(Rails.cache).to receive(:delete).with("namespace_user_cap_reached:#{group.id}")
guest_member.update!(access_level: GroupMember::DEVELOPER)
end
end
context 'when the :saas_user_caps feature flag is globally enabled' do
before do
stub_feature_flags(saas_user_caps: true)
end
it 'does not try to invalidate the cache for a project with a user namespace' do
project_owner = create(:user)
personal_project = create(:project, namespace: project_owner.namespace)
expect(Rails.cache).not_to receive(:delete)
personal_project.add_developer(other_user)
end
end
context 'when the :saas_user_caps feature flag is disabled' do
before do
stub_feature_flags(saas_user_caps: false)
end
it 'does not invalidate the namespace user cap reached cache' do
expect(Rails.cache).not_to receive(:delete)
group.add_developer(other_user)
end
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