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.
@@ -0,0 +1,37 @@
1
+ module Octoshark
2
+ module CurrentConnection
3
+ def current_connection
4
+ Thread.current[identifier] || raise(Octoshark::Error::NoCurrentConnection, "No current connection")
5
+ end
6
+
7
+ def current_connection?
8
+ !Thread.current[identifier].nil?
9
+ end
10
+
11
+ def current_or_default_connection
12
+ Thread.current[identifier] || ActiveRecord::Base.connection_pool.connection
13
+ end
14
+
15
+ def without_connection(&block)
16
+ change_connection_reference(nil) do
17
+ yield
18
+ end
19
+ end
20
+
21
+ def identifier
22
+ @identifier ||= "octoshark_#{object_id}"
23
+ end
24
+
25
+ private
26
+ def change_connection_reference(connection, &block)
27
+ previous_connection = Thread.current[identifier]
28
+ Thread.current[identifier] = connection
29
+
30
+ begin
31
+ yield
32
+ ensure
33
+ Thread.current[identifier] = previous_connection
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,3 +1,3 @@
1
1
  module Octoshark
2
- VERSION = "0.1.2"
2
+ VERSION = "0.3.0"
3
3
  end
data/octoshark.gemspec CHANGED
@@ -20,10 +20,9 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_runtime_dependency "activerecord", ">= 3.0"
22
22
 
23
- spec.add_development_dependency "bundler", "~> 1.5"
24
23
  spec.add_development_dependency "rake"
25
- spec.add_development_dependency "rspec", "~> 3.0.0"
26
- spec.add_development_dependency "sqlite3", "~> 1.3.0"
27
- spec.add_development_dependency "mysql2", "~> 0.3.14"
24
+ spec.add_development_dependency "rspec", "~> 3.7.0"
25
+ spec.add_development_dependency "sqlite3", "~> 1.4.1"
26
+ spec.add_development_dependency "mysql2", "~> 0.5.2"
28
27
  spec.add_development_dependency "appraisal"
29
28
  end
@@ -8,7 +8,7 @@ describe "ActiveRecord Extensions" do
8
8
 
9
9
  ActiveRecord::Base.logger = logger
10
10
 
11
- manager = Octoshark::ConnectionManager.new(configs)
11
+ manager = Octoshark::ConnectionPoolsManager.new(configs)
12
12
  manager.with_connection(:db1) do |connection|
13
13
  connection.execute("SELECT 1")
14
14
  end
@@ -25,8 +25,8 @@ describe "ActiveRecord Extensions" do
25
25
 
26
26
  ActiveRecord::Base.logger = logger
27
27
 
28
- manager = Octoshark::ConnectionManager.new(mysql2_configs)
29
- manager.use_database(:db1, database_name) do |connection|
28
+ manager = Octoshark::ConnectionPoolsManager.new(mysql2_configs)
29
+ manager.with_connection(:db1, database_name) do |connection|
30
30
  connection.execute("SELECT 1")
31
31
  end
32
32
 
@@ -41,7 +41,7 @@ describe "ActiveRecord Extensions" do
41
41
 
42
42
  ActiveRecord::Base.logger = logger
43
43
 
44
- manager = Octoshark::ConnectionManager.new(configs)
44
+ manager = Octoshark::ConnectionPoolsManager.new(configs)
45
45
  manager.with_connection(:db1) do |connection|
46
46
  ActiveRecord::Base.connection.execute("SELECT 1")
47
47
  end
@@ -1,245 +1,48 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Octoshark::ConnectionManager do
4
- describe "#initialize" do
5
- it "initializes connection manager with default connection" do
4
+ describe "#with_connection", mysql2: true do
5
+ it "creates temporary connection to database server" do
6
6
  manager = Octoshark::ConnectionManager.new
7
+ connection_reference = nil
7
8
 
8
- expect(manager.connection_pools.length).to eq(0)
9
- expect(manager.connection_pools[:default]).to be_nil
10
- end
11
-
12
- it "initializes connection manager with custom connections" do
13
- manager = Octoshark::ConnectionManager.new(configs)
14
-
15
- expect(manager.connection_pools.length).to eq(2)
16
- expect(manager.connection_pools[:db1]).to be_an_instance_of(ActiveRecord::ConnectionAdapters::ConnectionPool)
17
- expect(manager.connection_pools[:db2]).to be_an_instance_of(ActiveRecord::ConnectionAdapters::ConnectionPool)
18
- end
19
-
20
- it "accepts configs with string keys" do
21
- configs = { 'db1' => { 'adapter' => "sqlite3", 'database' => "tmp/db1.sqlite" } }
22
- manager = Octoshark::ConnectionManager.new(configs)
23
-
24
- expect { manager.connection_pools[:db1].connection }.not_to raise_error
25
- end
26
- end
9
+ config = mysql2_configs[:db1]
27
10
 
