activerecord-bogacs 0.7.0 → 0.7.1

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 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