activerecord-bogacs 0.5.0 → 0.7.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/test.yml +82 -0
- data/.travis.yml +32 -34
- data/Gemfile +2 -15
- data/LICENSE.txt +1 -1
- data/README.md +45 -21
- data/Rakefile +8 -6
- data/activerecord-bogacs.gemspec +6 -6
- data/lib/active_record/bogacs/autoload.rb +10 -0
- data/lib/active_record/bogacs/connection_handler.rb +36 -0
- data/lib/active_record/bogacs/default_pool.rb +278 -129
- data/lib/active_record/bogacs/false_pool.rb +95 -73
- data/lib/active_record/bogacs/pool_support.rb +26 -9
- data/lib/active_record/bogacs/railtie.rb +17 -0
- data/lib/active_record/bogacs/reaper.rb +4 -6
- data/lib/active_record/bogacs/shareable_pool.rb +12 -16
- data/lib/active_record/bogacs/thread_safe/synchronized.rb +18 -22
- data/lib/active_record/bogacs/thread_safe.rb +3 -67
- data/lib/active_record/bogacs/validator.rb +21 -26
- data/lib/active_record/bogacs/version.rb +2 -2
- data/lib/active_record/bogacs.rb +7 -54
- data/lib/active_record/connection_adapters/adapter_compat.rb +63 -17
- data/lib/active_record/connection_adapters/pool_class.rb +75 -0
- data/lib/activerecord-bogacs.rb +1 -0
- data/test/active_record/bogacs/false_pool_test.rb +66 -78
- data/test/active_record/bogacs/shareable_pool/connection_pool_test.rb +6 -3
- data/test/active_record/bogacs/shareable_pool/connection_sharing_test.rb +3 -2
- data/test/active_record/bogacs/shareable_pool_helper.rb +1 -1
- data/test/active_record/bogacs/validator_test.rb +22 -28
- data/test/active_record/connection_pool_test_methods.rb +24 -20
- data/test/test_helper.rb +42 -25
- metadata +35 -17
@@ -1,3 +1,8 @@
|
|
1
|
+
require 'active_record/version'
|
2
|
+
|
3
|
+
require 'concurrent/atomic/atomic_boolean'
|
4
|
+
|
5
|
+
require 'active_record/connection_adapters/adapter_compat'
|
1
6
|
require 'active_record/bogacs/pool_support'
|
2
7
|
require 'active_record/bogacs/thread_safe'
|
3
8
|
|
@@ -14,17 +19,17 @@ module ActiveRecord
|
|
14
19
|
attr_reader :size, :spec
|
15
20
|
|
16
21
|
def initialize(spec)
|
17
|
-
|
22
|
+
super()
|
18
23
|
|
19
24
|
@spec = spec
|
20
25
|
@size = nil
|
21
26
|
@automatic_reconnect = nil
|
27
|
+
@lock_thread = false
|
22
28
|
|
23
|
-
@
|
24
|
-
end
|
29
|
+
@thread_cached_conns = ThreadSafe::Map.new
|
25
30
|
|
26
|
-
|
27
|
-
|
31
|
+
@connected = ::Concurrent::AtomicBoolean.new
|
32
|
+
end
|
28
33
|
|
29
34
|
# @private attr_reader :reaper
|
30
35
|
def reaper; end
|
@@ -38,20 +43,21 @@ module ActiveRecord
|
|
38
43
|
# #connection can be called any number of times; the connection is
|
39
44
|
# held in a hash keyed by the thread id.
|
40
45
|
def connection
|
41
|
-
|
46
|
+
connection_id = current_connection_id(current_thread)
|
47
|
+
@thread_cached_conns[connection_id] ||= checkout
|
42
48
|
end
|
43
49
|
|
44
50
|
# Is there an open connection that is being used for the current thread?
|
45
51
|
def active_connection?
|
46
|
-
|
47
|
-
|
52
|
+
connection_id = current_connection_id(current_thread)
|
53
|
+
@thread_cached_conns[connection_id]
|
48
54
|
end
|
49
55
|
|
50
56
|
# Signal that the thread is finished with the current connection.
|
51
57
|
# #release_connection releases the connection-thread association
|
52
58
|
# and returns the connection to the pool.
|
53
|
-
def release_connection(
|
54
|
-
conn = @
|
59
|
+
def release_connection(owner_thread = Thread.current)
|
60
|
+
conn = @thread_cached_conns.delete(current_connection_id(owner_thread))
|
55
61
|
checkin conn if conn
|
56
62
|
end
|
57
63
|
|
@@ -60,40 +66,63 @@ module ActiveRecord
|
|
60
66
|
# connection when finished.
|
61
67
|
def with_connection
|
62
68
|
connection_id = current_connection_id
|
63
|
-
|
64
|
-
|
69
|
+
unless conn = @thread_cached_conns[connection_id]
|
70
|
+
conn = connection
|
71
|
+
fresh_connection = true
|
72
|
+
end
|
73
|
+
yield conn
|
65
74
|
ensure
|
66
|
-
release_connection
|
75
|
+
release_connection if fresh_connection
|
67
76
|
end
|
68
77
|
|
69
78
|
# Returns true if a connection has already been opened.
|
70
|
-
def connected?; @connected end
|
79
|
+
def connected?; @connected.true? end
|
80
|
+
|
81
|
+
# @private replacement for attr_reader :connections
|
82
|
+
def connections; @thread_cached_conns.values end
|
71
83
|
|
72
84
|
# Disconnects all connections in the pool, and clears the pool.
|
73
85
|
def disconnect!
|
74
86
|
synchronize do
|
75
|
-
@connected
|
76
|
-
|
77
|
-
connections = @reserved_connections.values
|
78
|
-
@reserved_connections.clear
|
87
|
+
@connected.make_false
|
79
88
|
|
89
|
+
connections = @thread_cached_conns.values
|
90
|
+
@thread_cached_conns.clear
|
80
91
|
connections.each do |conn|
|
81
|
-
|
92
|
+
if conn.in_use?
|
93
|
+
conn.steal!
|
94
|
+
checkin conn
|
95
|
+
end
|
82
96
|
conn.disconnect!
|
83
97
|
end
|
84
98
|
end
|
85
99
|
end
|
86
100
|
|
101
|
+
def discard! # :nodoc:
|
102
|
+
synchronize do
|
103
|
+
return if @thread_cached_conns.nil? # already discarded
|
104
|
+
@connected.make_false
|
105
|
+
|
106
|
+
connections.each do |conn|
|
107
|
+
conn.discard!
|
108
|
+
end
|
109
|
+
@thread_cached_conns = nil
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
87
113
|
# Clears the cache which maps classes.
|
88
114
|
def clear_reloadable_connections!
|
89
115
|
synchronize do
|
90
|
-
@connected
|
116
|
+
@connected.make_false
|
91
117
|
|
92
|
-
connections = @
|
93
|
-
@
|
118
|
+
connections = @thread_cached_conns.values
|
119
|
+
@thread_cached_conns.clear
|
94
120
|
|
95
121
|
connections.each do |conn|
|
96
|
-
|
122
|
+
if conn.in_use?
|
123
|
+
conn.steal!
|
124
|
+
checkin conn
|
125
|
+
end
|
97
126
|
conn.disconnect! if conn.requires_reloading?
|
98
127
|
end
|
99
128
|
end
|
@@ -105,7 +134,7 @@ module ActiveRecord
|
|
105
134
|
def verify_active_connections!
|
106
135
|
synchronize do
|
107
136
|
clear_stale_cached_connections!
|
108
|
-
@
|
137
|
+
@thread_cached_conns.values.each(&:verify!)
|
109
138
|
end
|
110
139
|
end if ActiveRecord::VERSION::MAJOR < 4
|
111
140
|
|
@@ -113,12 +142,12 @@ module ActiveRecord
|
|
113
142
|
# are no longer alive.
|
114
143
|
# @private AR 3.2 compatibility
|
115
144
|
def clear_stale_cached_connections!
|
116
|
-
keys = Thread.list.find_all { |t| t.alive? }.map(
|
117
|
-
keys = @
|
145
|
+
keys = Thread.list.find_all { |t| t.alive? }.map { |t| current_connection_id(t) }
|
146
|
+
keys = @thread_cached_conns.keys - keys
|
118
147
|
keys.each do |key|
|
119
|
-
if conn = @
|
120
|
-
checkin conn,
|
121
|
-
@
|
148
|
+
if conn = @thread_cached_conns[key]
|
149
|
+
checkin conn, true # no release
|
150
|
+
@thread_cached_conns.delete(key)
|
122
151
|
end
|
123
152
|
end
|
124
153
|
end if ActiveRecord::VERSION::MAJOR < 4
|
@@ -126,38 +155,26 @@ module ActiveRecord
|
|
126
155
|
# Check-out a database connection from the pool, indicating that you want
|
127
156
|
# to use it. You should call #checkin when you no longer need this.
|
128
157
|
#
|
129
|
-
#
|
130
|
-
#
|
131
|
-
#
|
132
|
-
# If all connections are leased and the pool is at capacity (meaning the
|
133
|
-
# number of currently leased connections is greater than or equal to the
|
134
|
-
# size limit set), an ActiveRecord::ConnectionTimeoutError exception will be raised.
|
135
|
-
#
|
136
|
-
# Returns: an AbstractAdapter object.
|
137
|
-
#
|
138
|
-
# Raises:
|
139
|
-
# - ConnectionTimeoutError: no connection can be obtained from the pool.
|
158
|
+
# @return [ActiveRecord::ConnectionAdapters::AbstractAdapter]
|
159
|
+
# @raise [ActiveRecord::ConnectionTimeoutError] no connection can be obtained from the pool
|
140
160
|
def checkout
|
141
|
-
#
|
142
|
-
|
161
|
+
conn = checkout_new_connection # acquire_connection
|
162
|
+
synchronize do
|
143
163
|
conn.lease
|
144
164
|
_run_checkout_callbacks(conn) # checkout_and_verify(conn)
|
145
|
-
|
146
|
-
|
165
|
+
end
|
166
|
+
conn
|
147
167
|
end
|
148
168
|
|
149
169
|
# Check-in a database connection back into the pool, indicating that you
|
150
170
|
# no longer need this connection.
|
151
171
|
#
|
152
|
-
#
|
153
|
-
# calling
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
#release conn
|
159
|
-
#@available.add conn
|
160
|
-
#end
|
172
|
+
# @param conn [ActiveRecord::ConnectionAdapters::AbstractAdapter] connection
|
173
|
+
# object, which was obtained earlier by calling #checkout on this pool
|
174
|
+
# @see #checkout
|
175
|
+
def checkin(conn, released = nil)
|
176
|
+
release(conn) unless released
|
177
|
+
_run_checkin_callbacks(conn)
|
161
178
|
end
|
162
179
|
|
163
180
|
# Remove a connection from the connection pool. The connection will
|
@@ -171,15 +188,24 @@ module ActiveRecord
|
|
171
188
|
# we do not really manage the connection pool - nothing to do ...
|
172
189
|
end
|
173
190
|
|
191
|
+
def flush(minimum_idle = nil)
|
192
|
+
# we do not really manage the connection pool
|
193
|
+
end
|
194
|
+
|
195
|
+
def flush!
|
196
|
+
reap
|
197
|
+
flush(-1)
|
198
|
+
end
|
199
|
+
|
200
|
+
def stat
|
201
|
+
{
|
202
|
+
connections: connections.size
|
203
|
+
}
|
204
|
+
end
|
205
|
+
|
174
206
|
private
|
175
207
|
|
176
|
-
#
|
177
|
-
# from the queue of available connections, 2) creating a new
|
178
|
-
# connection if the pool is not at capacity, 3) waiting on the
|
179
|
-
# queue for a connection to become available.
|
180
|
-
#
|
181
|
-
# Raises:
|
182
|
-
# - ConnectionTimeoutError if a connection could not be acquired
|
208
|
+
# @raise [ActiveRecord::ConnectionTimeoutError]
|
183
209
|
def acquire_connection
|
184
210
|
# underlying pool will poll and block if "empty" (all checked-out)
|
185
211
|
#if conn = @available.poll
|
@@ -193,34 +219,30 @@ module ActiveRecord
|
|
193
219
|
checkout_new_connection
|
194
220
|
end
|
195
221
|
|
196
|
-
def release(conn, owner =
|
197
|
-
thread_id = owner
|
222
|
+
def release(conn, owner = conn.owner)
|
223
|
+
thread_id = current_connection_id(owner) unless owner.nil?
|
198
224
|
|
199
225
|
thread_id ||=
|
200
|
-
if @
|
226
|
+
if @thread_cached_conns[conn_id = current_connection_id].equal?(conn)
|
201
227
|
conn_id
|
202
228
|
else
|
203
|
-
connections = @
|
204
|
-
connections.keys.find { |k| connections[k]
|
229
|
+
connections = @thread_cached_conns
|
230
|
+
connections.keys.find { |k| connections[k].equal?(conn) }
|
205
231
|
end
|
206
232
|
|
207
|
-
@
|
233
|
+
@thread_cached_conns.delete_pair(thread_id, conn) if thread_id
|
208
234
|
end
|
209
235
|
|
210
236
|
def checkout_new_connection
|
211
|
-
# NOTE: automatic reconnect
|
212
|
-
#raise ConnectionNotEstablished unless @automatic_reconnect
|
213
|
-
|
237
|
+
# NOTE: automatic reconnect makes no sense for us!
|
214
238
|
begin
|
215
239
|
conn = new_connection
|
216
|
-
rescue ConnectionTimeoutError => e
|
217
|
-
raise e
|
218
240
|
rescue => e
|
219
|
-
raise ConnectionTimeoutError, e.message if timeout_error?(e)
|
241
|
+
raise ConnectionTimeoutError, e.message if timeout_error?(e) && !e.is_a?(ConnectionTimeoutError)
|
220
242
|
raise e
|
221
243
|
end
|
244
|
+
@connected.make_true
|
222
245
|
conn.pool = self
|
223
|
-
synchronize { @connected = true } if @connected != true
|
224
246
|
conn
|
225
247
|
end
|
226
248
|
|
@@ -1,21 +1,34 @@
|
|
1
|
-
|
1
|
+
require 'active_record/connection_adapters/abstract/query_cache'
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Bogacs
|
5
5
|
module PoolSupport
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
def self.included(base)
|
8
|
+
base.send :include, ActiveRecord::ConnectionAdapters::QueryCache::ConnectionPoolConfiguration
|
9
|
+
end if ActiveRecord::ConnectionAdapters::QueryCache.const_defined? :ConnectionPoolConfiguration
|
10
|
+
|
11
|
+
attr_accessor :schema_cache
|
12
|
+
|
13
|
+
def lock_thread=(lock_thread)
|
14
|
+
if lock_thread
|
15
|
+
@lock_thread = Thread.current
|
16
|
+
else
|
17
|
+
@lock_thread = nil
|
18
|
+
end
|
19
|
+
end if ActiveRecord::VERSION::MAJOR > 4
|
10
20
|
|
11
21
|
def new_connection
|
12
|
-
Base.send(spec.adapter_method, spec.config)
|
22
|
+
conn = Base.send(spec.adapter_method, spec.config)
|
23
|
+
conn.schema_cache = schema_cache.dup if schema_cache && conn.respond_to?(:schema_cache=)
|
24
|
+
conn
|
13
25
|
end
|
14
26
|
|
15
|
-
|
16
|
-
|
17
|
-
|
27
|
+
# @private
|
28
|
+
def current_connection_id(owner_thread = Thread.current)
|
29
|
+
owner_thread.object_id
|
18
30
|
end
|
31
|
+
alias_method :connection_cache_key, :current_connection_id # for AR (5.2) compatibility
|
19
32
|
|
20
33
|
# @note Method not part of the pre 4.0 API (does no exist).
|
21
34
|
def remove(conn)
|
@@ -38,6 +51,10 @@ module ActiveRecord
|
|
38
51
|
|
39
52
|
private
|
40
53
|
|
54
|
+
def current_thread
|
55
|
+
@lock_thread || Thread.current
|
56
|
+
end
|
57
|
+
|
41
58
|
if ActiveRecord::VERSION::STRING > '4.2'
|
42
59
|
|
43
60
|
def _run_checkin_callbacks(conn)
|
@@ -90,4 +107,4 @@ module ActiveRecord
|
|
90
107
|
|
91
108
|
end
|
92
109
|
end
|
93
|
-
end
|
110
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Bogacs
|
3
|
+
class Railtie < Rails::Railtie
|
4
|
+
|
5
|
+
initializer 'active_record.bogacs', :before => 'active_record.initialize_database' do |_|
|
6
|
+
ActiveSupport.on_load :active_record do
|
7
|
+
require 'active_record/bogacs'
|
8
|
+
|
9
|
+
# support for auto-configuring FalsePool (when config[:pool] set to false) :
|
10
|
+
require 'active_record/bogacs/connection_handler'
|
11
|
+
ActiveRecord::Base.default_connection_handler = ConnectionHandler.new
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -3,22 +3,20 @@ require 'thread'
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Bogacs
|
5
5
|
|
6
|
-
# Every
|
6
|
+
# Every *frequency* seconds, the reaper will "reap" a pool it belongs to.
|
7
7
|
# Reaping means detecting stale cached connections in the pool - those that
|
8
8
|
# were checked-out by a thread but never checked back in after the thread
|
9
9
|
# finished/died.
|
10
10
|
#
|
11
|
-
#
|
12
|
-
# Instead the thread will be restarted and reaping continues at the next tick.
|
13
|
-
#
|
14
|
-
# Configure the frequency by setting `:reaping_frequency` in your database yaml file.
|
11
|
+
# Configure the frequency by setting `:reaping_frequency` in your database.yml.
|
15
12
|
#
|
13
|
+
# @note This version is fail safe - raised errors won't stop the reaping process.
|
16
14
|
class Reaper
|
17
15
|
|
18
16
|
attr_reader :pool, :frequency
|
19
17
|
attr_accessor :retry_error
|
20
18
|
|
21
|
-
# Reaper.new(
|
19
|
+
# `Reaper.new(pool, spec.config[:reaping_frequency]).run`
|
22
20
|
# @private
|
23
21
|
def initialize(pool, frequency)
|
24
22
|
@pool = pool;
|
@@ -1,9 +1,10 @@
|
|
1
|
+
require 'active_record/version'
|
1
2
|
require 'active_record/connection_adapters/abstract/connection_pool'
|
2
3
|
|
3
|
-
require '
|
4
|
+
require 'concurrent/atomic/atomic_reference'
|
5
|
+
require 'concurrent/thread_safe/util/cheap_lockable.rb'
|
4
6
|
|
5
7
|
require 'active_record/bogacs/thread_safe'
|
6
|
-
|
7
8
|
require 'active_record/bogacs/pool_support'
|
8
9
|
|
9
10
|
# NOTE: needs explicit configuration - before connection gets established e.g.
|
@@ -16,14 +17,9 @@ module ActiveRecord
|
|
16
17
|
class ShareablePool < ConnectionAdapters::ConnectionPool # NOTE: maybe do not override?!
|
17
18
|
include PoolSupport
|
18
19
|
|
19
|
-
|
20
|
-
include ThreadSafe::CheapLockable
|
21
|
-
else
|
22
|
-
alias_method :cheap_synchronize, :synchronize
|
23
|
-
end
|
20
|
+
include ThreadSafe::Synchronized
|
24
21
|
|
25
|
-
|
26
|
-
AtomicReference = ThreadSafe::AtomicReference
|
22
|
+
AtomicReference = ::Concurrent::AtomicReference
|
27
23
|
|
28
24
|
DEFAULT_SHARED_POOL = 0.25 # only allow 25% of the pool size to be shared
|
29
25
|
MAX_THREAD_SHARING = 5 # not really a strict limit but should hold
|
@@ -60,7 +56,7 @@ module ActiveRecord
|
|
60
56
|
def release_connection(with_id = current_connection_id)
|
61
57
|
if reserved_conn = @reserved_connections[with_id]
|
62
58
|
if shared_count = @shared_connections[reserved_conn]
|
63
|
-
|
59
|
+
synchronize do # lock due #get_shared_connection ... not needed ?!
|
64
60
|
# NOTE: the other option is to not care about shared here at all ...
|
65
61
|
if shared_count.get == 0 # releasing a shared connection
|
66
62
|
release_shared_connection(reserved_conn)
|
@@ -75,18 +71,18 @@ module ActiveRecord
|
|
75
71
|
|
76
72
|
# @override
|
77
73
|
def disconnect!
|
78
|
-
|
74
|
+
synchronize { @shared_connections.clear; super }
|
79
75
|
end
|
80
76
|
|
81
77
|
# @override
|
82
78
|
def clear_reloadable_connections!
|
83
|
-
|
79
|
+
synchronize { @shared_connections.clear; super }
|
84
80
|
end
|
85
81
|
|
86
82
|
# @override
|
87
83
|
# @note called from #reap thus the pool should work with reaper
|
88
84
|
def remove(conn)
|
89
|
-
|
85
|
+
synchronize { @shared_connections.delete(conn); super }
|
90
86
|
end
|
91
87
|
|
92
88
|
# # Return any checked-out connections back to the pool by threads that
|
@@ -135,7 +131,7 @@ module ActiveRecord
|
|
135
131
|
emulated_checkout(connection); shared = true
|
136
132
|
DEBUG && debug("with_shared_conn 20 got shared = #{connection.to_s}")
|
137
133
|
else
|
138
|
-
|
134
|
+
synchronize do
|
139
135
|
# check shared again as/if threads end up sync-ing up here :
|
140
136
|
if connection = get_shared_connection
|
141
137
|
emulated_checkout(connection)
|
@@ -218,7 +214,7 @@ module ActiveRecord
|
|
218
214
|
end
|
219
215
|
|
220
216
|
# we did as much as could without a lock - now sync due possible release
|
221
|
-
|
217
|
+
synchronize do # TODO although this likely might be avoided ...
|
222
218
|
# should try again if possibly the same connection got released :
|
223
219
|
unless least_count = @shared_connections[least_shared]
|
224
220
|
DEBUG && debug(" get_shared_conn retry (connection got released)")
|
@@ -238,7 +234,7 @@ module ActiveRecord
|
|
238
234
|
def rem_shared_connection(connection)
|
239
235
|
if shared_count = @shared_connections[connection]
|
240
236
|
# shared_count.update { |v| v - 1 } # NOTE: likely fine without lock!
|
241
|
-
|
237
|
+
synchronize do # give it back to the pool
|
242
238
|
shared_count.update { |v| v - 1 } # might give it back if :
|
243
239
|
release_shared_connection(connection) if shared_count.get == 0
|
244
240
|
end
|
@@ -1,33 +1,29 @@
|
|
1
|
+
require 'concurrent/thread_safe/util/cheap_lockable.rb'
|
2
|
+
|
1
3
|
# @note Inpspired by thread_safe gem's Util::CheapLockable mixin.
|
2
4
|
module ActiveRecord::Bogacs
|
3
5
|
module ThreadSafe
|
4
|
-
|
5
|
-
if engine == 'rbx'
|
6
|
+
if defined? JRUBY_VERSION
|
6
7
|
module Synchronized
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
::
|
8
|
+
if defined? ::JRuby::Util.synchronized # since JRuby 9.3
|
9
|
+
def synchronize
|
10
|
+
::JRuby::Util.synchronized(self) { yield }
|
11
|
+
end
|
12
|
+
else
|
13
|
+
require 'jruby'
|
14
|
+
def synchronize
|
15
|
+
::JRuby.reference0(self).synchronized { yield }
|
15
16
|
end
|
16
17
|
end
|
17
18
|
end
|
18
|
-
|
19
|
+
else
|
20
|
+
require 'concurrent/thread_safe/util/cheap_lockable.rb'
|
21
|
+
|
19
22
|
module Synchronized
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
def synchronize
|
24
|
-
::JRuby.reference0(self).synchronized { yield }
|
25
|
-
end
|
23
|
+
include ::Concurrent::ThreadSafe::Util::CheapLockable
|
24
|
+
alias_method :synchronize, :cheap_synchronize
|
25
|
+
public :synchronize
|
26
26
|
end
|
27
|
-
else
|
28
|
-
require 'thread'; require 'monitor'
|
29
|
-
# on MRI fallback to built-in MonitorMixin
|
30
|
-
Synchronized = MonitorMixin
|
31
27
|
end
|
32
28
|
end
|
33
|
-
end
|
29
|
+
end
|
@@ -2,75 +2,11 @@ module ActiveRecord
|
|
2
2
|
module Bogacs
|
3
3
|
module ThreadSafe
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
require 'concurrent/map.rb'
|
8
|
-
rescue LoadError => e
|
9
|
-
begin
|
10
|
-
require 'thread_safe'
|
11
|
-
rescue
|
12
|
-
warn "activerecord-bogacs needs gem 'concurrent-ruby', '~> 1.0' (or the old 'thread_safe' gem) " <<
|
13
|
-
"please install or add it to your Gemfile"
|
14
|
-
raise e
|
15
|
-
end
|
16
|
-
end
|
17
|
-
#end
|
18
|
-
|
19
|
-
#load_map # always pre-load thread_safe
|
20
|
-
|
21
|
-
if defined? ::Concurrent::Map
|
22
|
-
Map = ::Concurrent::Map
|
23
|
-
else
|
24
|
-
Map = ::ThreadSafe::Cache
|
25
|
-
end
|
5
|
+
require 'concurrent/map.rb'
|
6
|
+
Map = ::Concurrent::Map
|
26
7
|
|
27
8
|
autoload :Synchronized, 'active_record/bogacs/thread_safe/synchronized'
|
28
9
|
|
29
|
-
def self.load_atomic_reference
|
30
|
-
return const_get :AtomicReference if const_defined? :AtomicReference
|
31
|
-
|
32
|
-
begin
|
33
|
-
require 'concurrent/atomic/atomic_reference.rb'
|
34
|
-
rescue LoadError => e
|
35
|
-
begin
|
36
|
-
require 'atomic'
|
37
|
-
rescue LoadError
|
38
|
-
warn "shareable pool needs gem 'concurrent-ruby', '>= 0.9.1' (or the old 'atomic' gem) " <<
|
39
|
-
"please install or add it to your Gemfile"
|
40
|
-
raise e
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
if defined? ::Concurrent::AtomicReference
|
45
|
-
const_set :AtomicReference, ::Concurrent::AtomicReference
|
46
|
-
else
|
47
|
-
const_set :AtomicReference, ::Atomic
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def self.load_cheap_lockable(required = true)
|
52
|
-
return const_get :CheapLockable if const_defined? :CheapLockable
|
53
|
-
|
54
|
-
begin
|
55
|
-
require 'concurrent/thread_safe/util/cheap_lockable.rb'
|
56
|
-
rescue LoadError => e
|
57
|
-
begin
|
58
|
-
require 'thread_safe'
|
59
|
-
rescue
|
60
|
-
return nil unless required
|
61
|
-
warn "activerecord-bogacs needs gem 'concurrent-ruby', '~> 1.0' (or the old 'thread_safe' gem) " <<
|
62
|
-
"please install or add it to your Gemfile"
|
63
|
-
raise e
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
if defined? ::Concurrent::ThreadSafe::Util::CheapLockable
|
68
|
-
const_set :CheapLockable, ::Concurrent::ThreadSafe::Util::CheapLockable
|
69
|
-
else
|
70
|
-
const_set :CheapLockable, ::ThreadSafe::Util::CheapLockable
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
10
|
end
|
75
11
|
end
|
76
|
-
end
|
12
|
+
end
|