Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 458 lines (397 sloc) 15.83 kb
d869298 James Tucker Don't depend on rubygems loading thread (for Mutex)
raggi authored
1 require 'thread'
ff97e9d Nick Sieger Connection handling methods extracted out into separate ConnectionHandle...
nicksieger authored
2 require 'monitor'
50cd4bd Nick Sieger Introduce synchronization around connection pool access
nicksieger authored
3 require 'set'
e8550ee Jeremy Kemper Cherry-pick core extensions
jeremy authored
4 require 'active_support/core_ext/module/synchronization'
50cd4bd Nick Sieger Introduce synchronization around connection pool access
nicksieger authored
5
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
6 module ActiveRecord
fe575dd Nick Sieger Nearing the finish line. Initial fixed-size connection pool implemented,...
nicksieger authored
7 # Raised when a connection could not be obtained within the connection
8 # acquisition timeout period.
9 class ConnectionTimeoutError < ConnectionNotEstablished
10 end
11
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
12 module ConnectionAdapters
f17159b Xavier Noria edit pass: the names of Rails components have a space, ie, "Active Recor...
fxn authored
13 # Connection pool base class for managing Active Record database
fe575dd Nick Sieger Nearing the finish line. Initial fixed-size connection pool implemented,...
nicksieger authored
14 # connections.
15 #
a293278 Pratik Merge docrails
lifo authored
16 # == Introduction
17 #
18 # A connection pool synchronizes thread access to a limited number of
19 # database connections. The basic idea is that each thread checks out a
20 # database connection from the pool, uses that connection, and checks the
21 # connection back in. ConnectionPool is completely thread-safe, and will
22 # ensure that a connection cannot be used by two threads at the same time,
23 # as long as ConnectionPool's contract is correctly followed. It will also
24 # handle cases in which there are more threads than connections: if all
25 # connections have been checked out, and a thread tries to checkout a
26 # connection anyway, then ConnectionPool will wait until some other thread
27 # has checked in a connection.
28 #
29 # == Obtaining (checking out) a connection
30 #
fe575dd Nick Sieger Nearing the finish line. Initial fixed-size connection pool implemented,...
nicksieger authored
31 # Connections can be obtained and used from a connection pool in several
32 # ways:
33 #
f17159b Xavier Noria edit pass: the names of Rails components have a space, ie, "Active Recor...
fxn authored
34 # 1. Simply use ActiveRecord::Base.connection as with Active Record 2.1 and
817a07b Nick Sieger More doco and class/method renames. Now have a strategy for integration ...
nicksieger authored
35 # earlier (pre-connection-pooling). Eventually, when you're done with
36 # the connection(s) and wish it to be returned to the pool, you call
37 # ActiveRecord::Base.clear_active_connections!. This will be the
f17159b Xavier Noria edit pass: the names of Rails components have a space, ie, "Active Recor...
fxn authored
38 # default behavior for Active Record when used in conjunction with
39 # Action Pack's request handling cycle.
fe575dd Nick Sieger Nearing the finish line. Initial fixed-size connection pool implemented,...
nicksieger authored
40 # 2. Manually check out a connection from the pool with
41 # ActiveRecord::Base.connection_pool.checkout. You are responsible for
42 # returning this connection to the pool when finished by calling
43 # ActiveRecord::Base.connection_pool.checkin(connection).
44 # 3. Use ActiveRecord::Base.connection_pool.with_connection(&block), which
45 # obtains a connection, yields it as the sole argument to the block,
46 # and returns it to the pool after the block completes.
8e5e02b Nick Sieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
47 #
a293278 Pratik Merge docrails
lifo authored
48 # Connections in the pool are actually AbstractAdapter objects (or objects
49 # compatible with AbstractAdapter's interface).
50 #
51 # == Options
52 #
8e5e02b Nick Sieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
53 # There are two connection-pooling-related options that you can add to
54 # your database connection configuration:
55 #
56 # * +pool+: number indicating size of connection pool (default 5)
57 # * +wait_timeout+: number of seconds to block and wait for a connection
58 # before giving up and raising a timeout error (default 5 seconds).
817a07b Nick Sieger More doco and class/method renames. Now have a strategy for integration ...
nicksieger authored
59 class ConnectionPool
acccb72 Aaron Patterson column cache now lives on the connection pool
tenderlove authored
60 attr_accessor :automatic_reconnect
cccb998 José Valim Expose connections available in the connection pool.
josevalim authored
61 attr_reader :spec, :connections
0de661d Aaron Patterson the connection pool caches table_exists? calls
tenderlove authored
62 attr_reader :columns, :columns_hash, :primary_keys, :tables
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
63
a293278 Pratik Merge docrails
lifo authored
64 # Creates a new ConnectionPool object. +spec+ is a ConnectionSpecification
65 # object which describes database connection information (e.g. adapter,
66 # host name, username, password, etc), as well as the maximum size for
67 # this ConnectionPool.
68 #
69 # The default ConnectionPool maximum size is 5.
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
70 def initialize(spec)
71 @spec = spec
dd77733 Jeremy Kemper Timeout the connection pool monitor on ruby 1.8 only
jeremy authored
72
029952e Nick Sieger Extract a base class for connection pools, start to flesh out reserve/re...
nicksieger authored
73 # The cache of reserved connections mapped to threads
74 @reserved_connections = {}
dd77733 Jeremy Kemper Timeout the connection pool monitor on ruby 1.8 only
jeremy authored
75
cab76ce Nick Sieger Add synchronization to connection pool also
nicksieger authored
76 # The mutex used to synchronize pool access
77 @connection_mutex = Monitor.new
8e5e02b Nick Sieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
78 @queue = @connection_mutex.new_cond
2a04110 fix ruby 1.9 deadlock problem, fixes #5736 add connection pool tests
Hemant Kumar authored
79 @timeout = spec.config[:wait_timeout] || 5
dd77733 Jeremy Kemper Timeout the connection pool monitor on ruby 1.8 only
jeremy authored
80
8e5e02b Nick Sieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
81 # default max pool size to 5
82 @size = (spec.config[:pool] && spec.config[:pool].to_i) || 5
dd77733 Jeremy Kemper Timeout the connection pool monitor on ruby 1.8 only
jeremy authored
83
8e5e02b Nick Sieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
84 @connections = []
85 @checked_out = []
acccb72 Aaron Patterson column cache now lives on the connection pool
tenderlove authored
86 @automatic_reconnect = true
0de661d Aaron Patterson the connection pool caches table_exists? calls
tenderlove authored
87 @tables = {}
59f7780 Aaron Patterson adjust query counts to be consistent across databases, make sure databas...
tenderlove authored
88
5f3cf42 Aaron Patterson connection pool can cache column, table, and primary key information
tenderlove authored
89 @columns = Hash.new do |h, table_name|
90 h[table_name] = with_connection do |conn|
0cd4286 Aaron Patterson making sure primary key is set on the columns
tenderlove authored
91
92 # Fetch a list of columns
93 conn.columns(table_name, "#{table_name} Columns").tap do |columns|
94
95 # set primary key information
96 columns.each do |column|
97 column.primary = column.name == primary_keys[table_name]
98 end
99 end
5f3cf42 Aaron Patterson connection pool can cache column, table, and primary key information
tenderlove authored
100 end
101 end
102
103 @columns_hash = Hash.new do |h, table_name|
104 h[table_name] = Hash[columns[table_name].map { |col|
105 [col.name, col]
106 }]
107 end
108
109 @primary_keys = Hash.new do |h, table_name|
110 h[table_name] = with_connection do |conn|
0de661d Aaron Patterson the connection pool caches table_exists? calls
tenderlove authored
111 table_exists?(table_name) ? conn.primary_key(table_name) : 'id'
5f3cf42 Aaron Patterson connection pool can cache column, table, and primary key information
tenderlove authored
112 end
113 end
114 end
115
8f1b141 Sebastian Martinez Fixed punctuation errors.
smartinez87 authored
116 # A cached lookup for table existence.
0de661d Aaron Patterson the connection pool caches table_exists? calls
tenderlove authored
117 def table_exists?(name)
118 return true if @tables.key? name
119
120 with_connection do |conn|
121 conn.tables.each { |table| @tables[table] = true }
122 end
123
124 @tables.key? name
125 end
126
5f3cf42 Aaron Patterson connection pool can cache column, table, and primary key information
tenderlove authored
127 # Clears out internal caches:
128 #
129 # * columns
130 # * columns_hash
59f7780 Aaron Patterson adjust query counts to be consistent across databases, make sure databas...
tenderlove authored
131 # * tables
5f3cf42 Aaron Patterson connection pool can cache column, table, and primary key information
tenderlove authored
132 def clear_cache!
133 @columns.clear
134 @columns_hash.clear
59f7780 Aaron Patterson adjust query counts to be consistent across databases, make sure databas...
tenderlove authored
135 @tables.clear
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
136 end
137
8f1b141 Sebastian Martinez Fixed punctuation errors.
smartinez87 authored
138 # Clear out internal caches for table with +table_name+.
c94651f Aaron Patterson almost fisted
tenderlove authored
139 def clear_table_cache!(table_name)
140 @columns.delete table_name
141 @columns_hash.delete table_name
142 @primary_keys.delete table_name
143 end
144
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
145 # Retrieve the connection associated with the current thread, or call
146 # #checkout to obtain one if necessary.
147 #
148 # #connection can be called any number of times; the connection is
149 # held in a hash keyed by the thread id.
150 def connection
072cd60 Aaron Patterson refactor if / else to ||=
tenderlove authored
151 @reserved_connections[current_connection_id] ||= checkout
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
152 end
153
4211866 Aaron Patterson adding active_connection? to the connection pool
tenderlove authored
154 # Check to see if there is an active connection in this connection
155 # pool.
156 def active_connection?
157 @reserved_connections.key? current_connection_id
158 end
159
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
160 # Signal that the thread is finished with the current connection.
817a07b Nick Sieger More doco and class/method renames. Now have a strategy for integration ...
nicksieger authored
161 # #release_connection releases the connection-thread association
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
162 # and returns the connection to the pool.
3344520 Aaron Patterson reduce the number of times current_connection_id is called in with_conne...
tenderlove authored
163 def release_connection(with_id = current_connection_id)
164 conn = @reserved_connections.delete(with_id)
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
165 checkin conn if conn
166 end
167
0034b78 Sebastian Martinez Remove extra white spaces on ActiveRecord docs.
smartinez87 authored
168 # If a connection already exists yield it to the block. If no connection
b451de0 Santiago Pastorino Deletes trailing whitespaces (over text files only find * -type f -exec ...
spastorino authored
169 # exists checkout a connection, yield it to the block, and checkin the
5501b99 coderrr Ensure ActiveRecord::Base.connection_pool.with_connection creates a new ...
coderrr authored
170 # connection when finished.
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
171 def with_connection
3344520 Aaron Patterson reduce the number of times current_connection_id is called in with_conne...
tenderlove authored
172 connection_id = current_connection_id
173 fresh_connection = true unless @reserved_connections[connection_id]
5501b99 coderrr Ensure ActiveRecord::Base.connection_pool.with_connection creates a new ...
coderrr authored
174 yield connection
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
175 ensure
3344520 Aaron Patterson reduce the number of times current_connection_id is called in with_conne...
tenderlove authored
176 release_connection(connection_id) if fresh_connection
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
177 end
178
029952e Nick Sieger Extract a base class for connection pools, start to flesh out reserve/re...
nicksieger authored
179 # Returns true if a connection has already been opened.
180 def connected?
8e5e02b Nick Sieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
181 !@connections.empty?
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
182 end
183
a293278 Pratik Merge docrails
lifo authored
184 # Disconnects all connections in the pool, and clears the pool.
029952e Nick Sieger Extract a base class for connection pools, start to flesh out reserve/re...
nicksieger authored
185 def disconnect!
186 @reserved_connections.each do |name,conn|
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
187 checkin conn
029952e Nick Sieger Extract a base class for connection pools, start to flesh out reserve/re...
nicksieger authored
188 end
8e5e02b Nick Sieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
189 @reserved_connections = {}
190 @connections.each do |conn|
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
191 conn.disconnect!
192 end
8e5e02b Nick Sieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
193 @connections = []
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
194 end
195
8f1b141 Sebastian Martinez Fixed punctuation errors.
smartinez87 authored
196 # Clears the cache which maps classes.
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
197 def clear_reloadable_connections!
029952e Nick Sieger Extract a base class for connection pools, start to flesh out reserve/re...
nicksieger authored
198 @reserved_connections.each do |name, conn|
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
199 checkin conn
029952e Nick Sieger Extract a base class for connection pools, start to flesh out reserve/re...
nicksieger authored
200 end
201 @reserved_connections = {}
8e5e02b Nick Sieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
202 @connections.each do |conn|
203 conn.disconnect! if conn.requires_reloading?
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
204 end
62c4e4d Edgars Beigarts Fix connection reloading in development mode. [#4929 state:resolved]
ebeigarts authored
205 @connections.delete_if do |conn|
206 conn.requires_reloading?
207 end
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
208 end
209
817a07b Nick Sieger More doco and class/method renames. Now have a strategy for integration ...
nicksieger authored
210 # Verify active connections and remove and disconnect connections
211 # associated with stale threads.
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
212 def verify_active_connections! #:nodoc:
d07a6b1 Nick Sieger Make clear_active_connections! also return stale connections back to the...
nicksieger authored
213 clear_stale_cached_connections!
8e5e02b Nick Sieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
214 @connections.each do |connection|
7ba2872 Nick Sieger Deprecate verification_timeout and verify before reset
nicksieger authored
215 connection.verify!
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
216 end
217 end
218
d07a6b1 Nick Sieger Make clear_active_connections! also return stale connections back to the...
nicksieger authored
219 # Return any checked-out connections back to the pool by threads that
220 # are no longer alive.
221 def clear_stale_cached_connections!
42be67e Aaron Patterson unfactoring clear_stale_cached_connections!
tenderlove authored
222 keys = @reserved_connections.keys - Thread.list.find_all { |t|
223 t.alive?
224 }.map { |thread| thread.object_id }
225 keys.each do |key|
226 checkin @reserved_connections[key]
227 @reserved_connections.delete(key)
d07a6b1 Nick Sieger Make clear_active_connections! also return stale connections back to the...
nicksieger authored
228 end
229 end
230
a293278 Pratik Merge docrails
lifo authored
231 # Check-out a database connection from the pool, indicating that you want
232 # to use it. You should call #checkin when you no longer need this.
233 #
234 # This is done by either returning an existing connection, or by creating
235 # a new connection. If the maximum number of connections for this pool has
236 # already been reached, but the pool is empty (i.e. they're all being used),
237 # then this method will wait until a thread has checked in a connection.
238 # The wait time is bounded however: if no connection can be checked out
239 # within the timeout specified for this pool, then a ConnectionTimeoutError
240 # exception will be raised.
241 #
242 # Returns: an AbstractAdapter object.
243 #
244 # Raises:
245 # - ConnectionTimeoutError: no connection can be obtained from the pool
246 # within the timeout period.
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
247 def checkout
8e5e02b Nick Sieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
248 # Checkout an available connection
249 @connection_mutex.synchronize do
21eb18a Aliaksey Kandratsenka (aka Aliaksei Kandratsenka) Fix race in ConnectionPool#checkout
alk authored
250 loop do
251 conn = if @checked_out.size < @connections.size
252 checkout_existing_connection
253 elsif @connections.size < @size
254 checkout_new_connection
255 end
256 return conn if conn
2a04110 fix ruby 1.9 deadlock problem, fixes #5736 add connection pool tests
Hemant Kumar authored
257
258 @queue.wait(@timeout)
259
260 if(@checked_out.size < @connections.size)
21eb18a Aliaksey Kandratsenka (aka Aliaksei Kandratsenka) Fix race in ConnectionPool#checkout
alk authored
261 next
262 else
8343611 Aliaksey Kandratsenka (aka Aliaksei Kandratsenka) made ConnectionPool#checkout more robust by trying to loot dead threads ...
alk authored
263 clear_stale_cached_connections!
264 if @size == @checked_out.size
dd77733 Jeremy Kemper Timeout the connection pool monitor on ruby 1.8 only
jeremy authored
265 raise ConnectionTimeoutError, "could not obtain a database connection#{" within #{@timeout} seconds" if @timeout}. The max pool size is currently #{@size}; consider increasing it."
8343611 Aliaksey Kandratsenka (aka Aliaksei Kandratsenka) made ConnectionPool#checkout more robust by trying to loot dead threads ...
alk authored
266 end
21eb18a Aliaksey Kandratsenka (aka Aliaksei Kandratsenka) Fix race in ConnectionPool#checkout
alk authored
267 end
2a04110 fix ruby 1.9 deadlock problem, fixes #5736 add connection pool tests
Hemant Kumar authored
268
8e5e02b Nick Sieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
269 end
270 end
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
271 end
272
a293278 Pratik Merge docrails
lifo authored
273 # Check-in a database connection back into the pool, indicating that you
274 # no longer need this connection.
275 #
276 # +conn+: an AbstractAdapter object, which was obtained by earlier by
277 # calling +checkout+ on this pool.
8e5e02b Nick Sieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
278 def checkin(conn)
279 @connection_mutex.synchronize do
57bc25c John Firebaugh Use run_callbacks; the generated _run_<name>_callbacks method is not a p...
jfirebaugh authored
280 conn.run_callbacks :checkin do
471a394 Nick Sieger Modify connection pool callbacks to be compatible w/ new style
nicksieger authored
281 @checked_out.delete conn
282 @queue.signal
283 end
8e5e02b Nick Sieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
284 end
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
285 end
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
286
113cc4e Nick Sieger Remove some synchronization that's probably overkill, assuming one doesn...
nicksieger authored
287 synchronize :clear_reloadable_connections!, :verify_active_connections!,
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
288 :connected?, :disconnect!, :with => :@connection_mutex
289
290 private
fe575dd Nick Sieger Nearing the finish line. Initial fixed-size connection pool implemented,...
nicksieger authored
291 def new_connection
a3f12f5 Nick Sieger Default connection allow_concurrency to false (for PostgreSQL)
nicksieger authored
292 ActiveRecord::Base.send(spec.adapter_method, spec.config)
fe575dd Nick Sieger Nearing the finish line. Initial fixed-size connection pool implemented,...
nicksieger authored
293 end
294
d07a6b1 Nick Sieger Make clear_active_connections! also return stale connections back to the...
nicksieger authored
295 def current_connection_id #:nodoc:
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
296 Thread.current.object_id
297 end
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
298
fe575dd Nick Sieger Nearing the finish line. Initial fixed-size connection pool implemented,...
nicksieger authored
299 def checkout_new_connection
acccb72 Aaron Patterson column cache now lives on the connection pool
tenderlove authored
300 raise ConnectionNotEstablished unless @automatic_reconnect
301
fe575dd Nick Sieger Nearing the finish line. Initial fixed-size connection pool implemented,...
nicksieger authored
302 c = new_connection
303 @connections << c
a96b7d4 Nick Sieger Add connection reset and verification upon each connection checkout
nicksieger authored
304 checkout_and_verify(c)
fe575dd Nick Sieger Nearing the finish line. Initial fixed-size connection pool implemented,...
nicksieger authored
305 end
306
307 def checkout_existing_connection
d7d2d73 Nick Sieger Fix typo: was using brackets instead of parens. Must need more sleep.
nicksieger authored
308 c = (@connections - @checked_out).first
a96b7d4 Nick Sieger Add connection reset and verification upon each connection checkout
nicksieger authored
309 checkout_and_verify(c)
310 end
311
312 def checkout_and_verify(c)
471a394 Nick Sieger Modify connection pool callbacks to be compatible w/ new style
nicksieger authored
313 c.run_callbacks :checkout do
314 c.verify!
315 @checked_out << c
316 end
fe575dd Nick Sieger Nearing the finish line. Initial fixed-size connection pool implemented,...
nicksieger authored
317 c
318 end
319 end
320
a293278 Pratik Merge docrails
lifo authored
321 # ConnectionHandler is a collection of ConnectionPool objects. It is used
f17159b Xavier Noria edit pass: the names of Rails components have a space, ie, "Active Recor...
fxn authored
322 # for keeping separate connection pools for Active Record models that connect
a293278 Pratik Merge docrails
lifo authored
323 # to different databases.
324 #
325 # For example, suppose that you have 5 models, with the following hierarchy:
326 #
327 # |
328 # +-- Book
329 # | |
330 # | +-- ScaryBook
331 # | +-- GoodBook
332 # +-- Author
333 # +-- BankAccount
334 #
335 # Suppose that Book is to connect to a separate database (i.e. one other
336 # than the default database). Then Book, ScaryBook and GoodBook will all use
337 # the same connection pool. Likewise, Author and BankAccount will use the
338 # same connection pool. However, the connection pool used by Author/BankAccount
339 # is not the same as the one used by Book/ScaryBook/GoodBook.
340 #
341 # Normally there is only a single ConnectionHandler instance, accessible via
f17159b Xavier Noria edit pass: the names of Rails components have a space, ie, "Active Recor...
fxn authored
342 # ActiveRecord::Base.connection_handler. Active Record models use this to
a293278 Pratik Merge docrails
lifo authored
343 # determine that connection pool that they should use.
ca6d717 Nick Sieger Deprecate allow_concurrency and make it have no effect
nicksieger authored
344 class ConnectionHandler
b952470 Aaron Patterson use an attr_reader for performance
tenderlove authored
345 attr_reader :connection_pools
346
72d959d Nick Sieger Split connection handler into single- and multiple-thread versions.
nicksieger authored
347 def initialize(pools = {})
348 @connection_pools = pools
349 end
ff97e9d Nick Sieger Connection handling methods extracted out into separate ConnectionHandle...
nicksieger authored
350
351 def establish_connection(name, spec)
8e5e02b Nick Sieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
352 @connection_pools[name] = ConnectionAdapters::ConnectionPool.new(spec)
ff97e9d Nick Sieger Connection handling methods extracted out into separate ConnectionHandle...
nicksieger authored
353 end
354
25f9497 Aaron Patterson adding active_connections? to the connection pool for finding open conne...
tenderlove authored
355 # Returns true if there are any active connections among the connection
356 # pools that the ConnectionHandler is managing.
357 def active_connections?
358 connection_pools.values.any? { |pool| pool.active_connection? }
359 end
360
d07a6b1 Nick Sieger Make clear_active_connections! also return stale connections back to the...
nicksieger authored
361 # Returns any connections in use by the current thread back to the pool,
362 # and also returns connections to the pool cached by threads that are no
363 # longer alive.
ff97e9d Nick Sieger Connection handling methods extracted out into separate ConnectionHandle...
nicksieger authored
364 def clear_active_connections!
529c271 Nick Sieger Simplify dispatcher callbacks to eliminate unnecessary stale thread purg...
nicksieger authored
365 @connection_pools.each_value {|pool| pool.release_connection }
ff97e9d Nick Sieger Connection handling methods extracted out into separate ConnectionHandle...
nicksieger authored
366 end
367
8f1b141 Sebastian Martinez Fixed punctuation errors.
smartinez87 authored
368 # Clears the cache which maps classes.
ff97e9d Nick Sieger Connection handling methods extracted out into separate ConnectionHandle...
nicksieger authored
369 def clear_reloadable_connections!
370 @connection_pools.each_value {|pool| pool.clear_reloadable_connections! }
371 end
372
373 def clear_all_connections!
72d959d Nick Sieger Split connection handler into single- and multiple-thread versions.
nicksieger authored
374 @connection_pools.each_value {|pool| pool.disconnect! }
ff97e9d Nick Sieger Connection handling methods extracted out into separate ConnectionHandle...
nicksieger authored
375 end
376
377 # Verify active connections.
378 def verify_active_connections! #:nodoc:
817a07b Nick Sieger More doco and class/method renames. Now have a strategy for integration ...
nicksieger authored
379 @connection_pools.each_value {|pool| pool.verify_active_connections! }
ff97e9d Nick Sieger Connection handling methods extracted out into separate ConnectionHandle...
nicksieger authored
380 end
381
382 # Locate the connection of the nearest super class. This can be an
383 # active or defined connection: if it is the latter, it will be
384 # opened and set as the active connection for the class it was defined
385 # for (not necessarily the current class).
386 def retrieve_connection(klass) #:nodoc:
387 pool = retrieve_connection_pool(klass)
388 (pool && pool.connection) or raise ConnectionNotEstablished
389 end
390
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
391 # Returns true if a connection that's accessible to this class has
392 # already been opened.
ff97e9d Nick Sieger Connection handling methods extracted out into separate ConnectionHandle...
nicksieger authored
393 def connected?(klass)
0832bc6 Pratik Make sure ActiveRecord::Base.connected? doesn't raise an exception for d...
lifo authored
394 conn = retrieve_connection_pool(klass)
a4458f5 Aaron Patterson removing useless ternary
tenderlove authored
395 conn && conn.connected?
ff97e9d Nick Sieger Connection handling methods extracted out into separate ConnectionHandle...
nicksieger authored
396 end
397
398 # Remove the connection for this class. This will close the active
399 # connection and the defined connection (if they exist). The result
400 # can be used as an argument for establish_connection, for easily
401 # re-establishing the connection.
402 def remove_connection(klass)
403 pool = @connection_pools[klass.name]
04ef434 Aaron Patterson only test for existence of +pool+ once
tenderlove authored
404 return nil unless pool
405
acccb72 Aaron Patterson column cache now lives on the connection pool
tenderlove authored
406 pool.automatic_reconnect = false
04ef434 Aaron Patterson only test for existence of +pool+ once
tenderlove authored
407 pool.disconnect!
408 pool.spec.config
ff97e9d Nick Sieger Connection handling methods extracted out into separate ConnectionHandle...
nicksieger authored
409 end
410
fe575dd Nick Sieger Nearing the finish line. Initial fixed-size connection pool implemented,...
nicksieger authored
411 def retrieve_connection_pool(klass)
3007545 Nick Sieger Minor tweak to retrieve_connection_pool -- recurse instead of loop
nicksieger authored
412 pool = @connection_pools[klass.name]
413 return pool if pool
414 return nil if ActiveRecord::Base == klass
415 retrieve_connection_pool klass.superclass
fe575dd Nick Sieger Nearing the finish line. Initial fixed-size connection pool implemented,...
nicksieger authored
416 end
72d959d Nick Sieger Split connection handler into single- and multiple-thread versions.
nicksieger authored
417 end
1b22071 Joshua Peek Ensure ActiveRecord session store's connections are checked in after eac...
josh authored
418
419 class ConnectionManagement
e524609 Aaron Patterson proxy body responses so we close database connections after body is flus...
tenderlove authored
420 class Proxy # :nodoc:
421 attr_reader :body, :testing
422
423 def initialize(body, testing = false)
424 @body = body
425 @testing = testing
426 end
427
428 def each(&block)
429 body.each(&block)
430 end
431
432 def close
433 body.close if body.respond_to?(:close)
434
435 # Don't return connection (and perform implicit rollback) if
436 # this request is a part of integration test
437 ActiveRecord::Base.clear_active_connections! unless testing
438 end
439 end
440
1b22071 Joshua Peek Ensure ActiveRecord session store's connections are checked in after eac...
josh authored
441 def initialize(app)
442 @app = app
443 end
444
445 def call(env)
c7b7c6a Aaron Patterson make sure that active connections are not cleared during test when an ex...
tenderlove authored
446 testing = env.key?('rack.test')
447
e524609 Aaron Patterson proxy body responses so we close database connections after body is flus...
tenderlove authored
448 status, headers, body = @app.call(env)
449
c7b7c6a Aaron Patterson make sure that active connections are not cleared during test when an ex...
tenderlove authored
450 [status, headers, Proxy.new(body, testing)]
3b2a032 Aaron Patterson clearing active connections in the ConnectionManagement middleware if an...
tenderlove authored
451 rescue
c7b7c6a Aaron Patterson make sure that active connections are not cleared during test when an ex...
tenderlove authored
452 ActiveRecord::Base.clear_active_connections! unless testing
3b2a032 Aaron Patterson clearing active connections in the ConnectionManagement middleware if an...
tenderlove authored
453 raise
1b22071 Joshua Peek Ensure ActiveRecord session store's connections are checked in after eac...
josh authored
454 end
455 end
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
456 end
21eb18a Aliaksey Kandratsenka (aka Aliaksei Kandratsenka) Fix race in ConnectionPool#checkout
alk authored
457 end
Something went wrong with that request. Please try again.