janus-ar 0.15.2 → 0.15.3

Sign up to get free protection for your applications and to get access to all the features.
data/lib/janus/context.rb CHANGED
@@ -1,80 +1,80 @@
1
- # frozen_string_literal: true
2
-
3
- module Janus
4
- class Context
5
- THREAD_KEY = :janus_ar_context
6
-
7
- # Stores the staged data with an expiration time based on the current time,
8
- # and clears any expired entries. Returns true if any changes were made to
9
- # the current store
10
- def initialize(primary: false, expiry: nil)
11
- @primary = primary
12
- @expiry = expiry
13
- @last_used_connection = :primary
14
- end
15
-
16
- def stick_to_primary
17
- @primary = true
18
- end
19
-
20
- def potential_write
21
- stick_to_primary
22
- end
23
-
24
- def release_all
25
- @primary = false
26
- @expiry = nil
27
- @last_used_connection = nil
28
- end
29
-
30
- def use_primary?
31
- @primary
32
- end
33
-
34
- def used_connection(connection)
35
- @last_used_connection = connection
36
- end
37
-
38
- attr_reader :last_used_connection
39
-
40
- class << self
41
- def stick_to_primary
42
- current.stick_to_primary
43
- end
44
-
45
- def release_all
46
- current.release_all
47
- end
48
-
49
- def used_connection(connection)
50
- current.used_connection(connection)
51
- end
52
-
53
- def use_primary?
54
- current.use_primary?
55
- end
56
-
57
- def last_used_connection
58
- current.last_used_connection
59
- end
60
-
61
- protected
62
-
63
- def current
64
- fetch(THREAD_KEY) { new }
65
- end
66
-
67
- def fetch(key)
68
- get(key) || set(key, yield)
69
- end
70
-
71
- def get(key)
72
- Thread.current.thread_variable_get(key)
73
- end
74
-
75
- def set(key, value)
76
- Thread.current.thread_variable_set(key, value)
77
- end
78
- end
79
- end
80
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Janus
4
+ class Context
5
+ THREAD_KEY = :janus_ar_context
6
+
7
+ # Stores the staged data with an expiration time based on the current time,
8
+ # and clears any expired entries. Returns true if any changes were made to
9
+ # the current store
10
+ def initialize(primary: false, expiry: nil)
11
+ @primary = primary
12
+ @expiry = expiry
13
+ @last_used_connection = :primary
14
+ end
15
+
16
+ def stick_to_primary
17
+ @primary = true
18
+ end
19
+
20
+ def potential_write
21
+ stick_to_primary
22
+ end
23
+
24
+ def release_all
25
+ @primary = false
26
+ @expiry = nil
27
+ @last_used_connection = nil
28
+ end
29
+
30
+ def use_primary?
31
+ @primary
32
+ end
33
+
34
+ def used_connection(connection)
35
+ @last_used_connection = connection
36
+ end
37
+
38
+ attr_reader :last_used_connection
39
+
40
+ class << self
41
+ def stick_to_primary
42
+ current.stick_to_primary
43
+ end
44
+
45
+ def release_all
46
+ current.release_all
47
+ end
48
+
49
+ def used_connection(connection)
50
+ current.used_connection(connection)
51
+ end
52
+
53
+ def use_primary?
54
+ current.use_primary?
55
+ end
56
+
57
+ def last_used_connection
58
+ current.last_used_connection
59
+ end
60
+
61
+ protected
62
+
63
+ def current
64
+ fetch(THREAD_KEY) { new }
65
+ end
66
+
67
+ def fetch(key)
68
+ get(key) || set(key, yield)
69
+ end
70
+
71
+ def get(key)
72
+ Thread.current.thread_variable_get(key)
73
+ end
74
+
75
+ def set(key, value)
76
+ Thread.current.thread_variable_set(key, value)
77
+ end
78
+ end
79
+ end
80
+ end
@@ -1,17 +1,17 @@
1
- # frozen_string_literal: true
2
-
3
- module Janus
4
- class DbConsoleConfig
5
- def initialize(config)
6
- @_config = config.configuration_hash
7
- end
8
-
9
- def configuration_hash
10
- @_config[:janus]['replica'].symbolize_keys
11
- end
12
-
13
- def database
14
- @_config[:database]
15
- end
16
- end
17
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Janus
4
+ class DbConsoleConfig
5
+ def initialize(config)
6
+ @_config = config.configuration_hash
7
+ end
8
+
9
+ def configuration_hash
10
+ @_config[:janus]['replica'].symbolize_keys
11
+ end
12
+
13
+ def database
14
+ @_config[:database]
15
+ end
16
+ end
17
+ end
@@ -1,15 +1,15 @@
1
- # frozen_string_literal: true
2
-
3
- module Janus
4
- module Logging
5
- class Logger
6
- class << self
7
- def log(message, format = :info)
8
- logger&.send(format, "[Janus] #{message}")
9
- end
10
-
11
- attr_accessor :logger
12
- end
13
- end
14
- end
15
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Janus
4
+ module Logging
5
+ class Logger
6
+ class << self
7
+ def log(message, format = :info)
8
+ logger&.send(format, "[Janus] #{message}")
9
+ end
10
+
11
+ attr_accessor :logger
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,27 +1,27 @@
1
- # frozen_string_literal: true
2
-
3
- module Janus
4
- module Logging
5
- module Subscriber
6
- IGNORE_PAYLOAD_NAMES = %w(SCHEMA EXPLAIN).freeze
7
-
8
- def sql(event)
9
- name = event.payload[:name]
10
- unless IGNORE_PAYLOAD_NAMES.include?(name)
11
- name = [current_wrapper_name(event), name].compact.join(' ')
12
- event.payload[:name] = name
13
- end
14
- super(event)
15
- end
16
-
17
- protected
18
-
19
- def current_wrapper_name(_event)
20
- connection = Janus::Context.last_used_connection
21
- return nil unless connection
22
-
23
- "[#{connection}]"
24
- end
25
- end
26
- end
27
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Janus
4
+ module Logging
5
+ module Subscriber
6
+ IGNORE_PAYLOAD_NAMES = %w(SCHEMA EXPLAIN).freeze
7
+
8
+ def sql(event)
9
+ name = event.payload[:name]
10
+ unless IGNORE_PAYLOAD_NAMES.include?(name)
11
+ name = [current_wrapper_name(event), name].compact.join(' ')
12
+ event.payload[:name] = name
13
+ end
14
+ super(event)
15
+ end
16
+
17
+ protected
18
+
19
+ def current_wrapper_name(_event)
20
+ connection = Janus::Context.last_used_connection
21
+ return nil unless connection
22
+
23
+ "[#{connection}]"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,54 +1,54 @@
1
- # frozen_string_literal: true
2
- module Janus
3
- class QueryDirector
4
- ALL = :all
5
- REPLICA = :replica
6
- PRIMARY = :primary
7
-
8
- SQL_PRIMARY_MATCHERS = [
9
- /\A\s*select.+for update\Z/i, /select.+lock in share mode\Z/i,
10
- /\A\s*select.+(nextval|currval|lastval|get_lock|release_lock|pg_advisory_lock|pg_advisory_unlock)\(/i,
11
- /\A\s*show/i
12
- ].freeze
13
- SQL_REPLICA_MATCHERS = [/\A\s*(select|with.+\)\s*select)\s/i].freeze
14
- SQL_ALL_MATCHERS = [/\A\s*set\s/i].freeze
15
- SQL_SKIP_ALL_MATCHERS = [/\A\s*set\s+local\s/i].freeze
16
- WRITE_PREFIXES = %w(INSERT UPDATE DELETE LOCK CREATE GRANT DROP ALTER TRUNCATE BEGIN SAVEPOINT FLUSH).freeze
17
-
18
- def initialize(sql, open_transactions)
19
- @_sql = sql
20
- @_open_transactions = open_transactions
21
- end
22
-
23
- def where_to_send?
24
- if should_send_to_all?
25
- ALL
26
- elsif can_go_to_replica?
27
- REPLICA
28
- else
29
- PRIMARY
30
- end
31
- end
32
-
33
- private
34
-
35
- def should_send_to_all?
36
- SQL_ALL_MATCHERS.any? { |matcher| @_sql =~ matcher } && SQL_SKIP_ALL_MATCHERS.none? { |matcher| @_sql =~ matcher }
37
- end
38
-
39
- def can_go_to_replica?
40
- !should_go_to_primary?
41
- end
42
-
43
- def should_go_to_primary?
44
- Janus::Context.use_primary? ||
45
- write_query? ||
46
- @_open_transactions.positive? ||
47
- SQL_PRIMARY_MATCHERS.any? { |matcher| @_sql =~ matcher }
48
- end
49
-
50
- def write_query?
51
- WRITE_PREFIXES.include?(@_sql.upcase.split(' ').first)
52
- end
53
- end
54
- end
1
+ # frozen_string_literal: true
2
+ module Janus
3
+ class QueryDirector
4
+ ALL = :all
5
+ REPLICA = :replica
6
+ PRIMARY = :primary
7
+
8
+ SQL_PRIMARY_MATCHERS = [
9
+ /\A\s*select.+for update\Z/i, /select.+lock in share mode\Z/i,
10
+ /\A\s*select.+(nextval|currval|lastval|get_lock|release_lock|pg_advisory_lock|pg_advisory_unlock)\(/i,
11
+ /\A\s*show/i
12
+ ].freeze
13
+ SQL_REPLICA_MATCHERS = [/\A\s*(select|with.+\)\s*select)\s/i].freeze
14
+ SQL_ALL_MATCHERS = [/\A\s*set\s/i].freeze
15
+ SQL_SKIP_ALL_MATCHERS = [/\A\s*set\s+local\s/i].freeze
16
+ WRITE_PREFIXES = %w(INSERT UPDATE DELETE LOCK CREATE GRANT DROP ALTER TRUNCATE BEGIN SAVEPOINT FLUSH).freeze
17
+
18
+ def initialize(sql, open_transactions)
19
+ @_sql = sql
20
+ @_open_transactions = open_transactions
21
+ end
22
+
23
+ def where_to_send?
24
+ if should_send_to_all?
25
+ ALL
26
+ elsif can_go_to_replica?
27
+ REPLICA
28
+ else
29
+ PRIMARY
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def should_send_to_all?
36
+ SQL_ALL_MATCHERS.any? { |matcher| @_sql =~ matcher } && SQL_SKIP_ALL_MATCHERS.none? { |matcher| @_sql =~ matcher }
37
+ end
38
+
39
+ def can_go_to_replica?
40
+ !should_go_to_primary?
41
+ end
42
+
43
+ def should_go_to_primary?
44
+ Janus::Context.use_primary? ||
45
+ write_query? ||
46
+ @_open_transactions.positive? ||
47
+ SQL_PRIMARY_MATCHERS.any? { |matcher| @_sql =~ matcher }
48
+ end
49
+
50
+ def write_query?
51
+ WRITE_PREFIXES.include?(@_sql.upcase.split(' ').first)
52
+ end
53
+ end
54
+ end
data/lib/janus/version.rb CHANGED
@@ -1,17 +1,17 @@
1
- # frozen_string_literal: true
2
-
3
- module Janus
4
- unless defined?(::Janus::VERSION)
5
- module VERSION
6
- MAJOR = 0
7
- MINOR = 15
8
- PATCH = 2
9
- PRE = nil
10
-
11
- def self.to_s
12
- [MAJOR, MINOR, PATCH, PRE].compact.join('.')
13
- end
14
- end
15
- end
16
- ::Janus::VERSION
17
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Janus
4
+ unless defined?(::Janus::VERSION)
5
+ module VERSION
6
+ MAJOR = 0
7
+ MINOR = 15
8
+ PATCH = 3
9
+ PRE = nil
10
+
11
+ def self.to_s
12
+ [MAJOR, MINOR, PATCH, PRE].compact.join('.')
13
+ end
14
+ end
15
+ end
16
+ ::Janus::VERSION
17
+ end
data/lib/janus.rb CHANGED
@@ -1,22 +1,22 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_support'
4
-
5
- module Janus
6
- autoload :Context, 'janus/context'
7
- autoload :Client, 'janus/client'
8
- autoload :QueryDirector, 'janus/query_director'
9
- autoload :VERSION, 'janus/version'
10
- autoload :DbConsoleConfig, 'janus/db_console_config'
11
-
12
- module Logging
13
- autoload :Subscriber, 'janus/logging/subscriber'
14
- autoload :Logger, 'janus/logging/logger'
15
- end
16
- end
17
-
18
- ActiveSupport.on_load(:active_record) do
19
- ActiveRecord::LogSubscriber.log_subscribers.each do |subscriber|
20
- subscriber.extend Janus::Logging::Subscriber
21
- end
22
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+
5
+ module Janus
6
+ autoload :Context, 'janus/context'
7
+ autoload :Client, 'janus/client'
8
+ autoload :QueryDirector, 'janus/query_director'
9
+ autoload :VERSION, 'janus/version'
10
+ autoload :DbConsoleConfig, 'janus/db_console_config'
11
+
12
+ module Logging
13
+ autoload :Subscriber, 'janus/logging/subscriber'
14
+ autoload :Logger, 'janus/logging/logger'
15
+ end
16
+ end
17
+
18
+ ActiveSupport.on_load(:active_record) do
19
+ ActiveRecord::LogSubscriber.log_subscribers.each do |subscriber|
20
+ subscriber.extend Janus::Logging::Subscriber
21
+ end
22
+ end
@@ -1,76 +1,82 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe ActiveRecord::ConnectionAdapters::JanusMysql2Adapter do
4
- subject { described_class.new(config) }
5
-
6
- it { expect(described_class::FOUND_ROWS).to eq 'FOUND_ROWS' }
7
-
8
- let(:database) { 'test' }
9
- let(:primary_config) do
10
- {
11
- 'username' => 'primary',
12
- 'password' => 'primary_password',
13
- 'host' => '127.0.0.1',
14
- }
15
- end
16
- let(:replica_config) do
17
- {
18
- 'username' => 'replica',
19
- 'password' => 'replica_password',
20
- 'host' => '127.0.0.1',
21
- 'pool' => 500,
22
- }
23
- end
24
- let(:config) do
25
- {
26
- database:,
27
- adapter: 'janus_mysql2',
28
- janus: {
29
- 'primary' => primary_config,
30
- 'replica' => replica_config,
31
- },
32
- }
33
- end
34
-
35
- describe 'Configuration' do
36
- it 'creates primary connection as expected' do
37
- config = primary_config.dup.freeze
38
- expect(subject.config).to eq config.merge('database' => database,
39
- 'flags' => ::Janus::Client::FOUND_ROWS).symbolize_keys
40
- end
41
-
42
- it 'creates replica connection as expected' do
43
- config = replica_config.dup.freeze
44
- expect(
45
- subject.replica_connection.instance_variable_get(:@config)
46
- ).to eq config.merge('database' => database, 'flags' => ::Janus::Client::FOUND_ROWS).symbolize_keys
47
- end
48
-
49
- context 'Rails sets empty database for server connection' do
50
- let(:database) { nil }
51
-
52
- it 'creates primary connection as expected' do
53
- config = primary_config.dup.freeze
54
- expect(subject.config).to eq config.merge(
55
- 'database' => nil,
56
- 'flags' => ::Janus::Client::FOUND_ROWS
57
- ).symbolize_keys
58
- end
59
-
60
- it 'creates replica connection as expected' do
61
- config = replica_config.dup.freeze
62
- expect(
63
- subject.replica_connection.instance_variable_get(:@config)
64
- ).to eq config.merge('database' => nil, 'flags' => ::Janus::Client::FOUND_ROWS).symbolize_keys
65
- end
66
- end
67
- end
68
-
69
- describe 'Integration tests' do
70
- describe 'Integration tests' do
71
- let(:table_name) { 'table_name_mysql2' }
72
-
73
- it_behaves_like 'a mysql like server'
74
- end
75
- end
76
- end
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe ActiveRecord::ConnectionAdapters::JanusMysql2Adapter do
4
+ subject { described_class.new(config) }
5
+
6
+ it { expect(described_class::FOUND_ROWS).to eq 'FOUND_ROWS' }
7
+
8
+ let(:database) { 'test' }
9
+ let(:primary_config) do
10
+ {
11
+ 'username' => 'primary',
12
+ 'password' => 'primary_password',
13
+ 'host' => '127.0.0.1',
14
+ 'ssl' => true,
15
+ 'ssl_mode' => 'REQUIRED',
16
+ 'tls_min_version' => 3,
17
+ }
18
+ end
19
+ let(:replica_config) do
20
+ {
21
+ 'username' => 'replica',
22
+ 'password' => 'replica_password',
23
+ 'host' => '127.0.0.1',
24
+ 'pool' => 500,
25
+ 'ssl' => true,
26
+ 'ssl_mode' => 'REQUIRED',
27
+ 'tls_min_version' => 3,
28
+ }
29
+ end
30
+ let(:config) do
31
+ {
32
+ database:,
33
+ adapter: 'janus_mysql2',
34
+ janus: {
35
+ 'primary' => primary_config,
36
+ 'replica' => replica_config,
37
+ },
38
+ }
39
+ end
40
+
41
+ describe 'Configuration' do
42
+ it 'creates primary connection as expected' do
43
+ config = primary_config.dup.freeze
44
+ expect(subject.config).to eq config.merge('database' => database,
45
+ 'flags' => ::Janus::Client::FOUND_ROWS).symbolize_keys
46
+ end
47
+
48
+ it 'creates replica connection as expected' do
49
+ config = replica_config.dup.freeze
50
+ expect(
51
+ subject.replica_connection.instance_variable_get(:@config)
52
+ ).to eq config.merge('database' => database, 'flags' => ::Janus::Client::FOUND_ROWS).symbolize_keys
53
+ end
54
+
55
+ context 'Rails sets empty database for server connection' do
56
+ let(:database) { nil }
57
+
58
+ it 'creates primary connection as expected' do
59
+ config = primary_config.dup.freeze
60
+ expect(subject.config).to eq config.merge(
61
+ 'database' => nil,
62
+ 'flags' => ::Janus::Client::FOUND_ROWS
63
+ ).symbolize_keys
64
+ end
65
+
66
+ it 'creates replica connection as expected' do
67
+ config = replica_config.dup.freeze
68
+ expect(
69
+ subject.replica_connection.instance_variable_get(:@config)
70
+ ).to eq config.merge('database' => nil, 'flags' => ::Janus::Client::FOUND_ROWS).symbolize_keys
71
+ end
72
+ end
73
+ end
74
+
75
+ describe 'Integration tests' do
76
+ describe 'Integration tests' do
77
+ let(:table_name) { 'table_name_mysql2' }
78
+
79
+ it_behaves_like 'a mysql like server'
80
+ end
81
+ end
82
+ end