Class: Sequel::ConnectionPool

Inherits:
Object
  • Object
show all
Defined in:
lib/sequel_core/connection_pool.rb

Overview

A ConnectionPool manages access to database connections by keeping multiple connections and giving threads exclusive access to each connection.

Instance Attribute Summary collapse

Instance Method Summary collapse

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_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)



50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/sequel_core/connection_pool.rb', line 50

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
  @convert_exceptions = opts.include?(:pool_convert_exceptions) ? opts[:pool_convert_exceptions] : true
end

Instance Attribute Details

#allocatedObject (readonly)

A hash of connections currently being used, key is the Thread, value is the connection.



7
8
9
# File 'lib/sequel_core/connection_pool.rb', line 7

def allocated
  @allocated
end

#available_connectionsObject (readonly)

An array of connections opened but not currently used



10
11
12
# File 'lib/sequel_core/connection_pool.rb', line 10

def available_connections
  @available_connections
end

#connection_procObject

The proc used to create a new database connection.



13
14
15
# File 'lib/sequel_core/connection_pool.rb', line 13

def connection_proc
  @connection_proc
end

#created_countObject (readonly) Also known as: size

The total number of connections opened, should be equal to available_connections.length + allocated.length



18
19
20
# File 'lib/sequel_core/connection_pool.rb', line 18

def created_count
  @created_count
end

#max_sizeObject (readonly)

The maximum number of connections.



22
23
24
# File 'lib/sequel_core/connection_pool.rb', line 22

def max_size
  @max_size
end

#mutexObject (readonly)

The mutex that protects access to the other internal vairables. You must use this if you want to manipulate the variables safely.



26
27
28
# File 'lib/sequel_core/connection_pool.rb', line 26

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.



103
104
105
106
107
108
109
# File 'lib/sequel_core/connection_pool.rb', line 103

def disconnect(&block)
  @mutex.synchronize do
    @available_connections.each {|c| block[c]} if block
    @available_connections = []
    @created_count = @allocated.size
  end
end

#holdObject

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 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.



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/sequel_core/connection_pool.rb', line 76

def hold
  begin
    t = Thread.current
    time = Time.new
    timeout = time + @timeout
    sleep_time = @sleep_time
    if conn = owned_connection(t)
      return yield(conn)
    end
    until conn = acquire(t)
      raise(::Sequel::Error::PoolTimeoutError) if Time.new > timeout
      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.message) : e)
  end
end