Class: ConnectionPool
Overview
A ConnectionPool manages access to database connections by keeping multiple connections and giving threads exclusive access to each connection.
Instance Attribute Summary collapse
-
#allocated ⇒ Object
readonly
An array of connections currently being used.
-
#available_connections ⇒ Object
readonly
An array of connections opened but not currently used.
-
#connection_proc ⇒ Object
The proc used to create a new database connection.
-
#created_count ⇒ Object
(also: #size)
readonly
The total number of connections opened, should be equal to available_connections.length + allocated.length.
-
#max_size ⇒ Object
readonly
The maximum number of connections.
-
#mutex ⇒ Object
readonly
The mutex that protects access to the other internal vairables.
Instance Method Summary collapse
-
#disconnect(&block) ⇒ Object
Removes all connection currently available, optionally yielding each connection to the given block.
-
#hold ⇒ Object
Chooses the first available connection, or if none are available, creates a new connection.
-
#initialize(opts = {}, &block) ⇒ ConnectionPool
constructor
Constructs a new pool with a maximum size.
Constructor Details
#initialize(opts = {}, &block) ⇒ ConnectionPool
Constructs a new pool with a maximum size. If a block is supplied, it is used to create new connections as they are needed.
pool = ConnectionPool.new(:max_connections=>10) {MyConnection.new(opts)}
The connection creation proc can be changed at any time by assigning a Proc to pool#connection_proc.
pool = ConnectionPool.new(:max_connections=>10)
pool.connection_proc = proc {MyConnection.new(opts)}
The connection pool takes the following options:
-
:max_connections - The maximum number of connections the connection pool will open (default 4)
-
:pool_convert_exceptions - Whether to convert non-StandardError based exceptions to RuntimeError exceptions (default true)
-
:pool_reuse_connections - Which strategy to follow in regards to reusing connections:
-
:always - Always reuse a connection that belongs to the same thread
-
:allow - Only reuse a connection that belongs to the same thread if another cannot be acquired immediately (default)
-
:last_resort - Only reuse a connection that belongs to the same thread if the pool timeout has expired
-
:never - Never reuse a connection that belongs to the same thread
-
-
:pool_sleep_time - The amount of time to sleep before attempting to acquire a connection again (default 0.001)
-
:pool_timeout - The amount of seconds to wait to acquire a connection before raising a PoolTimeoutError (default 5)
56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/sequel_core/connection_pool.rb', line 56 def initialize(opts = {}, &block) @max_size = opts[:max_connections] || 4 @mutex = Mutex.new @connection_proc = block @available_connections = [] @allocated = [] @created_count = 0 @timeout = opts[:pool_timeout] || 5 @sleep_time = opts[:pool_sleep_time] || 0.001 @reuse_connections = opts[:pool_reuse_connections] || :allow @convert_exceptions = opts.include?(:pool_convert_exceptions) ? opts[:pool_convert_exceptions] : true end |
Instance Attribute Details
#allocated ⇒ Object (readonly)
An array of connections currently being used
6 7 8 |
# File 'lib/sequel_core/connection_pool.rb', line 6 def allocated @allocated end |
#available_connections ⇒ Object (readonly)
An array of connections opened but not currently used
9 10 11 |
# File 'lib/sequel_core/connection_pool.rb', line 9 def available_connections @available_connections end |
#connection_proc ⇒ Object
The proc used to create a new database connection.
12 13 14 |
# File 'lib/sequel_core/connection_pool.rb', line 12 def connection_proc @connection_proc end |
#created_count ⇒ Object (readonly) Also known as: size
The total number of connections opened, should be equal to available_connections.length + allocated.length
17 18 19 |
# File 'lib/sequel_core/connection_pool.rb', line 17 def created_count @created_count end |
#max_size ⇒ Object (readonly)
The maximum number of connections.
21 22 23 |
# File 'lib/sequel_core/connection_pool.rb', line 21 def max_size @max_size end |
#mutex ⇒ Object (readonly)
The mutex that protects access to the other internal vairables. You must use this if you want to manipulate the variables safely.
25 26 27 |
# File 'lib/sequel_core/connection_pool.rb', line 25 def mutex @mutex end |
Instance Method Details
#disconnect(&block) ⇒ Object
Removes all connection currently available, optionally yielding each connection to the given block. This method has the effect of disconnecting from the database. Once a connection is requested using #hold, the connection pool creates new connections to the database.
122 123 124 125 126 127 128 |
# File 'lib/sequel_core/connection_pool.rb', line 122 def disconnect(&block) @mutex.synchronize do @available_connections.each {|c| block[c]} if block @available_connections = [] @created_count = @allocated.size end end |
#hold ⇒ Object
Chooses the first available connection, or if none are available, creates a new connection. Passes the connection to the supplied block:
pool.hold {|conn| conn.execute('DROP TABLE posts')}
Pool#hold can be re-entrant, meaning it can be called recursively in the same thread without blocking if the :pool_reuse_connections option was set to :always or :allow. Depending on the :pool_reuse_connections option you may get the connection currently used by the thread or a new connection.
If no connection is immediately available and the pool is already using the maximum number of connections, Pool#hold will block until a connection is available or the timeout expires. If the timeout expires before a connection can be acquired, a Sequel::Error::PoolTimeoutError is raised.
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/sequel_core/connection_pool.rb', line 85 def hold begin t = Thread.current time = Time.new timeout = time + @timeout sleep_time = @sleep_time reuse = @reuse_connections if (reuse == :always) && (conn = owned_connection(t)) return yield(conn) end reuse = reuse == :allow ? true : false until conn = acquire(t) if reuse && (conn = owned_connection(t)) return yield(conn) end if Time.new > timeout if (@reuse_connections == :last_resort) && (conn = owned_connection(t)) return yield(conn) end raise(::Sequel::Error::PoolTimeoutError) end sleep sleep_time end begin yield conn ensure release(t, conn) end rescue Exception => e raise(@convert_exceptions && !e.is_a?(StandardError) ? RuntimeError.new(e.) : e) end end |