Commit 25ee81c1 authored by Dylan Griffith's avatar Dylan Griffith

Index trial groups in Elasticsearch

As part of https://gitlab.com/gitlab-org/gitlab/-/issues/220386 we want
to index trial groups in Elasticsearch so they can make use of Advanced
search.

This change also refactored the existing logic around indexing paid
groups a bit:

1. Removing the feature flag that has been on for a while now along
with the documentation explaining this feature flag. We already have
separate docs explaining that Advanced Global Search is enabled for
bronze and above groups so this is not necessary.
2. This will now also exclude `expired?` groups which we shouldn't have
been indexing to begin with. The assumption is that the `expired?` check
will also ensure we skip expired trials. These expired trials also have
a `trial_ends_on` date but based on looking at some data I think we can
expect this will be the same or less than `end_date`. The expired trials
that are in the index will be cleaned up in
https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38551
3. Don't check `saved_changes.key?('hosted_plan_id')` anymore since we
don't really care why the plan is changing. As long as we use
`safe_find_or_create_by!` we'll be fine to run this multiple times.
parent f3c72ba0
# Elasticsearch for paid tiers on GitLab.com
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220246) in GitLab 13.2
> - It's deployed behind a feature flag, disabled by default.
> - It's disabled on GitLab.com.
> - It's not recommended for use in GitLab self-managed instances.
This document describes how to enable Elasticsearch with GitLab for all paid tiers on GitLab.com. Once enabled,
all paid tiers will have access to the [Advanced Global Search feature](../../integration/elasticsearch.md) on GitLab.com.
## Enable or disable Elasticsearch for all paid tiers on GitLab.com
Since we're still in the process of rolling this out and want to control the timing this is behind a feature flag
which defaults to off.
To enable it:
```ruby
# Instance-wide
Feature.enable(:elasticsearch_index_only_paid_groups)
```
To disable it:
```ruby
# Instance-wide
Feature.disable(:elasticsearch_index_only_paid_groups)
```
...@@ -36,8 +36,8 @@ class GitlabSubscription < ApplicationRecord ...@@ -36,8 +36,8 @@ class GitlabSubscription < ApplicationRecord
[0, max_seats_used - seats].max [0, max_seats_used - seats].max
end end
def has_a_paid_hosted_plan? def has_a_paid_hosted_plan?(include_trials: false)
!trial? && (include_trials || !trial?) &&
hosted? && hosted? &&
seats > 0 && seats > 0 &&
Plan::PAID_HOSTED_PLANS.include?(plan_name) Plan::PAID_HOSTED_PLANS.include?(plan_name)
...@@ -88,13 +88,18 @@ class GitlabSubscription < ApplicationRecord ...@@ -88,13 +88,18 @@ class GitlabSubscription < ApplicationRecord
namespace_id.present? namespace_id.present?
end end
def automatically_index_in_elasticsearch?
return false unless ::Gitlab.dev_env_or_com?
return false if expired?
has_a_paid_hosted_plan?(include_trials: true)
end
# Kick off Elasticsearch indexing for paid groups with new or upgraded paid, hosted subscriptions # Kick off Elasticsearch indexing for paid groups with new or upgraded paid, hosted subscriptions
# Uses safe_find_or_create_by to avoid ActiveRecord::RecordNotUnique exception when upgrading from # Uses safe_find_or_create_by to avoid ActiveRecord::RecordNotUnique exception when upgrading from
# one paid plan to another paid plan # one paid plan to another paid plan
def index_namespace def index_namespace
return unless ::Feature.enabled?(:elasticsearch_index_only_paid_groups) && return unless automatically_index_in_elasticsearch?
has_a_paid_hosted_plan? &&
saved_changes.key?('hosted_plan_id')
ElasticsearchIndexedNamespace.safe_find_or_create_by!(namespace_id: namespace_id) ElasticsearchIndexedNamespace.safe_find_or_create_by!(namespace_id: namespace_id)
end end
......
---
title: Index trial groups in Elasticsearch
merge_request: 38541
author:
type: added
...@@ -254,39 +254,71 @@ RSpec.describe GitlabSubscription do ...@@ -254,39 +254,71 @@ RSpec.describe GitlabSubscription do
describe 'callbacks' do describe 'callbacks' do
context 'after_commit :index_namespace' do context 'after_commit :index_namespace' do
where(:elasticsearch_index_only_paid_groups_setting, :operation, :initial_plan, :should_update_plan?, :should_index_namespace?) do let(:gitlab_subscription) { build(:gitlab_subscription, plan) }
false | :create | :bronze | false | false let(:dev_env_or_com) { true }
true | :create | :bronze | false | true let(:expiration_date) { Date.today + 10 }
true | :create | :free | false | false let(:plan) { :bronze }
true | :create | { trial: true } | false | false
false | :update | :bronze | false | false before do
true | :update | :bronze | false | false allow(::Gitlab).to receive(:dev_env_or_com?).and_return(dev_env_or_com)
true | :update | :bronze | true | true gitlab_subscription.end_date = expiration_date
true | :update | :free | true | true end
true | :update | { trial: true } | true | true
it 'indexes the namespace' do
expect(ElasticsearchIndexedNamespace).to receive(:safe_find_or_create_by!).with(namespace_id: gitlab_subscription.namespace_id)
gitlab_subscription.save!
end
context 'when it is a trial' do
let(:gitlab_subscription) { build(:gitlab_subscription, :active_trial) }
it 'indexes the namespace' do
expect(ElasticsearchIndexedNamespace).to receive(:safe_find_or_create_by!).with(namespace_id: gitlab_subscription.namespace_id)
gitlab_subscription.save!
end
end
context 'when not ::Gitlab.dev_env_or_com?' do
let(:dev_env_or_com) { false }
it 'does not index the namespace' do
expect(ElasticsearchIndexedNamespace).not_to receive(:safe_find_or_create_by!)
gitlab_subscription.save!
end
end end
with_them do context 'when the plan has expired' do
let!(:gitlab_subscription) { operation == :create ? build(:gitlab_subscription, initial_plan) : create(:gitlab_subscription, initial_plan) } let(:expiration_date) { Date.today - 8.days }
it 'does not index the namespace' do
expect(ElasticsearchIndexedNamespace).not_to receive(:safe_find_or_create_by!)
gitlab_subscription.save!
end
end
context 'when it is not a hosted plan' do
before do before do
stub_feature_flags(elasticsearch_index_only_paid_groups: elasticsearch_index_only_paid_groups_setting) gitlab_subscription.namespace_id = nil
end end
it 'indexes namespace' do it 'does not index anything' do
if should_index_namespace? expect(ElasticsearchIndexedNamespace).not_to receive(:safe_find_or_create_by!)
expect(ElasticsearchIndexedNamespace).to receive(:safe_find_or_create_by!).with(namespace_id: gitlab_subscription.namespace_id)
else
expect(ElasticsearchIndexedNamespace).not_to receive(:safe_find_or_create_by!)
end
case operation gitlab_subscription.save!
when :create end
gitlab_subscription.save! end
when :update
update_attributes = should_update_plan? ? { hosted_plan: create(:silver_plan), trial: false } : { max_seats_used: 32 } context 'when it is a free plan' do
gitlab_subscription.update!(update_attributes) let(:plan) { :free }
end
it 'does not index the namespace' do
expect(ElasticsearchIndexedNamespace).not_to receive(:safe_find_or_create_by!)
gitlab_subscription.save!
end 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