Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-11-09 06:13:00 +00:00
parent 7dd9256e5e
commit e9112f3002
26 changed files with 366 additions and 150 deletions

View File

@ -19,6 +19,8 @@ tasks:
# ensure gdk.yml has correct instance settings # ensure gdk.yml has correct instance settings
gdk config set gitlab.rails.port 443 gdk config set gitlab.rails.port 443
gdk config set gitlab.rails.https.enabled true gdk config set gitlab.rails.https.enabled true
# make documentation builds available
gdk config set gitlab_docs.enabled true
# reconfigure GDK # reconfigure GDK
echo "$(date) Reconfiguring GDK" | tee -a /workspace/startup.log echo "$(date) Reconfiguring GDK" | tee -a /workspace/startup.log
gdk reconfigure gdk reconfigure
@ -83,6 +85,8 @@ ports:
onOpen: ignore onOpen: ignore
- port: 3000 # rails-web - port: 3000 # rails-web
onOpen: notify onOpen: notify
- port: 3005 # gitlab-docs
onOpen: notify
- port: 3010 # gitlab-pages - port: 3010 # gitlab-pages
onOpen: ignore onOpen: ignore
- port: 3808 # webpack - port: 3808 # webpack
@ -102,3 +106,4 @@ vscode:
- octref.vetur@0.34.1 - octref.vetur@0.34.1
- dbaeumer.vscode-eslint@2.1.8 - dbaeumer.vscode-eslint@2.1.8
- gitlab.gitlab-workflow@3.24.0 - gitlab.gitlab-workflow@3.24.0
- DavidAnson.vscode-markdownlint@0.44.4

View File

