Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 483 lines (417 sloc) 16.364 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'
bd2f5c0 Aaron Patterson pushing caching and visitors down to the connection
tenderlove authored
4 require 'active_support/core_ext/module/deprecation'
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
c606fe2 Aaron Patterson push synchronization in to each method. Reduces method calls and makes
tenderlove authored
60 include MonitorMixin
61
acccb72 Aaron Patterson column cache now lives on the connection pool
tenderlove authored
62 attr_accessor :automatic_reconnect
cccb998 José Valim Expose connections available in the connection pool.
josevalim authored
63 attr_reader :spec, :connections
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
64
a293278 Pratik Merge docrails
lifo authored
65 # Creates a new ConnectionPool object. +spec+ is a ConnectionSpecification
66 # object which describes database connection information (e.g. adapter,
67 # host name, username, password, etc), as well as the maximum size for
68 # this ConnectionPool.
69 #
70 # The default ConnectionPool maximum size is 5.
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
71 def initialize(spec)
c606fe2 Aaron Patterson push synchronization in to each method. Reduces method calls and makes
tenderlove authored
72 super()
73
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
74 @spec = spec
dd77733 Jeremy Kemper Timeout the connection pool monitor on ruby 1.8 only
jeremy authored
75
029952e Nick Sieger Extract a base class for connection pools, start to flesh out reserve/re...
nicksieger authored
76 # The cache of reserved connections mapped to threads
77 @reserved_connections = {}
dd77733 Jeremy Kemper Timeout the connection pool monitor on ruby 1.8 only
jeremy authored
78
c606fe2 Aaron Patterson push synchronization in to each method. Reduces method calls and makes
tenderlove authored
79 @queue = new_cond
2a04110 fix ruby 1.9 deadlock problem, fixes #5736 add connection pool tests
Hemant Kumar authored
80 @timeout = spec.config[:wait_timeout] || 5
dd77733 Jeremy Kemper Timeout the connection pool monitor on ruby 1.8 only
jeremy authored
81
8e5e02b Nick Sieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
82 # default max pool size to 5
83 @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
84
7db90aa Jon Leighton Make it the responsibility of the connection to hold onto an ARel visito...
jonleighton authored
85 @connections = []
acccb72 Aaron Patterson column cache now lives on the connection pool
tenderlove authored
86 @automatic_reconnect = true
c94651f Aaron Patterson almost fisted
tenderlove authored
87 end
88
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
89 # Retrieve the connection associated with the current thread, or call
90 # #checkout to obtain one if necessary.
91 #
92 # #connection can be called any number of times; the connection is
93 # held in a hash keyed by the thread id.
94 def connection
879611f Aaron Patterson Merge pull request #6398 from pmahoney/threadsafe-connection-pool
tenderlove authored
95 synchronize do
96 @reserved_connections[current_connection_id] ||= checkout
97 end
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
98 end
99
cff19cf Aaron Patterson make active_connection? return true only if there is an open connection ...
tenderlove authored
100 # Is there an open connection that is being used for the current thread?
4211866 Aaron Patterson adding active_connection? to the connection pool
tenderlove authored
101 def active_connection?
879611f Aaron Patterson Merge pull request #6398 from pmahoney/threadsafe-connection-pool
tenderlove authored
102 synchronize do
103 @reserved_connections.fetch(current_connection_id) {
104 return false
105 }.in_use?
106 end
4211866 Aaron Patterson adding active_connection? to the connection pool
tenderlove authored
107 end
108
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
109 # 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
110 # #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
111 # 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
112 def release_connection(with_id = current_connection_id)
113 conn = @reserved_connections.delete(with_id)
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
114 checkin conn if conn
115 end
116
0034b78 Sebastian Martinez Remove extra white spaces on ActiveRecord docs.
smartinez87 authored
117 # 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
118 # 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
119 # connection when finished.
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
120 def with_connection
3344520 Aaron Patterson reduce the number of times current_connection_id is called in with_conne...
tenderlove authored
121 connection_id = current_connection_id
ce3d8d6 Aaron Patterson Start implementing @reserved_connections in terms of connection leases.
tenderlove authored
122 fresh_connection = true unless active_connection?
5501b99 coderrr Ensure ActiveRecord::Base.connection_pool.with_connection creates a new ...
coderrr authored
123 yield connection
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
124 ensure
3344520 Aaron Patterson reduce the number of times current_connection_id is called in with_conne...
tenderlove authored
125 release_connection(connection_id) if fresh_connection
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
126 end
127
029952e Nick Sieger Extract a base class for connection pools, start to flesh out reserve/re...
nicksieger authored
128 # Returns true if a connection has already been opened.
129 def connected?
c606fe2 Aaron Patterson push synchronization in to each method. Reduces method calls and makes
tenderlove authored
130 synchronize { @connections.any? }
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
131 end
132
a293278 Pratik Merge docrails
lifo authored
133 # 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
134 def disconnect!
c606fe2 Aaron Patterson push synchronization in to each method. Reduces method calls and makes
tenderlove authored
135 synchronize do
136 @reserved_connections = {}
137 @connections.each do |conn|
138 checkin conn
139 conn.disconnect!
140 end
141 @connections = []
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
142 end
143 end
144
8f1b141 Sebastian Martinez Fixed punctuation errors.
smartinez87 authored
145 # Clears the cache which maps classes.
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
146 def clear_reloadable_connections!
c606fe2 Aaron Patterson push synchronization in to each method. Reduces method calls and makes
tenderlove authored
147 synchronize do
148 @reserved_connections = {}
149 @connections.each do |conn|
150 checkin conn
151 conn.disconnect! if conn.requires_reloading?
152 end
153 @connections.delete_if do |conn|
154 conn.requires_reloading?
155 end
62c4e4d Edgars Beigarts Fix connection reloading in development mode. [#4929 state:resolved]
ebeigarts authored
156 end
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
157 end
158
817a07b Nick Sieger More doco and class/method renames. Now have a strategy for integration ...
nicksieger authored
159 # Verify active connections and remove and disconnect connections
160 # associated with stale threads.
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
161 def verify_active_connections! #:nodoc:
c606fe2 Aaron Patterson push synchronization in to each method. Reduces method calls and makes
tenderlove authored
162 synchronize do
163 clear_stale_cached_connections!
164 @connections.each do |connection|
165 connection.verify!
166 end
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
167 end
168 end
169
bd2f5c0 Aaron Patterson pushing caching and visitors down to the connection
tenderlove authored
170 def columns
171 with_connection do |c|
172 c.schema_cache.columns
173 end
174 end
175 deprecate :columns
176
177 def columns_hash
178 with_connection do |c|
179 c.schema_cache.columns_hash
180 end
181 end
182 deprecate :columns_hash
183
184 def primary_keys
185 with_connection do |c|
186 c.schema_cache.primary_keys
187 end
188 end
189 deprecate :primary_keys
190
191 def clear_cache!
192 with_connection do |c|
193 c.schema_cache.clear!
194 end
195 end
196 deprecate :clear_cache!
197
d07a6b1 Nick Sieger Make clear_active_connections! also return stale connections back to the...
nicksieger authored
198 # Return any checked-out connections back to the pool by threads that
199 # are no longer alive.
200 def clear_stale_cached_connections!
42be67e Aaron Patterson unfactoring clear_stale_cached_connections!
tenderlove authored
201 keys = @reserved_connections.keys - Thread.list.find_all { |t|
202 t.alive?
203 }.map { |thread| thread.object_id }
204 keys.each do |key|
0e2477b Aaron Patterson Automatic closure of connections in threads is deprecated. For example
tenderlove authored
205 conn = @reserved_connections[key]
206 ActiveSupport::Deprecation.warn(<<-eowarn) if conn.in_use?
207 Database connections will not be closed automatically, please close your
208 database connection at the end of the thread by calling `close` on your
209 connection. For example: ActiveRecord::Base.connection.close
210 eowarn
211 checkin conn
42be67e Aaron Patterson unfactoring clear_stale_cached_connections!
tenderlove authored
212 @reserved_connections.delete(key)
d07a6b1 Nick Sieger Make clear_active_connections! also return stale connections back to the...
nicksieger authored
213 end
214 end
215
a293278 Pratik Merge docrails
lifo authored
216 # Check-out a database connection from the pool, indicating that you want
217 # to use it. You should call #checkin when you no longer need this.
218 #
219 # This is done by either returning an existing connection, or by creating
220 # a new connection. If the maximum number of connections for this pool has
221 # already been reached, but the pool is empty (i.e. they're all being used),
222 # then this method will wait until a thread has checked in a connection.
223 # The wait time is bounded however: if no connection can be checked out
224 # within the timeout specified for this pool, then a ConnectionTimeoutError
225 # exception will be raised.
226 #
227 # Returns: an AbstractAdapter object.
228 #
229 # Raises:
230 # - ConnectionTimeoutError: no connection can be obtained from the pool
231 # within the timeout period.
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
232 def checkout
c606fe2 Aaron Patterson push synchronization in to each method. Reduces method calls and makes
tenderlove authored
233 synchronize do
41563b4 Jonathan Rochkind ConnectionPool.checkout takes account of ruby using 'non-blocking condit...
jrochkind authored
234 waited_time = 0
235
21eb18a Aliaksey Kandratsenka (aka Aliaksei Kandratsenka) Fix race in ConnectionPool#checkout
alk authored
236 loop do
b72b477 Aaron Patterson Use connection lease to determine "checked_out" connections
tenderlove authored
237 conn = @connections.find { |c| c.lease }
238
239 unless conn
240 if @connections.size < @size
241 conn = checkout_new_connection
242 conn.lease
243 end
244 end
245
246 if conn
247 checkout_and_verify conn
248 return conn
249 end
2a04110 fix ruby 1.9 deadlock problem, fixes #5736 add connection pool tests
Hemant Kumar authored
250
41563b4 Jonathan Rochkind ConnectionPool.checkout takes account of ruby using 'non-blocking condit...
jrochkind authored
251 if waited_time >= @timeout
252 raise ConnectionTimeoutError, "could not obtain a database connection#{" within #{@timeout} seconds" if @timeout} (waited #{waited_time} seconds). The max pool size is currently #{@size}; consider increasing it."
253 end
254
255 # Sometimes our wait can end because a connection is available,
256 # but another thread can snatch it up first. If timeout hasn't
257 # passed but no connection is avail, looks like that happened --
258 # loop and wait again, for the time remaining on our timeout.
259 before_wait = Time.now
260 @queue.wait( [@timeout - waited_time, 0].max )
261 waited_time += (Time.now - before_wait)
2a04110 fix ruby 1.9 deadlock problem, fixes #5736 add connection pool tests
Hemant Kumar authored
262
41563b4 Jonathan Rochkind ConnectionPool.checkout takes account of ruby using 'non-blocking condit...
jrochkind authored
263 # Will go away in Rails 4, when we don't clean up
264 # after leaked connections automatically anymore. Right now, clean
265 # up after we've returned from a 'wait' if it looks like it's
266 # needed, then loop and try again.
267 if(active_connections.size >= @connections.size)
8343611 Aliaksey Kandratsenka (aka Aliaksei Kandratsenka) made ConnectionPool#checkout more robust by trying to loot dead threads ...
alk authored
268 clear_stale_cached_connections!
21eb18a Aliaksey Kandratsenka (aka Aliaksei Kandratsenka) Fix race in ConnectionPool#checkout
alk authored
269 end
8e5e02b Nick Sieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
270 end
271 end
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
272 end
273
a293278 Pratik Merge docrails
lifo authored
274 # Check-in a database connection back into the pool, indicating that you
275 # no longer need this connection.
276 #
277 # +conn+: an AbstractAdapter object, which was obtained by earlier by
278 # calling +checkout+ on this pool.
8e5e02b Nick Sieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
279 def checkin(conn)
c606fe2 Aaron Patterson push synchronization in to each method. Reduces method calls and makes
tenderlove authored
280 synchronize do
57bc25c John Firebaugh Use run_callbacks; the generated _run_<name>_callbacks method is not a p...
jfirebaugh authored
281 conn.run_callbacks :checkin do
b72b477 Aaron Patterson Use connection lease to determine "checked_out" connections
tenderlove authored
282 conn.expire
471a394 Nick Sieger Modify connection pool callbacks to be compatible w/ new style
nicksieger authored
283 @queue.signal
284 end
5f26ce6 Aaron Patterson make sure connections returned after close are marked as in_use
tenderlove authored
285
286 release conn
8e5e02b Nick Sieger Collapse connection pool class hierarchy; YAGNI.
nicksieger authored
287 end
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
288 end
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
289
290 private
7db90aa Jon Leighton Make it the responsibility of the connection to hold onto an ARel visito...
jonleighton authored
291
5f26ce6 Aaron Patterson make sure connections returned after close are marked as in_use
tenderlove authored
292 def release(conn)
e663aa3 Synchronize the ConnectionPool#release method to avoid thread safety iss...
Andrew Selder authored
293 synchronize do
294 thread_id = nil
295
296 if @reserved_connections[current_connection_id] == conn
297 thread_id = current_connection_id
298 else
299 thread_id = @reserved_connections.keys.find { |k|
300 @reserved_connections[k] == conn
301 }
302 end
5f26ce6 Aaron Patterson make sure connections returned after close are marked as in_use
tenderlove authored
303
e663aa3 Synchronize the ConnectionPool#release method to avoid thread safety iss...
Andrew Selder authored
304 @reserved_connections.delete thread_id if thread_id
305 end
5f26ce6 Aaron Patterson make sure connections returned after close are marked as in_use
tenderlove authored
306 end
307
fe575dd Nick Sieger Nearing the finish line. Initial fixed-size connection pool implemented,...
nicksieger authored
308 def new_connection
bd2f5c0 Aaron Patterson pushing caching and visitors down to the connection
tenderlove authored
309 ActiveRecord::Base.send(spec.adapter_method, spec.config)
fe575dd Nick Sieger Nearing the finish line. Initial fixed-size connection pool implemented,...
nicksieger authored
310 end
311
d07a6b1 Nick Sieger Make clear_active_connections! also return stale connections back to the...
nicksieger authored
312 def current_connection_id #:nodoc:
f41b58d Mark J. Titorenko use thread locals and an instance variable within QueryCache#BodyProxy t...
mjtko authored
313 ActiveRecord::Base.connection_id ||= Thread.current.object_id
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
314 end
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
315
fe575dd Nick Sieger Nearing the finish line. Initial fixed-size connection pool implemented,...
nicksieger authored
316 def checkout_new_connection
acccb72 Aaron Patterson column cache now lives on the connection pool
tenderlove authored
317 raise ConnectionNotEstablished unless @automatic_reconnect
318
fe575dd Nick Sieger Nearing the finish line. Initial fixed-size connection pool implemented,...
nicksieger authored
319 c = new_connection
29d2040 Aaron Patterson AbstractAdapter#close can be called to add the connection back to the
tenderlove authored
320 c.pool = self
fe575dd Nick Sieger Nearing the finish line. Initial fixed-size connection pool implemented,...
nicksieger authored
321 @connections << c
b72b477 Aaron Patterson Use connection lease to determine "checked_out" connections
tenderlove authored
322 c
a96b7d4 Nick Sieger Add connection reset and verification upon each connection checkout
nicksieger authored
323 end
324
325 def checkout_and_verify(c)
471a394 Nick Sieger Modify connection pool callbacks to be compatible w/ new style
nicksieger authored
326 c.run_callbacks :checkout do
327 c.verify!
328 end
fe575dd Nick Sieger Nearing the finish line. Initial fixed-size connection pool implemented,...
nicksieger authored
329 c
330 end
b72b477 Aaron Patterson Use connection lease to determine "checked_out" connections
tenderlove authored
331
5725e39 Aaron Patterson Rename `checked_out` to more descriptive `active_connections`
tenderlove authored
332 def active_connections
b72b477 Aaron Patterson Use connection lease to determine "checked_out" connections
tenderlove authored
333 @connections.find_all { |c| c.in_use? }
334 end
fe575dd Nick Sieger Nearing the finish line. Initial fixed-size connection pool implemented,...
nicksieger authored
335 end
336
a293278 Pratik Merge docrails
lifo authored
337 # 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
338 # for keeping separate connection pools for Active Record models that connect
a293278 Pratik Merge docrails
lifo authored
339 # to different databases.
340 #
341 # For example, suppose that you have 5 models, with the following hierarchy:
342 #
343 # |
344 # +-- Book
345 # | |
346 # | +-- ScaryBook
347 # | +-- GoodBook
348 # +-- Author
349 # +-- BankAccount
350 #
351 # Suppose that Book is to connect to a separate database (i.e. one other
352 # than the default database). Then Book, ScaryBook and GoodBook will all use
353 # the same connection pool. Likewise, Author and BankAccount will use the
354 # same connection pool. However, the connection pool used by Author/BankAccount
355 # is not the same as the one used by Book/ScaryBook/GoodBook.
356 #
357 # 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
358 # ActiveRecord::Base.connection_handler. Active Record models use this to
a293278 Pratik Merge docrails
lifo authored
359 # determine that connection pool that they should use.
ca6d717 Nick Sieger Deprecate allow_concurrency and make it have no effect
nicksieger authored
360 class ConnectionHandler
b952470 Aaron Patterson use an attr_reader for performance
tenderlove authored
361 attr_reader :connection_pools
362
72d959d Nick Sieger Split connection handler into single- and multiple-thread versions.
nicksieger authored
363 def initialize(pools = {})
364 @connection_pools = pools
ffb218c Aaron Patterson pools are 1:1 with spec now rather than 1:1 with class
tenderlove authored
365 @class_to_pool = {}
72d959d Nick Sieger Split connection handler into single- and multiple-thread versions.
nicksieger authored
366 end
ff97e9d Nick Sieger Connection handling methods extracted out into separate ConnectionHandle...
nicksieger authored
367
368 def establish_connection(name, spec)
ffb218c Aaron Patterson pools are 1:1 with spec now rather than 1:1 with class
tenderlove authored
369 @connection_pools[spec] ||= ConnectionAdapters::ConnectionPool.new(spec)
370 @class_to_pool[name] = @connection_pools[spec]
ff97e9d Nick Sieger Connection handling methods extracted out into separate ConnectionHandle...
nicksieger authored
371 end
372
25f9497 Aaron Patterson adding active_connections? to the connection pool for finding open conne...
tenderlove authored
373 # Returns true if there are any active connections among the connection
374 # pools that the ConnectionHandler is managing.
375 def active_connections?
376 connection_pools.values.any? { |pool| pool.active_connection? }
377 end
378
bb8f4c2 Jonathan Rochkind inline docs for clear_active_connections! no longer says it cleans dead ...
jrochkind authored
379 # Returns any connections in use by the current thread back to the pool.
ff97e9d Nick Sieger Connection handling methods extracted out into separate ConnectionHandle...
nicksieger authored
380 def clear_active_connections!
529c271 Nick Sieger Simplify dispatcher callbacks to eliminate unnecessary stale thread purg...
nicksieger authored
381 @connection_pools.each_value {|pool| pool.release_connection }
ff97e9d Nick Sieger Connection handling methods extracted out into separate ConnectionHandle...
nicksieger authored
382 end
383
8f1b141 Sebastian Martinez Fixed punctuation errors.
smartinez87 authored
384 # Clears the cache which maps classes.
ff97e9d Nick Sieger Connection handling methods extracted out into separate ConnectionHandle...
nicksieger authored
385 def clear_reloadable_connections!
386 @connection_pools.each_value {|pool| pool.clear_reloadable_connections! }
387 end
388
389 def clear_all_connections!
72d959d Nick Sieger Split connection handler into single- and multiple-thread versions.
nicksieger authored
390 @connection_pools.each_value {|pool| pool.disconnect! }
ff97e9d Nick Sieger Connection handling methods extracted out into separate ConnectionHandle...
nicksieger authored
391 end
392
393 # Verify active connections.
394 def verify_active_connections! #:nodoc:
817a07b Nick Sieger More doco and class/method renames. Now have a strategy for integration ...
nicksieger authored
395 @connection_pools.each_value {|pool| pool.verify_active_connections! }
ff97e9d Nick Sieger Connection handling methods extracted out into separate ConnectionHandle...
nicksieger authored
396 end
397
398 # Locate the connection of the nearest super class. This can be an
399 # active or defined connection: if it is the latter, it will be
400 # opened and set as the active connection for the class it was defined
401 # for (not necessarily the current class).
402 def retrieve_connection(klass) #:nodoc:
403 pool = retrieve_connection_pool(klass)
404 (pool && pool.connection) or raise ConnectionNotEstablished
405 end
406
82fcd9d Nick Sieger Clean up the code, get rid of reserve/release, add some more docs
nicksieger authored
407 # Returns true if a connection that's accessible to this class has
408 # already been opened.
ff97e9d Nick Sieger Connection handling methods extracted out into separate ConnectionHandle...
nicksieger authored
409 def connected?(klass)
0832bc6 Pratik Make sure ActiveRecord::Base.connected? doesn't raise an exception for d...
lifo authored
410 conn = retrieve_connection_pool(klass)
a4458f5 Aaron Patterson removing useless ternary
tenderlove authored
411 conn && conn.connected?
ff97e9d Nick Sieger Connection handling methods extracted out into separate ConnectionHandle...
nicksieger authored
412 end
413
414 # Remove the connection for this class. This will close the active
415 # connection and the defined connection (if they exist). The result
416 # can be used as an argument for establish_connection, for easily
417 # re-establishing the connection.
418 def remove_connection(klass)
ffb218c Aaron Patterson pools are 1:1 with spec now rather than 1:1 with class
tenderlove authored
419 pool = @class_to_pool.delete(klass.name)
04ef434 Aaron Patterson only test for existence of +pool+ once
tenderlove authored
420 return nil unless pool
421
ffb218c Aaron Patterson pools are 1:1 with spec now rather than 1:1 with class
tenderlove authored
422 @connection_pools.delete pool.spec
acccb72 Aaron Patterson column cache now lives on the connection pool
tenderlove authored
423 pool.automatic_reconnect = false
04ef434 Aaron Patterson only test for existence of +pool+ once
tenderlove authored
424 pool.disconnect!
425 pool.spec.config
ff97e9d Nick Sieger Connection handling methods extracted out into separate ConnectionHandle...
nicksieger authored
426 end
427
fe575dd Nick Sieger Nearing the finish line. Initial fixed-size connection pool implemented,...
nicksieger authored
428 def retrieve_connection_pool(klass)
ffb218c Aaron Patterson pools are 1:1 with spec now rather than 1:1 with class
tenderlove authored
429 pool = @class_to_pool[klass.name]
3007545 Nick Sieger Minor tweak to retrieve_connection_pool -- recurse instead of loop
nicksieger authored
430 return pool if pool
431 return nil if ActiveRecord::Base == klass
432 retrieve_connection_pool klass.superclass
fe575dd Nick Sieger Nearing the finish line. Initial fixed-size connection pool implemented,...
nicksieger authored
433 end
72d959d Nick Sieger Split connection handler into single- and multiple-thread versions.
nicksieger authored
434 end
1b22071 Joshua Peek Ensure ActiveRecord session store's connections are checked in after eac...
josh authored
435
436 class ConnectionManagement
e524609 Aaron Patterson proxy body responses so we close database connections after body is flus...
tenderlove authored
437 class Proxy # :nodoc:
438 attr_reader :body, :testing
439
440 def initialize(body, testing = false)
441 @body = body
442 @testing = testing
443 end
444
5044420 Steve Hodgkiss Fix inconsistencies by being polite to the wrapped body. Needed for Rack...
stevehodgkiss authored
445 def method_missing(method_sym, *arguments, &block)
446 @body.send(method_sym, *arguments, &block)
447 end
448
449 def respond_to?(method_sym, include_private = false)
450 super || @body.respond_to?(method_sym)
451 end
452
e524609 Aaron Patterson proxy body responses so we close database connections after body is flus...
tenderlove authored
453 def each(&block)
454 body.each(&block)
455 end
456
457 def close
458 body.close if body.respond_to?(:close)
459
460 # Don't return connection (and perform implicit rollback) if
461 # this request is a part of integration test
462 ActiveRecord::Base.clear_active_connections! unless testing
463 end
464 end
465
1b22071 Joshua Peek Ensure ActiveRecord session store's connections are checked in after eac...
josh authored
466 def initialize(app)
467 @app = app
468 end
469
470 def call(env)
c7b7c6a Aaron Patterson make sure that active connections are not cleared during test when an ex...
tenderlove authored
471 testing = env.key?('rack.test')
472
e524609 Aaron Patterson proxy body responses so we close database connections after body is flus...
tenderlove authored
473 status, headers, body = @app.call(env)
474
c7b7c6a Aaron Patterson make sure that active connections are not cleared during test when an ex...
tenderlove authored
475 [status, headers, Proxy.new(body, testing)]
3b2a032 Aaron Patterson clearing active connections in the ConnectionManagement middleware if an...
tenderlove authored
476 rescue
c7b7c6a Aaron Patterson make sure that active connections are not cleared during test when an ex...
tenderlove authored
477 ActiveRecord::Base.clear_active_connections! unless testing
3b2a032 Aaron Patterson clearing active connections in the ConnectionManagement middleware if an...
tenderlove authored
478 raise
1b22071 Joshua Peek Ensure ActiveRecord session store's connections are checked in after eac...
josh authored
479 end
480 end
6edaa26 Nick Sieger Initial conversion to connection pool
nicksieger authored
481 end
21eb18a Aliaksey Kandratsenka (aka Aliaksei Kandratsenka) Fix race in ConnectionPool#checkout
alk authored
482 end
Something went wrong with that request. Please try again.