activerecord-bogacs 0.7.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5010de8016e3c5896dc032a0fa6afc6ab5cbb1808f60e7c6f42b22b280910aeb
4
- data.tar.gz: 3290de6d8265973c7efa237e18de7f96253580363b743785b069f34c5c92504a
3
+ metadata.gz: 8272c1dff28e707a092e34ec3e95a0bcf76f31c7b38074da474db9e5cf520edd
4
+ data.tar.gz: fe9a92843c1b94098e9de4e85d830f96357aa8b49a0e769001eb14d37a71d334
5
5
  SHA512:
6
- metadata.gz: 559b6831696d5e7ca408c735bc1f61bcb5c3fcfad19b0806aff943a47c623ac322462e79c3cefc1aca745df5cdda19986651c405e2024eebb8fa3c4cf02d7296
7
- data.tar.gz: 588ccb8e705390652de5162a26cee060ce8fe51887693069602a55cfecfb19175b23268a821a7c956d7494d6be542f486c6bda89a4814932e8ee4249965a97de
6
+ metadata.gz: a9ccd085265c8f744dd7d7ef95dd38918ef2b37c029d1ad19a09322d727fa7a080f895ab14bab005cd54887402090798750a3ad9c1f6f7d0b8456a205ae7cd08
7
+ data.tar.gz: 40031eed7a1628094fc21d105006e32e06ab48b0890fa0abeb8379c2d513527a01c520e124438bb7dd380448e66cb8b3a2947beaf1cd15f1f2d074645b0b97d8
@@ -248,7 +248,7 @@ module ActiveRecord
248
248
  #
249
249
  # @return [ActiveRecord::ConnectionAdapters::AbstractAdapter]
250
250
  def connection
251
- connection_id = current_connection_id(current_thread)
251
+ connection_id = connection_cache_key(current_thread)
252
252
  conn = @thread_cached_conns.fetch(connection_id, nil)
253
253
  conn = ( @thread_cached_conns[connection_id] ||= checkout ) unless conn
254
254
  conn
@@ -258,7 +258,7 @@ module ActiveRecord
258
258
  #
259
259
  # @return [true, false]
260
260
  def active_connection?
261
- connection_id = current_connection_id(current_thread)
261
+ connection_id = connection_cache_key(current_thread)
262
262
  @thread_cached_conns.fetch(connection_id, nil)
263
263
  end
264
264
 
@@ -266,7 +266,7 @@ module ActiveRecord
266
266
  # #release_connection releases the connection-thread association
267
267
  # and returns the connection to the pool.
268
268
  def release_connection(owner_thread = Thread.current)
269
- conn = @thread_cached_conns.delete(current_connection_id(owner_thread))
269
+ conn = @thread_cached_conns.delete(connection_cache_key(owner_thread))
270
270
  checkin conn if conn
271
271
  end
272
272
 
@@ -276,7 +276,7 @@ module ActiveRecord
276
276
  #
277
277
  # @yield [ActiveRecord::ConnectionAdapters::AbstractAdapter]
278
278
  def with_connection
279
- connection_id = current_connection_id
279
+ connection_id = connection_cache_key
280
280
  unless conn = @thread_cached_conns[connection_id]
281
281
  conn = connection
282
282
  fresh_connection = true
@@ -333,7 +333,7 @@ module ActiveRecord
333
333
  # See AbstractAdapter#discard!
334
334
  def discard! # :nodoc:
335
335
  synchronize do
336
- return if @connections.nil? # already discarded
336
+ return if discarded?
337
337
  @connected.make_false
338
338
 
339
339
  @connections.each do |conn|
@@ -342,6 +342,11 @@ module ActiveRecord
342
342
  @connections = @available = @thread_cached_conns = nil
343
343
  end
344
344
  end
345
+
346
+ def discarded? # :nodoc:
347
+ @connections.nil?
348
+ end
349
+
345
350
  def clear_reloadable_connections!
346
351
  synchronize do
347
352
  @thread_cached_conns.clear
@@ -566,7 +571,7 @@ module ActiveRecord
566
571
  #--
567
572
  # if owner_thread param is omitted, this must be called in synchronize block
568
573
  def remove_connection_from_thread_cache(conn, owner_thread = conn.owner)
