Class | Sequel::ConnectionPool |
In: |
lib/sequel_core/connection_pool.rb
|
Parent: | Object |
A ConnectionPool manages access to database connections by keeping multiple connections and giving threads exclusive access to each connection.
connection_proc | [RW] | The proc used to create a new database connection. |
disconnection_proc | [RW] | The proc used to disconnect a database connection. |
max_size | [R] | The maximum number of connections. |
mutex | [R] | The mutex that protects access to the other internal vairables. You must use this if you want to manipulate the variables safely. |
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:
# File lib/sequel_core/connection_pool.rb, line 42 42: def initialize(opts = {}, &block) 43: @max_size = opts[:max_connections] || 4 44: @mutex = Mutex.new 45: @connection_proc = block 46: @disconnection_proc = opts[:disconnection_proc] 47: @servers = [:default] 48: @servers += opts[:servers].keys - @servers if opts[:servers] 49: @available_connections = Hash.new{|h,k| h[:default]} 50: @allocated = Hash.new{|h,k| h[:default]} 51: @created_count = Hash.new{|h,k| h[:default]} 52: @servers.each do |s| 53: @available_connections[s] = [] 54: @allocated[s] = {} 55: @created_count[s] = 0 56: end 57: @timeout = opts[:pool_timeout] || 5 58: @sleep_time = opts[:pool_sleep_time] || 0.001 59: @convert_exceptions = opts.include?(:pool_convert_exceptions) ? opts[:pool_convert_exceptions] : true 60: end
A hash of connections currently being used for the given server, key is the Thread, value is the connection.
# File lib/sequel_core/connection_pool.rb, line 64 64: def allocated(server=:default) 65: @allocated[server] 66: end
An array of connections opened but not currently used, for the given server.
# File lib/sequel_core/connection_pool.rb, line 70 70: def available_connections(server=:default) 71: @available_connections[server] 72: end
The total number of connections opened for the given server, should be equal to available_connections.length + allocated.length
# File lib/sequel_core/connection_pool.rb, line 76 76: def created_count(server=:default) 77: @created_count[server] 78: end
Removes all connection currently available on all servers, optionally yielding each connection to the given block. This method has the effect of disconnecting from the database, assuming that no connections are currently being used. Once a connection is requested using hold, the connection pool creates new connections to the database.
# File lib/sequel_core/connection_pool.rb, line 126 126: def disconnect(&block) 127: block ||= @disconnection_proc 128: @mutex.synchronize do 129: @available_connections.each do |server, conns| 130: conns.each{|c| block.call(c)} if block 131: conns.clear 132: set_created_count(server, allocated(server).length) 133: end 134: end 135: end
Chooses the first available connection to the given server, 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 is re-entrant, meaning it can be called recursively in the same thread without blocking.
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.
# File lib/sequel_core/connection_pool.rb, line 95 95: def hold(server=:default) 96: begin 97: t = Thread.current 98: time = Time.new 99: timeout = time + @timeout 100: sleep_time = @sleep_time 101: if conn = owned_connection(t, server) 102: return yield(conn) 103: end 104: until conn = acquire(t, server) 105: raise(::Sequel::Error::PoolTimeoutError) if Time.new > timeout 106: sleep sleep_time 107: end 108: begin 109: yield conn 110: rescue Sequel::DatabaseDisconnectError => dde 111: remove(t, conn, server) 112: raise 113: ensure 114: release(t, conn, server) unless dde 115: end 116: rescue Exception => e 117: raise(@convert_exceptions && !e.is_a?(StandardError) ? RuntimeError.new(e.message) : e) 118: end 119: end