janus-ar 0.15.2 → 7.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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 = 7
7
+ MINOR = 2
8
+ PATCH = 0
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-ar.rb ADDED
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+
5
+ module Janus
6
+ autoload :Context, 'janus-ar/context'
7
+ autoload :Client, 'janus-ar/client'
8
+ autoload :QueryDirector, 'janus-ar/query_director'
9
+ autoload :VERSION, 'janus-ar/version'
10
+ autoload :DbConsoleConfig, 'janus-ar/db_console_config'
11
+
12
+ module Logging
13
+ autoload :Subscriber, 'janus-ar/logging/subscriber'
14
+ autoload :Logger, 'janus-ar/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
@@ -1,80 +1,82 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe ActiveRecord::ConnectionAdapters::JanusTrilogyAdapter 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' => Trilogy::TLS_VERSION_12,
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' => Trilogy::TLS_VERSION_12,
28
- }
29
- end
30
- let(:config) do
31
- {
32
- database:,
33
- adapter: 'janus_trilogy',
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).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).symbolize_keys
71
- end
72
- end
73
- end
74
-
75
- describe 'Integration tests' do
76
- let(:table_name) { 'table_name_trilogy' }
77
-
78
- it_behaves_like 'a mysql like server'
79
- end
80
- end
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe ActiveRecord::ConnectionAdapters::JanusTrilogyAdapter 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' => Trilogy::TLS_VERSION_12,
17
+ 'found_rows' => true,
18
+ }
19
+ end
20
+ let(:replica_config) do
21
+ {
22
+ 'username' => 'replica',
23
+ 'password' => 'replica_password',
24
+ 'host' => '127.0.0.1',
25
+ 'pool' => 500,
26
+ 'ssl' => true,
27
+ 'ssl_mode' => 'REQUIRED',
28
+ 'tls_min_version' => Trilogy::TLS_VERSION_12,
29
+ 'found_rows' => true,
30
+ }
31
+ end
32
+ let(:config) do
33
+ {
34
+ database:,
35
+ adapter: 'janus_trilogy',
36
+ janus: {
37
+ 'primary' => primary_config,
38
+ 'replica' => replica_config,
39
+ },
40
+ }
41
+ end
42
+
43
+ describe 'Configuration' do
44
+ it 'creates primary connection as expected' do
45
+ config = primary_config.dup.freeze
46
+ expect(subject.config).to eq config.merge('database' => database,
47
+ 'flags' => ::Janus::Client::FOUND_ROWS).symbolize_keys
48
+ end
49
+
50
+ it 'creates replica connection as expected' do
51
+ config = replica_config.dup.freeze
52
+ expect(
53
+ subject.replica_connection.instance_variable_get(:@config)
54
+ ).to eq config.merge('database' => database).symbolize_keys
55
+ end
56
+
57
+ context 'Rails sets empty database for server connection' do
58
+ let(:database) { nil }
59
+
60
+ it 'creates primary connection as expected' do
61
+ config = primary_config.dup.freeze
62
+ expect(subject.config).to eq config.merge(
63
+ 'database' => nil,
64
+ 'flags' => ::Janus::Client::FOUND_ROWS
65
+ ).symbolize_keys
66
+ end
67
+
68
+ it 'creates replica connection as expected' do
69
+ config = replica_config.dup.freeze
70
+ expect(
71
+ subject.replica_connection.instance_variable_get(:@config)
72
+ ).to eq config.merge('database' => nil).symbolize_keys
73
+ end
74
+ end
75
+ end
76
+
77
+ describe 'Integration tests' do
78
+ let(:table_name) { 'table_name_trilogy' }
79
+
80
+ it_behaves_like 'a mysql like server'
81
+ end
82
+ end
@@ -1,7 +1,7 @@
1
- # frozen_string_literal: true
2
-
3
- require 'janus/client'
4
-
5
- RSpec.describe Janus::Client do
6
- it { expect(described_class::FOUND_ROWS).to eq 2 }
7
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'janus-ar/client'
4
+
5
+ RSpec.describe Janus::Client do
6
+ it { expect(described_class::FOUND_ROWS).to eq 2 }
7
+ end
@@ -1,46 +1,46 @@
1
- # frozen_string_literal: true
2
-
3
- require 'janus/context'
4
-
5
- RSpec.describe Janus::Context do
6
- describe '#initialize' do
7
- it 'sets the primary flag and expiry' do
8
- context = described_class.new(primary: true, expiry: 60)
9
- expect(context.use_primary?).to be true
10
- expect(context.last_used_connection).to eq(:primary)
11
- end
12
- end
13
-
14
- describe '#stick_to_primary' do
15
- it 'sets the primary flag to true' do
16
- context = described_class.new
17
- context.stick_to_primary
18
- expect(context.use_primary?).to be true
19
- end
20
- end
21
-
22
- describe '#potential_write' do
23
- it 'calls stick_to_primary' do
24
- context = described_class.new
25
- expect(context).to receive(:stick_to_primary)
26
- context.potential_write
27
- end
28
- end
29
-
30
- describe '#release_all' do
31
- it 'resets the primary flag and expiry' do
32
- context = described_class.new(primary: true, expiry: 60)
33
- context.release_all
34
- expect(context.use_primary?).to be false
35
- expect(context.last_used_connection).to be_nil
36
- end
37
- end
38
-
39
- describe '#used_connection' do
40
- it 'sets the last used connection' do
41
- context = described_class.new
42
- context.used_connection(:secondary)
43
- expect(context.last_used_connection).to eq(:secondary)
44
- end
45
- end
46
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'janus-ar/context'
4
+
5
+ RSpec.describe Janus::Context do
6
+ describe '#initialize' do
7
+ it 'sets the primary flag and expiry' do
8
+ context = described_class.new(primary: true, expiry: 60)
9
+ expect(context.use_primary?).to be true
10
+ expect(context.last_used_connection).to eq(:primary)
11
+ end
12
+ end
13
+
14
+ describe '#stick_to_primary' do
15
+ it 'sets the primary flag to true' do
16
+ context = described_class.new
17
+ context.stick_to_primary
18
+ expect(context.use_primary?).to be true
19
+ end
20
+ end
21
+
22
+ describe '#potential_write' do
23
+ it 'calls stick_to_primary' do
24
+ context = described_class.new
25
+ expect(context).to receive(:stick_to_primary)
26
+ context.potential_write
27
+ end
28
+ end
29
+
30
+ describe '#release_all' do
31
+ it 'resets the primary flag and expiry' do
32
+ context = described_class.new(primary: true, expiry: 60)
33
+ context.release_all
34
+ expect(context.use_primary?).to be false
35
+ expect(context.last_used_connection).to be_nil
36
+ end
37
+ end
38
+
39
+ describe '#used_connection' do
40
+ it 'sets the last used connection' do
41
+ context = described_class.new
42
+ context.used_connection(:secondary)
43
+ expect(context.last_used_connection).to eq(:secondary)
44
+ end
45
+ end
46
+ end
@@ -1,31 +1,31 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Janus::Logging::Logger do
4
- describe '.log' do
5
- let(:logger) { double('logger') }
6
-
7
- before do
8
- described_class.logger = logger
9
- end
10
-
11
- it 'logs the message with the specified format' do
12
- expect(logger).to receive(:send).with(:info, '[Janus] Test message')
13
- described_class.log('Test message', :info)
14
- end
15
-
16
- it 'does not log the message if logger is not set' do
17
- described_class.logger = nil
18
- expect(logger).not_to receive(:send)
19
- described_class.log('Test message', :info)
20
- end
21
- end
22
-
23
- describe '.logger=' do
24
- let(:logger) { double('logger') }
25
-
26
- it 'sets the logger' do
27
- described_class.logger = logger
28
- expect(described_class.logger).to eq(logger)
29
- end
30
- end
31
- end
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Janus::Logging::Logger do
4
+ describe '.log' do
5
+ let(:logger) { double('logger') }
6
+
7
+ before do
8
+ described_class.logger = logger
9
+ end
10
+
11
+ it 'logs the message with the specified format' do
12
+ expect(logger).to receive(:send).with(:info, '[Janus] Test message')
13
+ described_class.log('Test message', :info)
14
+ end
15
+
16
+ it 'does not log the message if logger is not set' do
17
+ described_class.logger = nil
18
+ expect(logger).not_to receive(:send)
19
+ described_class.log('Test message', :info)
20
+ end
21
+ end
22
+
23
+ describe '.logger=' do
24
+ let(:logger) { double('logger') }
25
+
26
+ it 'sets the logger' do
27
+ described_class.logger = logger
28
+ expect(described_class.logger).to eq(logger)
29
+ end
30
+ end
31
+ end