Commit 7d4db67a authored by Matthias Kaeppler's avatar Matthias Kaeppler

Track nil `proxy` to Sentry upon field access

We have a late-init scenario where load balancing isn't available before
configure_proxy is called. Logging this condition to sentry makes these
failures easier to track and diagnose.
parent fe6c395e
...@@ -3,9 +3,6 @@ ...@@ -3,9 +3,6 @@
module Gitlab module Gitlab
module Database module Database
module LoadBalancing module LoadBalancing
# The connection proxy to use for load balancing (if enabled).
cattr_accessor :proxy
# The exceptions raised for connection errors. # The exceptions raised for connection errors.
CONNECTION_ERRORS = if defined?(PG) CONNECTION_ERRORS = if defined?(PG)
[ [
...@@ -22,6 +19,21 @@ module Gitlab ...@@ -22,6 +19,21 @@ module Gitlab
[].freeze [].freeze
end end
ProxyNotConfiguredError = Class.new(StandardError)
# The connection proxy to use for load balancing (if enabled).
def self.proxy
unless @proxy
Gitlab::ErrorTracking.track_exception(
ProxyNotConfiguredError.new(
"Attempting to access the database load balancing proxy, but it wasn't configured.\n" \
"Did you forget to call '#{self.name}.configure_proxy'?"
))
end
@proxy
end
# Returns a Hash containing the load balancing configuration. # Returns a Hash containing the load balancing configuration.
def self.configuration def self.configuration
ActiveRecord::Base.configurations[Rails.env]['load_balancing'] || {} ActiveRecord::Base.configurations[Rails.env]['load_balancing'] || {}
...@@ -89,8 +101,8 @@ module Gitlab ...@@ -89,8 +101,8 @@ module Gitlab
end end
# Configures proxying of requests. # Configures proxying of requests.
def self.configure_proxy def self.configure_proxy(proxy = ConnectionProxy.new(hosts))
self.proxy = ConnectionProxy.new(hosts) @proxy = proxy
# This hijacks the "connection" method to ensure both # This hijacks the "connection" method to ensure both
# `ActiveRecord::Base.connection` and all models use the same load # `ActiveRecord::Base.connection` and all models use the same load
......
...@@ -3,6 +3,37 @@ ...@@ -3,6 +3,37 @@
require 'spec_helper' require 'spec_helper'
describe Gitlab::Database::LoadBalancing do describe Gitlab::Database::LoadBalancing do
describe '.proxy' do
context 'when configured' do
before do
allow(ActiveRecord::Base.singleton_class).to receive(:prepend)
subject.configure_proxy
end
after do
subject.configure_proxy(nil)
end
it 'returns the connection proxy' do
expect(subject.proxy).to be_an_instance_of(subject::ConnectionProxy)
end
end
context 'when not configured' do
it 'returns nil' do
expect(subject.proxy).to be_nil
end
it 'tracks an error to sentry' do
expect(Gitlab::ErrorTracking).to receive(:track_exception).with(
an_instance_of(subject::ProxyNotConfiguredError)
)
subject.proxy
end
end
end
describe '.configuration' do describe '.configuration' do
it 'returns a Hash' do it 'returns a Hash' do
config = { 'hosts' => %w(foo) } config = { 'hosts' => %w(foo) }
...@@ -176,14 +207,16 @@ describe Gitlab::Database::LoadBalancing do ...@@ -176,14 +207,16 @@ describe Gitlab::Database::LoadBalancing do
describe '.configure_proxy' do describe '.configure_proxy' do
after do after do
described_class.proxy = nil described_class.configure_proxy(nil)
end end
it 'configures the connection proxy' do it 'configures the connection proxy' do
expect(ActiveRecord::Base.singleton_class).to receive(:prepend) allow(ActiveRecord::Base.singleton_class).to receive(:prepend)
.with(Gitlab::Database::LoadBalancing::ActiveRecordProxy)
described_class.configure_proxy described_class.configure_proxy
expect(ActiveRecord::Base.singleton_class).to have_received(:prepend)
.with(Gitlab::Database::LoadBalancing::ActiveRecordProxy)
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