569
- @thread_cached_conns.delete_pair(current_connection_id(owner_thread), conn)
574
+ @thread_cached_conns.delete_pair(connection_cache_key(owner_thread), conn)
570
575
  end
571
576
  alias_method :release, :remove_connection_from_thread_cache
572
577
 
@@ -37,19 +37,24 @@ module ActiveRecord
37
37
  # @private
38
38
  def checkout_timeout; end
39
39
 
40
+ # @override
41
+ # def connection_cache_key(owner_thread = Thread.current)
42
+ # owner_thread
43
+ # end
44
+
40
45
  # Retrieve the connection associated with the current thread, or call
41
46
  # #checkout to obtain one if necessary.
42
47
  #
43
48
  # #connection can be called any number of times; the connection is
44
49
  # held in a hash keyed by the thread id.
45
50
  def connection
46
- connection_id = current_connection_id(current_thread)
51
+ connection_id = connection_cache_key(current_thread)
47
52
  @thread_cached_conns[connection_id] ||= checkout
48
53
  end
49
54
 
50
55
  # Is there an open connection that is being used for the current thread?
51
56
  def active_connection?
52
- connection_id = current_connection_id(current_thread)
57
+ connection_id = connection_cache_key(current_thread)
53
58
  @thread_cached_conns[connection_id]
54
59
  end
55
60
 
@@ -57,7 +62,7 @@ module ActiveRecord
57
62
  # #release_connection releases the connection-thread association
58
63
  # and returns the connection to the pool.
59
64
  def release_connection(owner_thread = Thread.current)
60
- conn = @thread_cached_conns.delete(current_connection_id(owner_thread))
65
+ conn = @thread_cached_conns.delete(connection_cache_key(owner_thread))
61
66
  checkin conn if conn
62
67
  end
63
68
 
@@ -65,7 +70,7 @@ module ActiveRecord
65
70
  # exists checkout a connection, yield it to the block, and checkin the
66
71
  # connection when finished.
67
72
  def with_connection
68
- connection_id = current_connection_id
73
+ connection_id = connection_cache_key
69
74
  unless conn = @thread_cached_conns[connection_id]
70
75
  conn = connection
71
76
  fresh_connection = true
@@ -100,7 +105,7 @@ module ActiveRecord
100
105
 
101
106
  def discard! # :nodoc:
102
107
  synchronize do
103
- return if @thread_cached_conns.nil? # already discarded
108
+ return if discarded?
104
109
  @connected.make_false
105
110
 
106
111
  connections.each do |conn|
@@ -110,6 +115,10 @@ module ActiveRecord
110
115
  end
111
116
  end
112
117
 
118
+ def discarded? # :nodoc:
119
+ @thread_cached_conns.nil?
120
+ end
121
+
113
122
  # Clears the cache which maps classes.
114
123
  def clear_reloadable_connections!
115
124
  synchronize do
@@ -142,7 +151,7 @@ module ActiveRecord
142
151
  # are no longer alive.
143
152
  # @private AR 3.2 compatibility
144
153
  def clear_stale_cached_connections!
145
- keys = Thread.list.find_all { |t| t.alive? }.map { |t| current_connection_id(t) }
154
+ keys = Thread.list.find_all { |t| t.alive? }.map { |t| connection_cache_key(t) }
146
155
  keys = @thread_cached_conns.keys - keys
147
156
  keys.each do |key|
148
157
  if conn = @thread_cached_conns[key]
@@ -220,10 +229,10 @@ module ActiveRecord
220
229
  end
221
230
 
222
231
  def release(conn, owner = conn.owner)
223
- thread_id = current_connection_id(owner) unless owner.nil?
232
+ thread_id = connection_cache_key(owner) unless owner.nil?
224
233
 
225
234
  thread_id ||=
226
- if @thread_cached_conns[conn_id = current_connection_id].equal?(conn)
235
+ if @thread_cached_conns[conn_id = connection_cache_key].equal?(conn)
227
236
  conn_id
228
237
  else
229
238
  connections = @thread_cached_conns
@@ -24,11 +24,11 @@ module ActiveRecord
24
24
  conn
25
25
  end
26
26
 