@ -1,6 +1,7 @@
<script> <script>
import { GlButton, GlSprintf, GlLink, GlSafeHtmlDirective } from '@gitlab/ui'; import { GlButton, GlSprintf, GlLink, GlSafeHtmlDirective } from '@gitlab/ui';
import emptyStateSVG from 'icons/_mr_widget_empty_state.svg'; import emptyStateSVG from 'icons/_mr_widget_empty_state.svg';
import api from '~/api';
import { helpPagePath } from '~/helpers/help_page_helper'; import { helpPagePath } from '~/helpers/help_page_helper';
export default { export default {
@ -22,6 +23,11 @@ export default {
data() { data() {
return { emptyStateSVG }; return { emptyStateSVG };
}, },
methods: {
onClickNewFile() {
api.trackRedisHllUserEvent('i_code_review_widget_nothing_merge_click_new_file');
},
},
ciHelpPage: helpPagePath('/ci/quick_start/index.html'), ciHelpPage: helpPagePath('/ci/quick_start/index.html'),
safeHtmlConfig: { ADD_TAGS: ['use'] }, safeHtmlConfig: { ADD_TAGS: ['use'] },
}; };
@ -59,6 +65,7 @@ export default {
category="secondary" category="secondary"
variant="success" variant="success"
data-testid="createFileButton" data-testid="createFileButton"
@click="onClickNewFile"
> >
{{ __('Create file') }} {{ __('Create file') }}
</gl-button> </gl-button>

View File

@ -11,5 +11,5 @@
= preload_link_tag(path_to_stylesheet('application_utilities'), crossorigin: css_crossorigin) = preload_link_tag(path_to_stylesheet('application_utilities'), crossorigin: css_crossorigin)
= preload_link_tag(path_to_stylesheet('application'), crossorigin: css_crossorigin) = preload_link_tag(path_to_stylesheet('application'), crossorigin: css_crossorigin)
= preload_link_tag(path_to_stylesheet("highlight/themes/#{user_color_scheme}"), crossorigin: css_crossorigin) = preload_link_tag(path_to_stylesheet("highlight/themes/#{user_color_scheme}"), crossorigin: css_crossorigin)
- if Gitlab::Tracking.enabled? && Gitlab::CurrentSettings.snowplow_collector_hostname - if Gitlab::Tracking.enabled? && Gitlab::Tracking.collector_hostname
%link{ rel: 'preconnect', href: Gitlab::CurrentSettings.snowplow_collector_hostname, crossorigin: '' } %link{ rel: 'preconnect', href: Gitlab::Tracking.collector_hostname, crossorigin: '' }

View File

@ -20,7 +20,7 @@ Gitlab::Database::LoadBalancing.base_models.each do |model|
Gitlab::Cluster::LifecycleEvents.on_before_fork do Gitlab::Cluster::LifecycleEvents.on_before_fork do
# When forking, we don't want to wait until the connections aren't in use # When forking, we don't want to wait until the connections aren't in use
# any more, as this could delay the boot cycle. # any more, as this could delay the boot cycle.
model.connection.load_balancer.disconnect!(timeout: 0) model.load_balancer.disconnect!(timeout: 0)
end end
# Service discovery only needs to run in the worker processes, as the main one # Service discovery only needs to run in the worker processes, as the main one

View File

@ -67,6 +67,7 @@
- 'i_code_review_user_resolve_conflict' - 'i_code_review_user_resolve_conflict'
- 'i_code_review_user_searches_diff' - 'i_code_review_user_searches_diff'
- 'i_code_review_user_resolve_thread_in_issue' - 'i_code_review_user_resolve_thread_in_issue'
- 'i_code_review_widget_nothing_merge_click_new_file'
- name: code_review_category_monthly_active_users - name: code_review_category_monthly_active_users
operator: OR operator: OR
source: redis source: redis
@ -126,6 +127,7 @@
- 'i_code_review_user_resolve_conflict' - 'i_code_review_user_resolve_conflict'
- 'i_code_review_user_searches_diff' - 'i_code_review_user_searches_diff'
- 'i_code_review_user_resolve_thread_in_issue' - 'i_code_review_user_resolve_thread_in_issue'
- 'i_code_review_widget_nothing_merge_click_new_file'
- name: code_review_extension_category_monthly_active_users - name: code_review_extension_category_monthly_active_users
operator: OR operator: OR
source: redis source: redis

View File

@ -0,0 +1,25 @@
---
key_path: redis_hll_counters.code_review.i_code_review_widget_nothing_merge_click_new_file_monthly
description: Count of users who click the create file button in the nothing to merge widget state
product_section: dev
product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
status: active
milestone: '14.5'
introduced_by_url:
time_frame: 28d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
options:
events:
- i_code_review_widget_nothing_merge_click_new_file
data_category: optional
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,25 @@
---
key_path: redis_hll_counters.code_review.i_code_review_widget_nothing_merge_click_new_file_weekly
description: Count of users who click the create file button in the nothing to merge widget state
product_section: dev
product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
status: active
milestone: '14.5'
introduced_by_url:
time_frame: 7d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
options:
events:
- i_code_review_widget_nothing_merge_click_new_file
data_category: optional
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -424,7 +424,7 @@ records the same events as the full Snowplow pipeline. To query events, use the
To install and run Snowplow Micro, complete these steps to modify the To install and run Snowplow Micro, complete these steps to modify the
[GitLab Development Kit (GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit): [GitLab Development Kit (GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit):
1. Ensure Docker is installed and running. 1. Ensure [Docker is installed](https://docs.docker.com/get-docker/) and running.
1. To install Snowplow Micro, clone the settings in 1. To install Snowplow Micro, clone the settings in
[this project](https://gitlab.com/gitlab-org/snowplow-micro-configuration). [this project](https://gitlab.com/gitlab-org/snowplow-micro-configuration).
@ -436,73 +436,18 @@ To install and run Snowplow Micro, complete these steps to modify the
./snowplow-micro.sh ./snowplow-micro.sh
``` ```
1. Use GDK to start the PostgreSQL terminal and connect 1. Set the environment variable to tell the GDK to use Snowplow Micro in development. This overrides two `application_settings` options:
to the `gitlabhq_development` database: - `snowplow_enabled` setting will instead return `true` from `Gitlab::Tracking.enabled?`
- `snowplow_collector_hostname` setting will instead always return `localhost:9090` (or whatever is set for `SNOWPLOW_MICRO_URI`) from `Gitlab::Tracking.collector_hostname`.
```shell ```shell
gdk psql -d gitlabhq_development export SNOWPLOW_MICRO_ENABLE=1
``` ```
1. Update your instance's settings to enable Snowplow events and Optionally, you can set the URI for you Snowplow Micro instance as well (the default value is `http://localhost:9090`):
point to the Snowplow Micro collector:
```shell ```shell
update application_settings set snowplow_collector_hostname='localhost:9090', snowplow_enabled=true, snowplow_cookie_domain='.gitlab.com'; export SNOWPLOW_MICRO_URI=https://127.0.0.1:8080
```
1. Update `DEFAULT_SNOWPLOW_OPTIONS` in `app/assets/javascripts/tracking/constants.js` to remove `forceSecureTracker: true`:
```diff
diff --git a/app/assets/javascripts/tracking/constants.js b/app/assets/javascripts/tracking/constants.js
index 598111e4086..eff38074d4c 100644
--- a/app/assets/javascripts/tracking/constants.js
+++ b/app/assets/javascripts/tracking/constants.js
@@ -7,7 +7,6 @@ export const DEFAULT_SNOWPLOW_OPTIONS = {
appId: '',
userFingerprint: false,
respectDoNotTrack: true,
- forceSecureTracker: true,
eventMethod: 'post',
contexts: { webPage: true, performanceTiming: true },
formTracking: false,
```
1. Update `options` in `lib/gitlab/tracking.rb` to add `protocol` and `port`:
```diff
diff --git a/lib/gitlab/tracking.rb b/lib/gitlab/tracking.rb
index 618e359211b..e9084623c43 100644
--- a/lib/gitlab/tracking.rb
+++ b/lib/gitlab/tracking.rb
@@ -41,7 +41,9 @@ def options(group)
cookie_domain: Gitlab::CurrentSettings.snowplow_cookie_domain,
app_id: Gitlab::CurrentSettings.snowplow_app_id,
form_tracking: additional_features,
- link_click_tracking: additional_features
+ link_click_tracking: additional_features,
+ protocol: 'http',
+ port: 9090
}.transform_keys! { |key| key.to_s.camelize(:lower).to_sym }
end
```
1. Update `emitter` in `lib/gitlab/tracking/destinations/snowplow.rb` to change `protocol`:
```diff
diff --git a/lib/gitlab/tracking/destinations/snowplow.rb b/lib/gitlab/tracking/destinations/snowplow.rb
index 4fa844de325..5dd9d0eacfb 100644
--- a/lib/gitlab/tracking/destinations/snowplow.rb
+++ b/lib/gitlab/tracking/destinations/snowplow.rb
@@ -40,7 +40,7 @@ def tracker
def emitter
SnowplowTracker::AsyncEmitter.new(
Gitlab::CurrentSettings.snowplow_collector_hostname,
- protocol: 'https'
+ protocol: 'http'
)
end
end
``` ```
1. Restart GDK: 1. Restart GDK:

View File

@ -26,7 +26,7 @@ module Gitlab
return to_enum(__method__) unless block_given? return to_enum(__method__) unless block_given?
base_models.each do |model| base_models.each do |model|
yield model.connection.load_balancer yield model.load_balancer
end end
end end

View File

@ -13,7 +13,15 @@ module Gitlab
WriteInsideReadOnlyTransactionError = Class.new(StandardError) WriteInsideReadOnlyTransactionError = Class.new(StandardError)
READ_ONLY_TRANSACTION_KEY = :load_balacing_read_only_transaction READ_ONLY_TRANSACTION_KEY = :load_balacing_read_only_transaction
attr_reader :load_balancer # The load balancer is intentionally not exposed since the returned instance
# might be different `model.connection.load_balancer` vs `model.load_balancer`
#
# The used `model.connection` is dependent on `use_model_load_balancing`.
# See more in: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73949.
#
# Always use `model.load_balancer` or `model.sticking`.
#
# attr_reader :load_balancer
# These methods perform writes after which we need to stick to the # These methods perform writes after which we need to stick to the
# primary. # primary.

View File

@ -40,6 +40,7 @@ module Gitlab
def setup_connection_proxy def setup_connection_proxy
# We just use a simple `class_attribute` here so we don't need to # We just use a simple `class_attribute` here so we don't need to
# inject any modules and/or expose unnecessary methods. # inject any modules and/or expose unnecessary methods.
setup_class_attribute(:load_balancer, load_balancer)
setup_class_attribute(:connection, ConnectionProxy.new(load_balancer)) setup_class_attribute(:connection, ConnectionProxy.new(load_balancer))
setup_class_attribute(:sticking, Sticking.new(load_balancer)) setup_class_attribute(:sticking, Sticking.new(load_balancer))
end end
@ -107,10 +108,6 @@ module Gitlab
def connection def connection
use_model_load_balancing? ? super : ActiveRecord::Base.connection use_model_load_balancing? ? super : ActiveRecord::Base.connection
end end
def sticking
use_model_load_balancing? ? super : ActiveRecord::Base.sticking
end
# rubocop:enable Database/MultipleDatabases # rubocop:enable Database/MultipleDatabases
end end
end end

View File

@ -6,7 +6,7 @@ module Gitlab
class << self class << self
def enabled? def enabled?
Gitlab::CurrentSettings.snowplow_enabled? snowplow_micro_enabled? || Gitlab::CurrentSettings.snowplow_enabled?
end end
def event(category, action, label: nil, property: nil, value: nil, context: [], project: nil, user: nil, namespace: nil, **extra) # rubocop:disable Metrics/ParameterLists def event(category, action, label: nil, property: nil, value: nil, context: [], project: nil, user: nil, namespace: nil, **extra) # rubocop:disable Metrics/ParameterLists
@ -18,21 +18,25 @@ module Gitlab
end end
def options(group) def options(group)
additional_features = Feature.enabled?(:additional_snowplow_tracking, group, type: :ops) snowplow.options(group)
{ end
namespace: SNOWPLOW_NAMESPACE,
hostname: Gitlab::CurrentSettings.snowplow_collector_hostname, def collector_hostname
cookie_domain: Gitlab::CurrentSettings.snowplow_cookie_domain, snowplow.hostname
app_id: Gitlab::CurrentSettings.snowplow_app_id,
form_tracking: additional_features,
link_click_tracking: additional_features
}.transform_keys! { |key| key.to_s.camelize(:lower).to_sym }
end end
private private
def snowplow def snowplow
@snowplow ||= Gitlab::Tracking::Destinations::Snowplow.new @snowplow ||= if snowplow_micro_enabled?
Gitlab::Tracking::Destinations::SnowplowMicro.new
else
Gitlab::Tracking::Destinations::Snowplow.new
end
end
def snowplow_micro_enabled?
Rails.env.development? && Gitlab::Utils.to_boolean(ENV['SNOWPLOW_MICRO_ENABLE'])
end end
end end
end end

View File

@ -16,25 +16,53 @@ module Gitlab
increment_total_events_counter increment_total_events_counter
end end
def options(group)
additional_features = Feature.enabled?(:additional_snowplow_tracking, group, type: :ops)
{
namespace: Gitlab::Tracking::SNOWPLOW_NAMESPACE,
hostname: hostname,
cookie_domain: cookie_domain,
app_id: app_id,
form_tracking: additional_features,
link_click_tracking: additional_features
}.transform_keys! { |key| key.to_s.camelize(:lower).to_sym }
end
def hostname
Gitlab::CurrentSettings.snowplow_collector_hostname
end
private private
def enabled? def enabled?
Gitlab::Tracking.enabled? Gitlab::Tracking.enabled?
end end
def app_id
Gitlab::CurrentSettings.snowplow_app_id
end
def protocol
'https'
end
def cookie_domain
Gitlab::CurrentSettings.snowplow_cookie_domain
end
def tracker def tracker
@tracker ||= SnowplowTracker::Tracker.new( @tracker ||= SnowplowTracker::Tracker.new(
emitter, emitter,
SnowplowTracker::Subject.new, SnowplowTracker::Subject.new,
Gitlab::Tracking::SNOWPLOW_NAMESPACE, Gitlab::Tracking::SNOWPLOW_NAMESPACE,
Gitlab::CurrentSettings.snowplow_app_id app_id
) )
end end
def emitter def emitter
SnowplowTracker::AsyncEmitter.new( SnowplowTracker::AsyncEmitter.new(
Gitlab::CurrentSettings.snowplow_collector_hostname, hostname,
protocol: 'https', protocol: protocol,
on_success: method(:increment_successful_events_emissions), on_success: method(:increment_successful_events_emissions),
on_failure: method(:failure_callback) on_failure: method(:failure_callback)
) )
@ -68,8 +96,6 @@ module Gitlab
end end
def log_failures(failures) def log_failures(failures)
hostname = Gitlab::CurrentSettings.snowplow_collector_hostname
failures.each do |failure| failures.each do |failure|
Gitlab::AppLogger.error("#{failure["se_ca"]} #{failure["se_ac"]} failed to be reported to collector at #{hostname}") Gitlab::AppLogger.error("#{failure["se_ca"]} #{failure["se_ac"]} failed to be reported to collector at #{hostname}")
end end

View File

@ -0,0 +1,48 @@
# frozen_string_literal: true
#
module Gitlab
module Tracking
module Destinations
class SnowplowMicro < Snowplow
include ::Gitlab::Utils::StrongMemoize
extend ::Gitlab::Utils::Override
DEFAULT_URI = 'http://localhost:9090'
override :options
def options(group)
super.update(
protocol: uri.scheme,
port: uri.port,
force_secure_tracker: false
)
end
override :hostname
def hostname
"#{uri.host}:#{uri.port}"
end
private
def uri
strong_memoize(:snowplow_uri) do
uri = URI(ENV['SNOWPLOW_MICRO_URI'] || DEFAULT_URI)
uri = URI("http://#{ENV['SNOWPLOW_MICRO_URI']}") unless %w[http https].include?(uri.scheme)
uri
end
end
override :cookie_domain
def cookie_domain
'.gitlab.com'
end
override :protocol
def protocol
uri.scheme
end
end
end
end
end

View File

@ -249,3 +249,7 @@
redis_slot: code_review redis_slot: code_review
category: code_review category: code_review
aggregation: weekly aggregation: weekly
- name: i_code_review_widget_nothing_merge_click_new_file
redis_slot: code_review
category: code_review
aggregation: weekly

View File

@ -3,12 +3,9 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
let(:proxy) do let(:config) { Gitlab::Database::LoadBalancing::Configuration.new(ActiveRecord::Base) }
config = Gitlab::Database::LoadBalancing::Configuration let(:load_balancer) { Gitlab::Database::LoadBalancing::LoadBalancer.new(config) }
.new(ActiveRecord::Base) let(:proxy) { described_class.new(load_balancer) }
described_class.new(Gitlab::Database::LoadBalancing::LoadBalancer.new(config))
end
describe '#select' do describe '#select' do
it 'performs a read' do it 'performs a read' do
@ -143,9 +140,9 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
context 'with a read query' do context 'with a read query' do
it 'runs the transaction and any nested queries on the replica' do it 'runs the transaction and any nested queries on the replica' do
expect(proxy.load_balancer).to receive(:read) expect(load_balancer).to receive(:read)
.twice.and_yield(replica) .twice.and_yield(replica)
expect(proxy.load_balancer).not_to receive(:read_write) expect(load_balancer).not_to receive(:read_write)
expect(session).not_to receive(:write!) expect(session).not_to receive(:write!)
proxy.transaction { proxy.select('true') } proxy.transaction { proxy.select('true') }
@ -154,8 +151,8 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
context 'with a write query' do context 'with a write query' do
it 'raises an exception' do it 'raises an exception' do
allow(proxy.load_balancer).to receive(:read).and_yield(replica) allow(load_balancer).to receive(:read).and_yield(replica)
allow(proxy.load_balancer).to receive(:read_write).and_yield(replica) allow(load_balancer).to receive(:read_write).and_yield(replica)
expect do expect do
proxy.transaction { proxy.insert('something') } proxy.transaction { proxy.insert('something') }
@ -178,9 +175,9 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
context 'with a read query' do context 'with a read query' do
it 'runs the transaction and any nested queries on the primary and stick to it' do it 'runs the transaction and any nested queries on the primary and stick to it' do
expect(proxy.load_balancer).to receive(:read_write) expect(load_balancer).to receive(:read_write)
.twice.and_yield(primary) .twice.and_yield(primary)
expect(proxy.load_balancer).not_to receive(:read) expect(load_balancer).not_to receive(:read)
expect(session).to receive(:write!) expect(session).to receive(:write!)
proxy.transaction { proxy.select('true') } proxy.transaction { proxy.select('true') }
@ -189,9 +186,9 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
context 'with a write query' do context 'with a write query' do
it 'runs the transaction and any nested queries on the primary and stick to it' do it 'runs the transaction and any nested queries on the primary and stick to it' do
expect(proxy.load_balancer).to receive(:read_write) expect(load_balancer).to receive(:read_write)
.twice.and_yield(primary) .twice.and_yield(primary)
expect(proxy.load_balancer).not_to receive(:read) expect(load_balancer).not_to receive(:read)
expect(session).to receive(:write!).twice expect(session).to receive(:write!).twice
proxy.transaction { proxy.insert('something') } proxy.transaction { proxy.insert('something') }
@ -209,7 +206,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
end end
it 'properly forwards keyword arguments' do it 'properly forwards keyword arguments' do
allow(proxy.load_balancer).to receive(:read_write) allow(load_balancer).to receive(:read_write)
expect(proxy).to receive(:write_using_load_balancer).and_call_original expect(proxy).to receive(:write_using_load_balancer).and_call_original
@ -234,7 +231,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
end end
it 'properly forwards keyword arguments' do it 'properly forwards keyword arguments' do
allow(proxy.load_balancer).to receive(:read) allow(load_balancer).to receive(:read)
expect(proxy).to receive(:read_using_load_balancer).and_call_original expect(proxy).to receive(:read_using_load_balancer).and_call_original
@ -259,7 +256,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
allow(session).to receive(:use_replicas_for_read_queries?).and_return(false) allow(session).to receive(:use_replicas_for_read_queries?).and_return(false)
expect(connection).to receive(:foo).with('foo') expect(connection).to receive(:foo).with('foo')
expect(proxy.load_balancer).to receive(:read).and_yield(connection) expect(load_balancer).to receive(:read).and_yield(connection)
proxy.read_using_load_balancer(:foo, 'foo') proxy.read_using_load_balancer(:foo, 'foo')
end end
@ -271,7 +268,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
allow(session).to receive(:use_replicas_for_read_queries?).and_return(true) allow(session).to receive(:use_replicas_for_read_queries?).and_return(true)
expect(connection).to receive(:foo).with('foo') expect(connection).to receive(:foo).with('foo')
expect(proxy.load_balancer).to receive(:read).and_yield(connection) expect(load_balancer).to receive(:read).and_yield(connection)
proxy.read_using_load_balancer(:foo, 'foo') proxy.read_using_load_balancer(:foo, 'foo')
end end
@ -283,7 +280,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
allow(session).to receive(:use_replicas_for_read_queries?).and_return(true) allow(session).to receive(:use_replicas_for_read_queries?).and_return(true)
expect(connection).to receive(:foo).with('foo') expect(connection).to receive(:foo).with('foo')
expect(proxy.load_balancer).to receive(:read).and_yield(connection) expect(load_balancer).to receive(:read).and_yield(connection)
proxy.read_using_load_balancer(:foo, 'foo') proxy.read_using_load_balancer(:foo, 'foo')
end end
@ -296,7 +293,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
expect(connection).to receive(:foo).with('foo') expect(connection).to receive(:foo).with('foo')
expect(proxy.load_balancer).to receive(:read_write) expect(load_balancer).to receive(:read_write)
.and_yield(connection) .and_yield(connection)
proxy.read_using_load_balancer(:foo, 'foo') proxy.read_using_load_balancer(:foo, 'foo')
@ -314,7 +311,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
end end
it 'uses but does not stick to the primary' do it 'uses but does not stick to the primary' do
expect(proxy.load_balancer).to receive(:read_write).and_yield(connection) expect(load_balancer).to receive(:read_write).and_yield(connection)
expect(connection).to receive(:foo).with('foo') expect(connection).to receive(:foo).with('foo')
expect(session).not_to receive(:write!) expect(session).not_to receive(:write!)

View File

@ -61,7 +61,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
setup.setup_connection_proxy setup.setup_connection_proxy
expect(model.connection.load_balancer).to eq(lb) expect(model.load_balancer).to eq(lb)
expect(model.sticking) expect(model.sticking)
.to be_an_instance_of(Gitlab::Database::LoadBalancing::Sticking) .to be_an_instance_of(Gitlab::Database::LoadBalancing::Sticking)
end end
@ -265,17 +265,19 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
stub_env('GITLAB_USE_MODEL_LOAD_BALANCING', env_GITLAB_USE_MODEL_LOAD_BALANCING) stub_env('GITLAB_USE_MODEL_LOAD_BALANCING', env_GITLAB_USE_MODEL_LOAD_BALANCING)
stub_env('GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci', env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci) stub_env('GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci', env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci)
stub_feature_flags(use_model_load_balancing: ff_use_model_load_balancing) stub_feature_flags(use_model_load_balancing: ff_use_model_load_balancing)
end
it 'results match expectations' do # Make load balancer to force init with a dedicated replicas connections
result = models.transform_values do |model| models.each do |_, model|
# Make load balancer to force init with a dedicated replicas connections
described_class.new(model).tap do |subject| described_class.new(model).tap do |subject|
subject.configuration.hosts = [subject.configuration.replica_db_config.host] subject.configuration.hosts = [subject.configuration.replica_db_config.host]
subject.setup subject.setup
end end
end
end
load_balancer = model.connection.load_balancer it 'results match expectations' do
result = models.transform_values do |model|
load_balancer = model.connection.instance_variable_get(:@load_balancer)
{ {
read: load_balancer.read { |connection| connection.pool.db_config.name }, read: load_balancer.read { |connection| connection.pool.db_config.name },
@ -285,6 +287,13 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
expect(result).to eq(expectations) expect(result).to eq(expectations)
end end
it 'does return load_balancer assigned to a given connection' do
models.each do |name, model|
expect(model.load_balancer.name).to eq(name)
expect(model.sticking.instance_variable_get(:@load_balancer)).to eq(model.load_balancer)
end
end
end end
end end
end end

View File

@ -181,11 +181,11 @@ RSpec.describe Gitlab::Database::LoadBalancing::SidekiqClientMiddleware do
end end
context 'when worker data consistency is :delayed' do context 'when worker data consistency is :delayed' do
include_examples 'mark data consistency location', :delayed include_examples 'mark data consistency location', :delayed
end end
context 'when worker data consistency is :sticky' do context 'when worker data consistency is :sticky' do
include_examples 'mark data consistency location', :sticky include_examples 'mark data consistency location', :sticky
end end
end end
end end

View File

@ -64,7 +64,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::SidekiqServerMiddleware, :clean_
let(:wal_locations) { { Gitlab::Database::MAIN_DATABASE_NAME.to_sym => location } } let(:wal_locations) { { Gitlab::Database::MAIN_DATABASE_NAME.to_sym => location } }
it 'does not stick to the primary', :aggregate_failures do it 'does not stick to the primary', :aggregate_failures do
expect(ActiveRecord::Base.connection.load_balancer) expect(ActiveRecord::Base.load_balancer)
.to receive(:select_up_to_date_host) .to receive(:select_up_to_date_host)
.with(location) .with(location)
.and_return(true) .and_return(true)
@ -107,7 +107,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::SidekiqServerMiddleware, :clean_
let(:job) { { 'job_id' => 'a180b47c-3fd6-41b8-81e9-34da61c3400e', 'dedup_wal_locations' => wal_locations } } let(:job) { { 'job_id' => 'a180b47c-3fd6-41b8-81e9-34da61c3400e', 'dedup_wal_locations' => wal_locations } }
before do before do
allow(ActiveRecord::Base.connection.load_balancer) allow(ActiveRecord::Base.load_balancer)
.to receive(:select_up_to_date_host) .to receive(:select_up_to_date_host)
.with(wal_locations[:main]) .with(wal_locations[:main])
.and_return(true) .and_return(true)
@ -120,7 +120,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::SidekiqServerMiddleware, :clean_
let(:job) { { 'job_id' => 'a180b47c-3fd6-41b8-81e9-34da61c3400e', 'database_write_location' => '0/D525E3A8' } } let(:job) { { 'job_id' => 'a180b47c-3fd6-41b8-81e9-34da61c3400e', 'database_write_location' => '0/D525E3A8' } }
before do before do
allow(ActiveRecord::Base.connection.load_balancer) allow(ActiveRecord::Base.load_balancer)
.to receive(:select_up_to_date_host) .to receive(:select_up_to_date_host)
.with('0/D525E3A8') .with('0/D525E3A8')
.and_return(true) .and_return(true)

View File

@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
let(:sticking) do let(:sticking) do
described_class.new(ActiveRecord::Base.connection.load_balancer) described_class.new(ActiveRecord::Base.load_balancer)
end end
after do after do
@ -73,7 +73,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
end end
describe '#all_caught_up?' do describe '#all_caught_up?' do
let(:lb) { ActiveRecord::Base.connection.load_balancer } let(:lb) { ActiveRecord::Base.load_balancer }
let(:last_write_location) { 'foo' } let(:last_write_location) { 'foo' }
before do before do
@ -137,7 +137,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
end end
describe '#unstick_or_continue_sticking' do describe '#unstick_or_continue_sticking' do
let(:lb) { ActiveRecord::Base.connection.load_balancer } let(:lb) { ActiveRecord::Base.load_balancer }
it 'simply returns if no write location could be found' do it 'simply returns if no write location could be found' do
allow(sticking) allow(sticking)
@ -182,13 +182,13 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
RSpec.shared_examples 'sticking' do RSpec.shared_examples 'sticking' do
before do before do
allow(ActiveRecord::Base.connection.load_balancer) allow(ActiveRecord::Base.load_balancer)
.to receive(:primary_write_location) .to receive(:primary_write_location)
.and_return('foo') .and_return('foo')
end end
it 'sticks an entity to the primary', :aggregate_failures do it 'sticks an entity to the primary', :aggregate_failures do
allow(ActiveRecord::Base.connection.load_balancer) allow(ActiveRecord::Base.load_balancer)
.to receive(:primary_only?) .to receive(:primary_only?)
.and_return(false) .and_return(false)
@ -227,11 +227,11 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
describe '#mark_primary_write_location' do describe '#mark_primary_write_location' do
it 'updates the write location with the load balancer' do it 'updates the write location with the load balancer' do
allow(ActiveRecord::Base.connection.load_balancer) allow(ActiveRecord::Base.load_balancer)
.to receive(:primary_write_location) .to receive(:primary_write_location)
.and_return('foo') .and_return('foo')
allow(ActiveRecord::Base.connection.load_balancer) allow(ActiveRecord::Base.load_balancer)
.to receive(:primary_only?) .to receive(:primary_only?)
.and_return(false) .and_return(false)
@ -291,7 +291,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
end end
describe '#select_caught_up_replicas' do describe '#select_caught_up_replicas' do
let(:lb) { ActiveRecord::Base.connection.load_balancer } let(:lb) { ActiveRecord::Base.load_balancer }
context 'with no write location' do context 'with no write location' do
before do before do

View File

@ -76,7 +76,7 @@ RSpec.describe Gitlab::Database::LoadBalancing do
context 'when a read connection is used' do context 'when a read connection is used' do
it 'returns :replica' do it 'returns :replica' do
proxy.load_balancer.read do |connection| load_balancer.read do |connection|
expect(described_class.db_role_for_connection(connection)).to eq(:replica) expect(described_class.db_role_for_connection(connection)).to eq(:replica)
end end
end end
@ -84,7 +84,7 @@ RSpec.describe Gitlab::Database::LoadBalancing do
context 'when a read_write connection is used' do context 'when a read_write connection is used' do
it 'returns :primary' do it 'returns :primary' do
proxy.load_balancer.read_write do |connection| load_balancer.read_write do |connection|
expect(described_class.db_role_for_connection(connection)).to eq(:primary) expect(described_class.db_role_for_connection(connection)).to eq(:primary)
end end
end end

View File

@ -64,7 +64,7 @@ RSpec.describe Gitlab::Database::QueryAnalyzer do
end end
def process_sql(sql) def process_sql(sql)
ApplicationRecord.connection.load_balancer.read_write do |connection| ApplicationRecord.load_balancer.read_write do |connection|
described_class.new.send(:process_sql, sql, connection) described_class.new.send(:process_sql, sql, connection)
end end
end end

View File

@ -205,7 +205,7 @@ RSpec.describe Gitlab::Database do
context 'when replicas are configured', :database_replica do context 'when replicas are configured', :database_replica do
it 'returns the name for a replica' do it 'returns the name for a replica' do
replica = ActiveRecord::Base.connection.load_balancer.host replica = ActiveRecord::Base.load_balancer.host
expect(described_class.db_config_name(replica)).to eq('main_replica') expect(described_class.db_config_name(replica)).to eq('main_replica')
end end

View File

@ -0,0 +1,51 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Tracking::Destinations::SnowplowMicro do
include StubENV
before do
stub_application_setting(snowplow_enabled: true)
stub_env('SNOWPLOW_MICRO_ENABLE', '1')
allow(Rails.env).to receive(:development?).and_return(true)
end
describe '#hostname' do
context 'when SNOWPLOW_MICRO_URI is set' do
before do
stub_env('SNOWPLOW_MICRO_URI', 'http://gdk.test:9091')
end
it 'returns hostname URI part' do
expect(subject.hostname).to eq('gdk.test:9091')
end
end
context 'when SNOWPLOW_MICRO_URI is without protocol' do
before do
stub_env('SNOWPLOW_MICRO_URI', 'gdk.test:9091')
end
it 'returns hostname URI part' do
expect(subject.hostname).to eq('gdk.test:9091')
end
end
context 'when SNOWPLOW_MICRO_URI is hostname only' do
before do
stub_env('SNOWPLOW_MICRO_URI', 'uriwithoutport')
end
it 'returns hostname URI with default HTTP port' do
expect(subject.hostname).to eq('uriwithoutport:80')
end
end
context 'when SNOWPLOW_MICRO_URI is not set' do
it 'returns localhost hostname' do
expect(subject.hostname).to eq('localhost:9090')
end
end
end
end

View File

@ -2,6 +2,8 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::Tracking do RSpec.describe Gitlab::Tracking do
include StubENV
before do before do
stub_application_setting(snowplow_enabled: true) stub_application_setting(snowplow_enabled: true)
stub_application_setting(snowplow_collector_hostname: 'gitfoo.com') stub_application_setting(snowplow_collector_hostname: 'gitfoo.com')
@ -12,17 +14,62 @@ RSpec.describe Gitlab::Tracking do
end end
describe '.options' do describe '.options' do
it 'returns useful client options' do shared_examples 'delegates to destination' do |klass|
expected_fields = { before do
namespace: 'gl', allow_next_instance_of(klass) do |instance|
hostname: 'gitfoo.com', allow(instance).to receive(:options).and_call_original
cookieDomain: '.gitfoo.com', end
appId: '_abc123_', end
formTracking: true,
linkClickTracking: true
}
expect(subject.options(nil)).to match(expected_fields) it "delegates to #{klass} destination" do
expect_next_instance_of(klass) do |instance|
expect(instance).to receive(:options)
end
subject.options(nil)
end
end
context 'when destination is Snowplow' do
it_behaves_like 'delegates to destination', Gitlab::Tracking::Destinations::Snowplow
it 'returns useful client options' do
expected_fields = {
namespace: 'gl',
hostname: 'gitfoo.com',
cookieDomain: '.gitfoo.com',
appId: '_abc123_',
formTracking: true,
linkClickTracking: true
}
expect(subject.options(nil)).to match(expected_fields)
end
end
context 'when destination is SnowplowMicro' do
before do
stub_env('SNOWPLOW_MICRO_ENABLE', '1')
allow(Rails.env).to receive(:development?).and_return(true)
end
it_behaves_like 'delegates to destination', Gitlab::Tracking::Destinations::SnowplowMicro
it 'returns useful client options' do
expected_fields = {
namespace: 'gl',
hostname: 'localhost:9090',
cookieDomain: '.gitlab.com',
appId: '_abc123_',
protocol: 'http',
port: 9090,
force_secure_tracker: false,
formTracking: true,
linkClickTracking: true
}
expect(subject.options(nil)).to match(expected_fields)
end
end end
it 'when feature flag is disabled' do it 'when feature flag is disabled' do
@ -71,7 +118,23 @@ RSpec.describe Gitlab::Tracking do
end end
end end
it_behaves_like 'delegates to destination', Gitlab::Tracking::Destinations::Snowplow context 'when destination is Snowplow' do
before do
stub_env('SNOWPLOW_MICRO_ENABLE', '0')
allow(Rails.env).to receive(:development?).and_return(true)
end
it_behaves_like 'delegates to destination', Gitlab::Tracking::Destinations::Snowplow
end
context 'when destination is SnowplowMicro' do
before do
stub_env('SNOWPLOW_MICRO_ENABLE', '1')
allow(Rails.env).to receive(:development?).and_return(true)
end
it_behaves_like 'delegates to destination', Gitlab::Tracking::Destinations::SnowplowMicro
end
it 'tracks errors' do it 'tracks errors' do
expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).with( expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).with(

View File

@ -2,17 +2,17 @@
RSpec.configure do |config| RSpec.configure do |config|
config.around(:each, :database_replica) do |example| config.around(:each, :database_replica) do |example|
old_proxies = [] old_proxies = {}
Gitlab::Database::LoadBalancing.base_models.each do |model| Gitlab::Database::LoadBalancing.base_models.each do |model|
old_proxies[model] = [model.load_balancer, model.connection, model.sticking]
config = Gitlab::Database::LoadBalancing::Configuration config = Gitlab::Database::LoadBalancing::Configuration
.new(model, [model.connection_db_config.configuration_hash[:host]]) .new(model, [model.connection_db_config.configuration_hash[:host]])
lb = Gitlab::Database::LoadBalancing::LoadBalancer.new(config)
old_proxies << [model, model.connection] model.load_balancer = Gitlab::Database::LoadBalancing::LoadBalancer.new(config)
model.sticking = Gitlab::Database::LoadBalancing::Sticking.new(model.load_balancer)
model.connection = model.connection = Gitlab::Database::LoadBalancing::ConnectionProxy.new(model.load_balancer)
Gitlab::Database::LoadBalancing::ConnectionProxy.new(lb)
end end
Gitlab::Database::LoadBalancing::Session.clear_session Gitlab::Database::LoadBalancing::Session.clear_session
@ -23,8 +23,8 @@ RSpec.configure do |config|
Gitlab::Database::LoadBalancing::Session.clear_session Gitlab::Database::LoadBalancing::Session.clear_session
redis_shared_state_cleanup! redis_shared_state_cleanup!
old_proxies.each do |(model, proxy)| old_proxies.each do |model, proxy|
model.connection = proxy model.load_balancer, model.connection, model.sticking = proxy
end end
end end
end end