28
- describe "#identifier" do
29
- it "has unique identifiers" do
30
- manager1 = Octoshark::ConnectionManager.new
31
- manager2 = Octoshark::ConnectionManager.new
32
- expect(manager1.identifier).to_not eq(manager2.identifier)
33
- end
34
- end
11
+ manager.with_connection(config.except(:database)) do |connection|
12
+ connection_reference = connection
35
13
 
36
- describe "#current_connection" do
37
- it "returns last used connection as current one" do
38
- manager = Octoshark::ConnectionManager.new(configs)
39
- manager.with_connection(:db1) do |connection|
40
- expect(manager.current_connection).to eq(connection)
14
+ connection.execute("SELECT 1")
15
+ expect(connection.database_name).to be_nil
41
16
  end
42
- end
43
17
 
44
- it "raises error when no current connection" do
45
- manager = Octoshark::ConnectionManager.new
46
-
47
- expect { manager.current_connection }.to raise_error(Octoshark::Error::NoCurrentConnection)
48
- end
49
- end
50
-
51
- describe "#current_connection?" do
52
- it "returns true if current one" do
53
- manager = Octoshark::ConnectionManager.new(configs)
54
- manager.with_connection(:db1) do
55
- expect(manager.current_connection?).to be_truthy
56
- end
18
+ expect(connection_reference.active?).to eq(false)
57
19
  end
58
20
 
59
- it "returns false if no current one" do
21
+ it "creates temporary connection to specific database", mysql2: true do
60
22
  manager = Octoshark::ConnectionManager.new
23
+ connection_reference = nil
61
24
 
62
- expect(manager.current_connection?).to be_falsey
63
- end
64
- end
25
+ config = mysql2_configs[:db1]
26
+ database_name = config.fetch('database')
65
27
 
66
- describe "#current_or_default_connection" do
67
- it "returns current connection" do
68
- manager = Octoshark::ConnectionManager.new(configs)
69
- manager.with_connection(:db1) do |db1|
70
- expect(manager.current_or_default_connection).to eq(db1)
71
- end
72
- end
73
-
74
- it "returns default connection when no current connection" do
75
- manager = Octoshark::ConnectionManager.new
28
+ manager.with_connection(config) do |connection|
29
+ connection_reference = connection
76
30
 
77
- expect(manager.current_or_default_connection).to eq(ActiveRecord::Base.connection_pool.connection)
78
- end
79
- end
80
-
81
- describe '#find_connection_pool' do
82
- it "can find connection pool by name" do
83
- manager = Octoshark::ConnectionManager.new(configs)
84
- expect(manager.find_connection_pool(:db1)).to be_an_instance_of(ActiveRecord::ConnectionAdapters::ConnectionPool)
85
- end
86
-
87
- it "raises Octoshark::Error::NoConnection when no pool with that name" do
88
- manager = Octoshark::ConnectionManager.new({})
89
- expect { manager.find_connection_pool(:invalid) }.to raise_error(Octoshark::Error::NoConnection)
90
- end
91
- end
92
-
93
- describe '#with_connection' do
94
- it "can use multiple connections" do
95
- manager = Octoshark::ConnectionManager.new(configs)
96
-
97
- manager.with_connection(:db1) do
98
- expect(db(manager.current_connection)).to eq("db1")
99
- end
100
-
101
- manager.with_connection(:db2) do
102
- expect(db(manager.current_connection)).to eq("db2")
31
+ connection.execute("SELECT 1")
32
+ expect(connection.database_name).to eq(database_name)
103
33
  end