27
- # @private
28
- def current_connection_id(owner_thread = Thread.current)
27
+ # @override (previously named current_connection_id)
28
+ # @private connection_cache_key for AR (5.2) compatibility
29
+ def connection_cache_key(owner_thread = Thread.current)
29
30
  owner_thread.object_id
30
31
  end
31
- alias_method :connection_cache_key, :current_connection_id # for AR (5.2) compatibility
32
32
 
33
33
  # @note Method not part of the pre 4.0 API (does no exist).
34
34
  def remove(conn)
@@ -14,10 +14,9 @@ require 'active_record/bogacs/pool_support'
14
14
  #
15
15
  module ActiveRecord
16
16
  module Bogacs
17
- class ShareablePool < ConnectionAdapters::ConnectionPool # NOTE: maybe do not override?!
18
- include PoolSupport
17
+ class ShareablePool < DefaultPool
19
18
 
20
- include ThreadSafe::Synchronized
19
+ include ::Concurrent::ThreadSafe::Util::CheapLockable
21
20
 
22
21
  AtomicReference = ::Concurrent::AtomicReference
23
22
 
@@ -28,38 +27,35 @@ module ActiveRecord
28
27
 
29
28
  # @override
30
29
  def initialize(spec)
31
- super(spec) # ConnectionPool#initialize
30
+ super(spec)
32
31
  shared_size = spec.config[:shared_pool]
33
32
  shared_size = shared_size ? shared_size.to_f : DEFAULT_SHARED_POOL
34
33
  # size 0.0 - 1.0 assumes percentage of the pool size
35
34
  shared_size = ( @size * shared_size ).round if shared_size <= 1.0
36
35
  @shared_size = shared_size.to_i
37
- @shared_connections = ThreadSafe::Map.new # :initial_capacity => @shared_size, :concurrency_level => 20
36
+ @shared_connections = ThreadSafe::Map.new # initial_capacity: @shared_size
38
37
  end
39
38
 
40
39
  # @override
41
40
  def connection
42
- Thread.current[shared_connection_key] || begin # super - simplified :
43
- super # @reserved_connections.compute_if_absent(current_connection_id) { checkout }
44
- end
41
+ current_thread[shared_connection_key] || super
45
42
  end
46
43
 
47
44
  # @override
48
45
  def active_connection?
49
- if shared_conn = Thread.current[shared_connection_key]
50
- return shared_conn.in_use?
51
- end
52
- super_active_connection? current_connection_id
46
+ return true if current_thread[shared_connection_key]
47
+ has_active_connection? # super
53
48
  end
54
49
 
55
50
  # @override called from ConnectionManagement middle-ware (when finished)
56
- def release_connection(with_id = current_connection_id)
57
- if reserved_conn = @reserved_connections[with_id]
51
+ def release_connection(owner_thread = Thread.current)
52
+ conn_id = connection_cache_key(owner_thread)
53
+ if reserved_conn = @thread_cached_conns.delete(conn_id)
58
54
  if shared_count = @shared_connections[reserved_conn]
59
- synchronize do # lock due #get_shared_connection ... not needed ?!
55
+ cheap_synchronize do # lock due #get_shared_connection ... not needed ?!
60
56
  # NOTE: the other option is to not care about shared here at all ...
61
57
  if shared_count.get == 0 # releasing a shared connection
62
- release_shared_connection(reserved_conn)
58
+ release_shared_connection(reserved_conn, owner_thread)
63
59
  #else return false
64
60
  end
65
61
  end
@@ -101,14 +97,14 @@ module ActiveRecord
101
97
 
102
98
  # Custom API :
103
99
 
104
- def release_shared_connection(connection)
100
+ def release_shared_connection(connection, owner_thread = Thread.current)
105
101
  shared_conn_key = shared_connection_key
106
- if connection == Thread.current[shared_conn_key]
107
- Thread.current[shared_conn_key] = nil
102
+ if connection == owner_thread[shared_conn_key]
103
+ owner_thread[shared_conn_key] = nil
108
104
  end
109
105
 
110
106
  @shared_connections.delete(connection)
111
- checkin connection
107
+ shared_checkin connection # synchronized
112
108
  end
113
109
 
114
110
  def with_shared_connection
