octoshark 0.1.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/ci-legacy.yml +66 -0
- data/.github/workflows/ci.yml +64 -0
- data/.ruby-version +1 -1
- data/Appraisals +20 -10
- data/CHANGELOG.md +19 -0
- data/Gemfile +1 -0
- data/README.md +187 -72
- data/Rakefile +4 -4
- data/gemfiles/rails3.0.gemfile +9 -0
- data/gemfiles/rails3.1.gemfile +3 -1
- data/gemfiles/rails3.2.gemfile +3 -1
- data/gemfiles/{rails4.gemfile → rails4.0.gemfile} +3 -1
- data/gemfiles/rails4.1.gemfile +3 -1
- data/gemfiles/rails4.2.gemfile +3 -1
- data/gemfiles/rails5.0.gemfile +9 -0
- data/gemfiles/rails5.1.gemfile +9 -0
- data/gemfiles/rails5.2.gemfile +9 -0
- data/gemfiles/rails6.0.gemfile +9 -0
- data/gemfiles/rails6.1.gemfile +9 -0
- data/lib/octoshark.rb +4 -19
- data/lib/octoshark/active_record_extensions.rb +18 -34
- data/lib/octoshark/connection_manager.rb +8 -106
- data/lib/octoshark/connection_pools_manager.rb +97 -0
- data/lib/octoshark/current_connection.rb +37 -0
- data/lib/octoshark/version.rb +1 -1
- data/octoshark.gemspec +3 -4
- data/spec/octoshark/active_record_extensions_spec.rb +4 -4
- data/spec/octoshark/connection_manager_spec.rb +22 -219
- data/spec/octoshark/connection_pools_manager_spec.rb +180 -0
- data/spec/octoshark/current_connection_spec.rb +74 -0
- data/spec/support/{config.yml.travis → config.yml.github} +6 -6
- metadata +30 -33
- data/.travis.yml +0 -18
- data/spec/octoshark_spec.rb +0 -40
data/Rakefile
CHANGED
@@ -10,16 +10,16 @@ task :default => :spec
|
|
10
10
|
|
11
11
|
namespace :db do
|
12
12
|
task :establish_connection do
|
13
|
-
configs = YAML.load_file('spec/support/config.yml')
|
14
|
-
config = configs[
|
15
|
-
@databases = configs.map { |_, config| config[
|
13
|
+
configs = YAML.load_file('spec/support/config.yml')
|
14
|
+
config = configs['db1'].reject { |k, v| k == 'database' }
|
15
|
+
@databases = configs.map { |_, config| config['database'] }
|
16
16
|
ActiveRecord::Base.establish_connection(config)
|
17
17
|
end
|
18
18
|
|
19
19
|
task :create => :establish_connection do
|
20
20
|
@databases.each do |database|
|
21
21
|
begin
|
22
|
-
ActiveRecord::Base.connection.create_database(database)
|
22
|
+
ActiveRecord::Base.connection.create_database(database, charset: 'utf8')
|
23
23
|
puts "#{database} created."
|
24
24
|
rescue ActiveRecord::StatementInvalid => e
|
25
25
|
if e.message.match /database exists/
|
data/gemfiles/rails3.1.gemfile
CHANGED
data/gemfiles/rails3.2.gemfile
CHANGED
data/gemfiles/rails4.1.gemfile
CHANGED
data/gemfiles/rails4.2.gemfile
CHANGED
data/lib/octoshark.rb
CHANGED
@@ -3,23 +3,8 @@ require 'active_record'
|
|
3
3
|
require 'octoshark/active_record_extensions'
|
4
4
|
|
5
5
|
module Octoshark
|
6
|
-
autoload :
|
7
|
-
autoload :
|
8
|
-
|
9
|
-
|
10
|
-
# automatically reconnect on connection establish.
|
11
|
-
@@connection_managers = []
|
12
|
-
|
13
|
-
def self.connection_managers
|
14
|
-
@@connection_managers
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.reset_connection_managers!
|
18
|
-
connection_managers.map(&:reset!)
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.disconnect!
|
22
|
-
connection_managers.map(&:disconnect!)
|
23
|
-
@@connection_managers = []
|
24
|
-
end
|
6
|
+
autoload :CurrentConnection, 'octoshark/current_connection'
|
7
|
+
autoload :ConnectionManager, 'octoshark/connection_manager'
|
8
|
+
autoload :ConnectionPoolsManager, 'octoshark/connection_pools_manager'
|
9
|
+
autoload :Error, 'octoshark/error'
|
25
10
|
end
|
@@ -1,47 +1,31 @@
|
|
1
1
|
module Octoshark
|
2
|
-
module
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
class << self
|
7
|
-
alias_method_chain :establish_connection, :octoshark
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
module ClassMethods
|
12
|
-
# When a connection is established in an ancestor process that must have
|
13
|
-
# subsequently forked, ActiveRecord establishes a new connection because
|
14
|
-
# it can't reuse the existing one. When that happens, we need to reconnect
|
15
|
-
# Octoshark connection managers.
|
16
|
-
def establish_connection_with_octoshark(*args)
|
17
|
-
establish_connection_without_octoshark(*args)
|
18
|
-
Octoshark.reset_connection_managers!
|
19
|
-
end
|
2
|
+
module ConnectionHandler
|
3
|
+
def establish_connection(*args)
|
4
|
+
Octoshark::ConnectionPoolsManager.reset_connection_managers!
|
5
|
+
super(*args)
|
20
6
|
end
|
21
7
|
end
|
22
8
|
|
23
9
|
module ActiveRecordAbstractAdapter
|
24
|
-
extend ActiveSupport::Concern
|
25
|
-
|
26
10
|
attr_accessor :connection_name, :database_name
|
27
11
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
def log_with_octoshark(sql, name = "SQL", *other_args, &block)
|
33
|
-
if connection_name
|
34
|
-
if database_name
|
35
|
-
name = "[Octoshark: #{connection_name} #{database_name}] #{name}"
|
36
|
-
else
|
37
|
-
name = "[Octoshark: #{connection_name}] #{name}"
|
38
|
-
end
|
12
|
+
def log(sql, name = "SQL", *other_args, &block)
|
13
|
+
if connection_name || database_name
|
14
|
+
name = "[Octoshark: #{[connection_name, database_name].compact.join(' ')}] #{name}"
|
39
15
|
end
|
40
16
|
|
41
|
-
|
17
|
+
super(sql, name, *other_args, &block)
|
42
18
|
end
|
43
19
|
end
|
44
20
|
end
|
45
21
|
|
46
|
-
ActiveRecord::
|
47
|
-
|
22
|
+
if defined?(ActiveRecord::ConnectionAdapters::ConnectionHandler)
|
23
|
+
# Rails 3.2, 4.0, 4.1, 4.2, 5.0
|
24
|
+
ActiveRecord::ConnectionAdapters::ConnectionHandler.send(:prepend, Octoshark::ConnectionHandler)
|
25
|
+
else
|
26
|
+
# Rails 3.0 and 3.1 does not lazy load
|
27
|
+
require 'active_record/connection_adapters/abstract_adapter'
|
28
|
+
ActiveRecord::ConnectionAdapters::ConnectionHandler.send(:prepend, Octoshark::ConnectionHandler)
|
29
|
+
end
|
30
|
+
|
31
|
+
ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:prepend, Octoshark::ActiveRecordAbstractAdapter)
|
@@ -1,118 +1,20 @@
|
|
1
1
|
module Octoshark
|
2
2
|
class ConnectionManager
|
3
|
+
include CurrentConnection
|
3
4
|
|
4
|
-
|
5
|
+
def with_connection(config, connection_name: nil, &block)
|
6
|
+
connection_method = "#{config[:adapter]}_connection"
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
Octoshark.connection_managers << self
|
11
|
-
end
|
12
|
-
|
13
|
-
def reset!
|
14
|
-
disconnect!
|
15
|
-
setup_connection_pools
|
16
|
-
end
|
17
|
-
|
18
|
-
def current_connection
|
19
|
-
Thread.current[identifier] || raise(Octoshark::Error::NoCurrentConnection, "No current connection")
|
20
|
-
end
|
21
|
-
|
22
|
-
def current_connection?
|
23
|
-
!Thread.current[identifier].nil?
|
24
|
-
end
|
25
|
-
|
26
|
-
def current_or_default_connection
|
27
|
-
Thread.current[identifier] || ActiveRecord::Base.connection_pool.connection
|
28
|
-
end
|
29
|
-
|
30
|
-
def with_connection(name, &block)
|
31
|
-
connection_pool = find_connection_pool(name)
|
32
|
-
with_connection_pool(name, connection_pool, &block)
|
33
|
-
end
|
34
|
-
|
35
|
-
def with_new_connection(name, config, reusable: false, &block)
|
36
|
-
if reusable
|
37
|
-
connection_pool = @connection_pools[name] ||= create_connection_pool(config)
|
38
|
-
with_connection_pool(name, connection_pool, &block)
|
39
|
-
else
|
40
|
-
connection_pool = create_connection_pool(config)
|
41
|
-
with_connection_pool(name, connection_pool, &block).tap do
|
42
|
-
connection_pool.disconnect!
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def use_database(name, database_name, &block)
|
48
|
-
connection_pool = find_connection_pool(name)
|
49
|
-
with_connection_pool(name, connection_pool, database_name, &block)
|
50
|
-
end
|
51
|
-
|
52
|
-
def without_connection(&block)
|
53
|
-
change_connection_reference(nil) do
|
54
|
-
yield
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def find_connection_pool(name)
|
59
|
-
@connection_pools[name] || raise(Octoshark::Error::NoConnection, "No such database connection '#{name}'")
|
60
|
-
end
|
61
|
-
|
62
|
-
def disconnect!
|
63
|
-
@connection_pools.values.each do |connection_pool|
|
64
|
-
connection_pool.disconnect!
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def identifier
|
69
|
-
@identifier ||= "octoshark_#{object_id}"
|
70
|
-
end
|
71
|
-
|
72
|
-
private
|
73
|
-
def spec_class
|
74
|
-
if defined?(ActiveRecord::ConnectionAdapters::ConnectionSpecification)
|
75
|
-
spec_class = ActiveRecord::ConnectionAdapters::ConnectionSpecification
|
76
|
-
else
|
77
|
-
spec_class = ActiveRecord::Base::ConnectionSpecification
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def change_connection_reference(connection, &block)
|
82
|
-
previous_connection = Thread.current[identifier]
|
83
|
-
Thread.current[identifier] = connection
|
8
|
+
connection = ActiveRecord::Base.send(connection_method, config)
|
9
|
+
connection.connection_name = connection_name
|
10
|
+
connection.database_name = config[:database] if config[:database]
|
84
11
|
|
85
12
|
begin
|
86
|
-
yield
|
87
|
-
ensure
|
88
|
-
Thread.current[identifier] = previous_connection
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def setup_connection_pools
|
93
|
-
@connection_pools = HashWithIndifferentAccess.new
|
94
|
-
|
95
|
-
@configs.each_pair do |name, config|
|
96
|
-
@connection_pools[name] = create_connection_pool(config)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
def create_connection_pool(config)
|
101
|
-
spec = spec_class.new(config, "#{config[:adapter]}_connection")
|
102
|
-
ActiveRecord::ConnectionAdapters::ConnectionPool.new(spec)
|
103
|
-
end
|
104
|
-
|
105
|
-
def with_connection_pool(name, connection_pool, database_name = nil, &block)
|
106
|
-
connection_pool.with_connection do |connection|
|
107
|
-
connection.connection_name = name
|
108
|
-
if database_name
|
109
|
-
connection.database_name = database_name
|
110
|
-
connection.execute("use #{database_name}")
|
111
|
-
end
|
112
|
-
|
113
13
|
change_connection_reference(connection) do
|
114
14
|
yield(connection)
|
115
15
|
end
|
16
|
+
ensure
|
17
|
+
connection.disconnect!
|
116
18
|
end
|
117
19
|
end
|
118
20
|
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module Octoshark
|
2
|
+
class ConnectionPoolsManager
|
3
|
+
include CurrentConnection
|
4
|
+
|
5
|
+
# Octoshark needs to keep track of all persistent connection managers
|
6
|
+
# in order to automatically reconnect on connection establish.
|
7
|
+
@@connection_managers = []
|
8
|
+
|
9
|
+
def self.connection_managers
|
10
|
+
@@connection_managers
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.reset_connection_managers!
|
14
|
+
connection_managers.each(&:reset!)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.disconnect!
|
18
|
+
connection_managers.map(&:disconnect!)
|
19
|
+
@@connection_managers = []
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :connection_pools
|
23
|
+
|
24
|
+
def initialize(configs = {})
|
25
|
+
@configs = configs.with_indifferent_access
|
26
|
+
setup_connection_pools
|
27
|
+
|
28
|
+
self.class.connection_managers << self
|
29
|
+
end
|
30
|
+
|
31
|
+
def reset!
|
32
|
+
disconnect!
|
33
|
+
setup_connection_pools
|
34
|
+
end
|
35
|
+
|
36
|
+
def with_connection(name, database_name = nil, &block)
|
37
|
+
connection_pool = find_connection_pool(name)
|
38
|
+
|
39
|
+
connection_pool.with_connection do |connection|
|
40
|
+
connection.connection_name = name
|
41
|
+
|
42
|
+
if database_name
|
43
|
+
connection.database_name = database_name
|
44
|
+
connection.execute("use #{database_name}")
|
45
|
+
end
|
46
|
+
|
47
|
+
change_connection_reference(connection) do
|
48
|
+
yield(connection)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def find_connection_pool(name)
|
54
|
+
@connection_pools[name] || raise(Octoshark::Error::NoConnection, "No such database connection '#{name}'")
|
55
|
+
end
|
56
|
+
|
57
|
+
def disconnect!
|
58
|
+
@connection_pools.values.each do |connection_pool|
|
59
|
+
connection_pool.disconnect!
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def setup_connection_pools
|
66
|
+
@connection_pools = HashWithIndifferentAccess.new
|
67
|
+
|
68
|
+
@configs.each_pair do |name, config|
|
69
|
+
@connection_pools[name] = create_connection_pool(name, config)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def create_connection_pool(name, config)
|
74
|
+
spec =
|
75
|
+
if defined?(ActiveRecord::ConnectionAdapters::PoolConfig)
|
76
|
+
env_name = defined?(Rails) ? Rails.env : nil
|
77
|
+
db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new(env_name, name, config)
|
78
|
+
ActiveRecord::ConnectionAdapters::PoolConfig.new(owner_name = ActiveRecord::Base, db_config)
|
79
|
+
else
|
80
|
+
adapter_method = "#{config[:adapter]}_connection"
|
81
|
+
if defined?(ActiveRecord::ConnectionAdapters::ConnectionSpecification)
|
82
|
+
spec_class = ActiveRecord::ConnectionAdapters::ConnectionSpecification
|
83
|
+
|
84
|
+
if spec_class.instance_method(:initialize).arity == 3
|
85
|
+
spec_class.new(name, config, adapter_method)
|
86
|
+
else
|
87
|
+
spec_class.new(config, adapter_method)
|
88
|
+
end
|
89
|
+
else
|
90
|
+
ActiveRecord::Base::ConnectionSpecification.new(config, adapter_method)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
ActiveRecord::ConnectionAdapters::ConnectionPool.new(spec)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|