104
- end
105
-
106
- it "can nest connection" do
107
- manager = Octoshark::ConnectionManager.new(configs)
108
-
109
- manager.with_connection(:db1) do
110
- expect(db(manager.current_connection)).to eq("db1")
111
-
112
- manager.with_connection(:db2) do
113
- expect(db(manager.current_connection)).to eq("db2")
114
- end
115
-
116
- expect(db(manager.current_connection)).to eq("db1")
117
- end
118
- end
119
-
120
- it "returns value from execution" do
121
- manager = Octoshark::ConnectionManager.new(configs)
122
- result = manager.with_connection(:db1) { |connection| connection.execute("SELECT 1") }
123
- expect(result).to eq([{"1"=>1, 0=>1}])
124
- end
125
-
126
- it "raises Octoshark::Error::NoConnection" do
127
- manager = Octoshark::ConnectionManager.new({})
128
-
129
- expect { manager.with_connection(:invalid) }.to raise_error(Octoshark::Error::NoConnection)
130
- end
131
- end
132
-
133
- describe "#with_new_connection" do
134
- it "creates temporary connection" do
135
- manager = Octoshark::ConnectionManager.new
136
- result = manager.with_new_connection(:db1, configs[:db1]) { |connection| connection.execute("SELECT 1") }
137
34
 
138
- expect(manager.connection_pools).to be_blank
35
+ expect(connection_reference.active?).to eq(false)
139
36
  end
140
37
 
141
38
  it "returns query results with temporary connection" do
142
39
  manager = Octoshark::ConnectionManager.new
143
- result = manager.with_new_connection(:db1, configs[:db1]) { |connection| connection.execute("SELECT 1") }
144
-
145
- expect(result).to eq([{"1"=>1, 0=>1}])
146
- end
147
-
148
- it "creates persistent connection" do
149
- connection_id = nil
150
- manager = Octoshark::ConnectionManager.new
151
- expect(manager.connection_pools.length).to eq(0)
152
-
153
- manager.with_new_connection(:db1, configs[:db1], reusable: true) do |connection|
154
- connection_id = connection.object_id
40
+ config = configs[:db1]
41
+ result = manager.with_connection(config) do |connection|
42
+ connection.execute("SELECT 1")
155
43
  end
156
- expect(manager.connection_pools.length).to eq(1)
157
-
158
- manager.with_new_connection(:db1, configs[:db1], reusable: true) do |connection|
159
- expect(connection.object_id).to eq(connection_id)
160
- end
161
- expect(manager.connection_pools.length).to eq(1)
162
- end
163
-
164
- it "returns query results with persistent connection" do
165
- manager = Octoshark::ConnectionManager.new
166
-
167
- result = manager.with_new_connection(:db1, configs[:db1], reusable: true) { |connection| connection.execute("SELECT 1") }
168
- expect(result).to eq([{"1"=>1, 0=>1}])
169
-
170
- result = manager.with_new_connection(:db1, configs[:db1], reusable: true) { |connection| connection.execute("SELECT 1") }
171
- expect(result).to eq([{"1"=>1, 0=>1}])
172
- end
173
- end
174
-
175
- describe "#use_database" do
176
- it "can nest connection", mysql2: true do
177
- manager = Octoshark::ConnectionManager.new(mysql2_configs)
178
-
179
- db1 = mysql2_configs[:db1]['database']
180
- db2 = mysql2_configs[:db2]['database']
181
-
182
- manager.use_database(:db1, db1) do
183
- expect(db(manager.current_connection)).to eq(db1)
184
-
185
- manager.use_database(:db2, db2) do
186
- expect(db(manager.current_connection)).to eq(db2)
187
- end
188
-
189
- expect(db(manager.current_connection)).to eq(db1)
190
- end
191
- end
192
-
193
- it "returns value from execution", mysql2: true do
194
- manager = Octoshark::ConnectionManager.new(mysql2_configs)
195
- db1 = mysql2_configs[:db1]['database']
196
- result = manager.use_database(:db1, db1) { |connection| connection.execute("SELECT 1") }.to_a
197
- expect(result).to eq([[1]])
198
- end
199
- end
200
-
201
- describe '#without_connection' do
202
- it "can reset current connection temporarily inside nested connection block" do
203
- manager = Octoshark::ConnectionManager.new(configs)
204
-
205
- manager.with_connection(:db1) do
206
- expect(db(manager.current_connection)).to eq("db1")
207
-
208
- manager.without_connection do
209
- expect { manager.current_connection }.to raise_error(Octoshark::Error::NoCurrentConnection)
210
- end
211
-
212
- expect(db(manager.current_connection)).to eq("db1")
213
- end
214
- end
215
- end
216
-
217
- describe "#disconnect!" do
218
- it "removes all connections from connection pools" do
219
- manager = Octoshark::ConnectionManager.new(configs)
220
-
221
- manager.with_connection(:db1) { |connection| connection.execute("SELECT 1") }
222
- expect(manager.find_connection_pool(:db1)).to be_connected
223
-
224
- manager.disconnect!
225
-
226
- expect(manager.find_connection_pool(:db1)).to_not be_connected
227
- end
228
- end
229
-
230
- describe ".reset!" do
231
- it "gets new connection pools ready to rock" do
232
- manager = Octoshark::ConnectionManager.new(configs)
233
-
234
- manager.with_connection(:db1) { |connection| connection.execute("SELECT 1") }
235
- expect(manager.connection_pools[:db1].connections.count).to eq(1)
236
-
237
- manager.reset!
238
-
239
- expect(manager.connection_pools[:db1].connections.count).to eq(0)
240
44
 
241
- manager.with_connection(:db1) { |connection| connection.execute("SELECT 1") }
242
- expect(manager.connection_pools[:db1].connections.count).to eq(1)
45
+ expect(result.first['1']).to eq(1)
243
46
  end
244
47
  end
245
48
  end
@@ -0,0 +1,180 @@
1
+ require 'spec_helper'
2
+
3
+ describe Octoshark::ConnectionPoolsManager do
4
+ describe "#initialize" do
5
+ it "initializes connection manager with default connection" do
6
+ manager = Octoshark::ConnectionPoolsManager.new
7
+
8
+ expect(manager.connection_pools.length).to eq(0)
9
+ expect(manager.connection_pools[:default]).to be_nil
10
+ end
11
+
12
+ it "initializes connection manager with custom connections" do
13
+ manager = Octoshark::ConnectionPoolsManager.new(configs)
14
+
15
+ expect(manager.connection_pools.length).to eq(2)
16
+ expect(manager.connection_pools[:db1]).to be_an_instance_of(ActiveRecord::ConnectionAdapters::ConnectionPool)
17
+ expect(manager.connection_pools[:db2]).to be_an_instance_of(ActiveRecord::ConnectionAdapters::ConnectionPool)
18
+ end
19
+
20
+ it "accepts configs with string keys" do
21
+ configs = { 'db1' => { 'adapter' => "sqlite3", 'database' => "tmp/db1.sqlite" } }
22
+ manager = Octoshark::ConnectionPoolsManager.new(configs)
23
+
24
+ expect { manager.connection_pools[:db1].connection }.not_to raise_error
25
+ end
26
+ end
27
+
28
+ describe '#find_connection_pool' do
29
+ it "can find connection pool by name" do
30
+ manager = Octoshark::ConnectionPoolsManager.new(configs)
31
+ expect(manager.find_connection_pool(:db1)).to be_an_instance_of(ActiveRecord::ConnectionAdapters::ConnectionPool)
32
+ end
33
+
34
+ it "raises Octoshark::Error::NoConnection when no pool with that name" do
35
+ manager = Octoshark::ConnectionPoolsManager.new({})
36
+ expect { manager.find_connection_pool(:invalid) }.to raise_error(Octoshark::Error::NoConnection)
37
+ end
38
+ end
39
+
40
+ describe '#with_connection' do
41
+ it "can use multiple connections" do
42
+ manager = Octoshark::ConnectionPoolsManager.new(configs)
43
+
44
+ manager.with_connection(:db1) do
45
+ expect(db(manager.current_connection)).to eq("db1")
46
+ end
47
+
48
+ manager.with_connection(:db2) do
49
+ expect(db(manager.current_connection)).to eq("db2")
50
+ end
51
+ end
52
+
53
+ it "can nest connection" do
54
+ manager = Octoshark::ConnectionPoolsManager.new(configs)
55
+
56
+ manager.with_connection(:db1) do
57
+ expect(db(manager.current_connection)).to eq("db1")
58
+
59
+ manager.with_connection(:db2) do
60
+ expect(db(manager.current_connection)).to eq("db2")
61
+ end
62
+
63
+ expect(db(manager.current_connection)).to eq("db1")
64
+ end
65
+ end
66
+
67
+ it "returns value from execution" do
68
+ manager = Octoshark::ConnectionPoolsManager.new(configs)
69
+ result = manager.with_connection(:db1) { |connection| connection.execute("SELECT 1") }
70
+ expect(result.first['1']).to eq(1)
71
+ end
72
+
73
+ it "raises Octoshark::Error::NoConnection" do
74
+ manager = Octoshark::ConnectionPoolsManager.new({})
75
+
76
+ expect { manager.with_connection(:invalid) }.to raise_error(Octoshark::Error::NoConnection)
77
+ end
78
+
79
+ context "using specific database", mysql2: true do
80
+ it "can use specific database" do
81
+ manager = Octoshark::ConnectionPoolsManager.new(mysql2_configs)
82
+
83
+ db1 = mysql2_configs[:db1]['database']
84
+ db2 = mysql2_configs[:db2]['database']
85
+
86
+ manager.with_connection(:db1, db1) do
87
+ expect(db(manager.current_connection)).to eq(db1)
88
+
89
+ manager.with_connection(:db2, db2) do
90
+ expect(db(manager.current_connection)).to eq(db2)
91
+ end
92
+
93
+ expect(db(manager.current_connection)).to eq(db1)
94
+ end
95
+ end
96
+
97
+ it "sets database name on the connection" do
98
+ manager = Octoshark::ConnectionPoolsManager.new(mysql2_configs)
99
+
100
+ db1 = mysql2_configs[:db1]['database']
101
+
102
+ manager.with_connection(:db1, db1) do |connection|
103
+ expect(connection.database_name).to eq('octoshark_db1')
104
+ end
105
+ end
106
+
107
+ it "returns value from execution" do
108
+ manager = Octoshark::ConnectionPoolsManager.new(mysql2_configs)
109
+ db1 = mysql2_configs[:db1]['database']
110
+ result = manager.with_connection(:db1, db1) { |connection| connection.execute("SELECT 1") }.to_a
111
+ expect(result).to eq([[1]])
112
+ end
113
+ end
114
+ end
115
+
116
+ describe "#disconnect!" do
117
+ it "removes all connections from connection pools" do
118
+ manager = Octoshark::ConnectionPoolsManager.new(configs)
119
+
120
+ manager.with_connection(:db1) { |connection| connection.execute("SELECT 1") }
121
+ expect(manager.find_connection_pool(:db1)).to be_connected
122
+
123
+ manager.disconnect!
124
+
125
+ expect(manager.find_connection_pool(:db1)).to_not be_connected
126
+ end
127
+ end
128
+
129
+ describe ".reset!" do
130
+ it "gets new connection pools ready to rock" do
131
+ manager = Octoshark::ConnectionPoolsManager.new(configs)
132
+
133
+ manager.with_connection(:db1) { |connection| connection.execute("SELECT 1") }
134
+ expect(manager.connection_pools[:db1].connections.count).to eq(1)
135
+
136
+ manager.reset!
137
+
138
+ expect(manager.connection_pools[:db1].connections.count).to eq(0)
139
+
140
+ manager.with_connection(:db1) { |connection| connection.execute("SELECT 1") }
141
+ expect(manager.connection_pools[:db1].connections.count).to eq(1)
142
+ end
143
+ end
144
+
145
+ describe ".reset_connection_managers!" do
146
+ it "resets connection managers" do
147
+ manager = Octoshark::ConnectionPoolsManager.new(configs)
148
+ old_pools = manager.connection_pools.map(&:object_id)
149
+
150
+ Octoshark::ConnectionPoolsManager.reset_connection_managers!
151
+
152
+ new_pools = manager.connection_pools.map(&:object_id)
153
+ expect(new_pools).to_not eq(old_pools)
154
+ end
155
+ end
156
+
157
+ describe ".disconnect!" do
158
+ it "disconnects connection managers" do
159
+ manager = Octoshark::ConnectionPoolsManager.new(configs)
160
+
161
+ Octoshark::ConnectionPoolsManager.disconnect!
162
+
163
+ expect(Octoshark::ConnectionPoolsManager.connection_managers).to be_blank
164
+ end
165
+
166
+ it "cleans old connections" do
167
+ manager = Octoshark::ConnectionPoolsManager.new(configs)
168
+
169
+ manager.with_connection(:db1) { |connection| connection.execute("SELECT 1") }
170
+ manager.with_connection(:db2) { |connection| connection.execute("SELECT 1") }
171
+ expect(manager.connection_pools[:db1].connections.count).to eq(1)
172
+ expect(manager.connection_pools[:db2].connections.count).to eq(1)
173
+
174
+ Octoshark::ConnectionPoolsManager.disconnect!
175
+
176
+ expect(manager.connection_pools[:db1].connections.count).to eq(0)
177
+ expect(manager.connection_pools[:db2].connections.count).to eq(0)
178
+ end
179
+ end
180
+ end