@@ -121,9 +117,8 @@ module ActiveRecord
121
117
 
122
118
  start = Time.now if DEBUG
123
119
  begin
124
- connection_id = current_connection_id
125
120
  # if there's a 'regular' connection on the thread use it as super
126
- if super_active_connection?(connection_id) # for current thread
121
+ if has_active_connection? # for current thread
127
122
  connection = self.connection # do not mark as shared
128
123
  DEBUG && debug("with_shared_conn 10 got active = #{connection.to_s}")
129
124
  # otherwise if we have a shared connection - use that one :
@@ -131,6 +126,7 @@ module ActiveRecord
131
126
  emulated_checkout(connection); shared = true
132
127
  DEBUG && debug("with_shared_conn 20 got shared = #{connection.to_s}")
133
128
  else
129
+ shared = true
134
130
  synchronize do
135
131
  # check shared again as/if threads end up sync-ing up here :
136
132
  if connection = get_shared_connection
@@ -144,7 +140,6 @@ module ActiveRecord
144
140
  DEBUG && debug("with_shared_conn 30 acq shared = #{connection.to_s}")
145
141
  end
146
142
  end
147
- shared = true
148
143
  end
149
144
 
150
145
  Thread.current[shared_conn_key] = connection if shared
@@ -152,23 +147,17 @@ module ActiveRecord
152
147
  DEBUG && debug("with_shared_conn obtaining a connection took #{(Time.now - start) * 1000}ms")
153
148
  yield connection
154
149
  ensure
155
- Thread.current[shared_conn_key] = nil # if shared
156
- rem_shared_connection(connection) if shared
150
+ Thread.current[shared_conn_key] = nil if shared
151
+ rem_shared_connection(connection) if shared && connection
157
152
  end
158
153
  end
159
154
 
160
155
  private
161
156
 
162
- def super_active_connection?(connection_id = current_connection_id)
163
- (@reserved_connections.get(connection_id) || ( return false )).in_use?
157
+ def has_active_connection? # super.active_connection?
158
+ @thread_cached_conns.fetch(connection_cache_key(current_thread), nil)
164
159
  end
165
160
 
166
- def super_active_connection?(connection_id = current_connection_id)
167
- synchronize do
168
- (@reserved_connections[connection_id] || ( return false )).in_use?
169
- end
170
- end if ActiveRecord::VERSION::MAJOR < 4
171
-
172
161
  def acquire_connection_no_wait?
173
162
  synchronize do
174
163
  @connections.size < @size || @available.send(:can_remove_no_wait?)
@@ -214,7 +203,7 @@ module ActiveRecord
214
203
  end
215
204
 
216
205
  # we did as much as could without a lock - now sync due possible release
217
- synchronize do # TODO although this likely might be avoided ...
206
+ cheap_synchronize do # TODO although this likely might be avoided ...
218
207
  # should try again if possibly the same connection got released :
219
208
  unless least_count = @shared_connections[least_shared]
220
209
  DEBUG && debug(" get_shared_conn retry (connection got released)")
@@ -234,7 +223,7 @@ module ActiveRecord
234
223
  def rem_shared_connection(connection)
235
224
  if shared_count = @shared_connections[connection]
236
225
  # shared_count.update { |v| v - 1 } # NOTE: likely fine without lock!
237
- synchronize do # give it back to the pool
226
+ cheap_synchronize do # give it back to the pool
238
227
  shared_count.update { |v| v - 1 } # might give it back if :
239
228
  release_shared_connection(connection) if shared_count.get == 0
240
229
  end
@@ -243,12 +232,22 @@ module ActiveRecord
243
232
 
244
233
  def emulated_checkin(connection)
245
234
  # NOTE: not sure we'd like to run `run_callbacks :checkin {}` here ...
246
- connection.expire
235
+ connection.expire if connection.owner.equal? Thread.current
247
236
  end
248
237
 
249
238
  def emulated_checkout(connection)
250
239
  # NOTE: not sure we'd like to run `run_callbacks :checkout {}` here ...
