octoshark 0.1.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|