251
- connection.lease; # connection.verify! auto-reconnect should do this
240
+ connection.lease unless connection.in_use? # connection.verify! auto-reconnect should do this
241
+ end
242
+
243
+ def shared_checkin(conn)
244
+ #conn.lock.synchronize do
245
+ synchronize do
246
+ _run_checkin_callbacks(conn) if conn.owner.equal? Thread.current
247
+
248
+ @available.add conn
249
+ end
250
+ #end
252
251
  end
253
252
 
254
253
  def shared_connection_key
@@ -265,7 +264,7 @@ module ActiveRecord
265
264
  when 'true' then ActiveRecord::Base.logger
266
265
  else File.expand_path(debug)
267
266
  end
268
- require 'logger'; Logger.new log_dev
267
+ log_dev.respond_to?(:debug) ? log_dev : (require 'logger'; Logger.new log_dev)
269
268
  else nil
270
269
  end
271
270
  end
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module Bogacs
3
- VERSION = '0.7.0'
3
+ VERSION = '0.7.1'
4
4
  end
5
5
  end
@@ -4,8 +4,7 @@ module ActiveRecord
4
4
  module Bogacs
5
5
  class ShareablePool
6
6
 
7
- # TODO: ShareablePool is pretty much broken since 0.7 :
8
- class ConnectionPoolTest #< TestBase
7
+ class ConnectionPoolTest < TestBase
9
8
 
10
9
  include ConnectionAdapters::ConnectionPoolTestMethods
11
10
 
@@ -25,8 +24,7 @@ module ActiveRecord
25
24
 
26
25
  end
27
26
 
28
- # TODO: ShareablePool is pretty much broken since 0.7 :
29
- class PoolAPITest #< TestBase
27
+ class PoolAPITest < TestBase
30
28
 
31
29
  def setup; ActiveRecord::Base.connection end
32
30
  # def teardown; ActiveRecord::Base.connection_pool.reap end
@@ -4,8 +4,7 @@ module ActiveRecord
4
4
  module Bogacs
5
5
  class ShareablePool
6
6
 
7
- # TODO: ShareablePool is pretty much broken since 0.7 :
8
- class ConnectionSharingTest #< TestBase
7
+ class ConnectionSharingTest < TestBase
9
8
  include TestHelper
10
9
 
11
10
  def setup
@@ -244,7 +243,7 @@ module ActiveRecord
244
243
  sleep(0.005)
245
244
 
246
245
  with_shared_connection do |conn2|
247
- assert conn1 == conn2
246
+ assert conn1.equal?(conn2)
248
247
 
249
248
  # we can not do any-more here without a timeout :
250
249
  failed = nil
@@ -24,7 +24,7 @@ module ActiveRecord
24
24
  alias_method :connections, :initialized_connections
25
25
 
26
26
  def reserved_connections
27
- ActiveRecord::Base.connection_pool.reserved_connections
27
+ connection_pool.instance_variable_get :@thread_cached_conns
28
28
  end
29
29
 
30
30
  def available_connections
@@ -70,7 +70,7 @@ module ActiveRecord
70
70
  end
71
71
 
72
72
  def self.shutdown
73
- ActiveRecord::Base.connection_pool.discard!
73
+ ActiveRecord::Base.connection_pool.disconnect!
74
74
  ConnectionAdapters::ConnectionHandler.connection_pool_class = ConnectionAdapters::ConnectionPool
75
75
  end
76
76
 
data/test/test_helper.rb CHANGED
@@ -55,7 +55,7 @@ config[:'prepared_statements'] = prepared_statements if prepared_statements
55
55
  #jdbc_properties = { 'logUnclosedConnections' => true, 'loginTimeout' => 5 }
56
56
  #config[:'properties'] = jdbc_properties
57
57
  config[:'properties'] ||= {}
58
- config[:'properties']['useSSL'] ||= 'false' if config[:adapter].starts_with?('mysql')
58
+ config[:'properties']['useSSL'] ||= 'false' if config[:adapter].start_with?('mysql')
59
59
 
60
60
  checkout_timeout = ENV['AR_POOL_CHECKOUT_TIMEOUT'] || checkout_timeout
61
61
  config[:'checkout_timeout'] = checkout_timeout.to_f if checkout_timeout
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-bogacs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Karol Bucek
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-14 00:00:00.000000000 Z
11
+ date: 2022-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement