Class: PgHelper::ConnectionPool

Inherits:
Object
  • Object
show all
Includes:
MonitorMixin
Defined in:
lib/pg_helper/connection_pool.rb

Defined Under Namespace

Classes: Queue

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts) ⇒ ConnectionPool

all opts but :checkout_timeout, :pool, :auto_connect will be passed to PGConn.new



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/pg_helper/connection_pool.rb', line 164

def initialize(opts)
  super()

  connection_opts = opts.dup
  @checkout_timeout = opts.delete(:checkout_timeout) || 5
  @size = opts.delete(:pool) || 5
  @auto_connect = opts.delete(:auto_connect) || true

  @connection_options = connection_opts

  # The cache of reserved connections mapped to threads
  @reserved_connections = ThreadSafe::Cache.new(initial_capacity: @size)

  @connections         = []

  @available = Queue.new self
end

Instance Attribute Details

#auto_connectObject

Returns the value of attribute auto_connect.



160
161
162
# File 'lib/pg_helper/connection_pool.rb', line 160

def auto_connect
  @auto_connect
end

#checkout_timeoutObject

Returns the value of attribute checkout_timeout.



160
161
162
# File 'lib/pg_helper/connection_pool.rb', line 160

def checkout_timeout
  @checkout_timeout
end

#connection_optionsObject (readonly)

Returns the value of attribute connection_options.



161
162
163
# File 'lib/pg_helper/connection_pool.rb', line 161

def connection_options
  @connection_options
end

#connectionsObject (readonly)

Returns the value of attribute connections.



161
162
163
# File 'lib/pg_helper/connection_pool.rb', line 161

def connections
  @connections
end

#sizeObject (readonly)

Returns the value of attribute size.



161
162
163
# File 'lib/pg_helper/connection_pool.rb', line 161

def size
  @size
end

Instance Method Details

#active_connection?Boolean

Is there an open connection that is being used for the current thread?

Returns:

  • (Boolean)


196
197
198
199
200
201
202
# File 'lib/pg_helper/connection_pool.rb', line 196

def active_connection?
  synchronize do
    @reserved_connections.fetch(current_connection_id) do
      return false
    end
  end
end

#checkin(conn) ⇒ Object

Check-in a database connection back into the pool, indicating that you no longer need this connection.

conn: an AbstractAdapter object, which was obtained by earlier by calling checkout on this pool.



287
288
289
290
291
292
# File 'lib/pg_helper/connection_pool.rb', line 287

def checkin(conn)
  synchronize do
    release conn
    @available.add conn
  end
end

#checkoutObject

Check-out a database connection from the pool, indicating that you want to use it. You should call #checkin when you no longer need this.

This is done by either returning and leasing existing connection, or by creating a new connection and leasing it.

If all connections are leased and the pool is at capacity (meaning the number of currently leased connections is greater than or equal to the size limit set), an ActiveRecord::ConnectionTimeoutError exception will be raised.

Returns: an AbstractAdapter object.

Raises:

  • ConnectionTimeoutError: no connection can be obtained from the pool.



275
276
277
278
279
280
# File 'lib/pg_helper/connection_pool.rb', line 275

def checkout
  synchronize do
    conn = acquire_connection
    checkout_and_verify(conn)
  end
end

#clear_reloadable_connections!Object

Clears the cache which maps classes.



245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/pg_helper/connection_pool.rb', line 245

def clear_reloadable_connections!
  synchronize do
    @reserved_connections.clear
    @connections.each do |conn|
      checkin conn
    end

    @connections.delete_if(&:finished?)

    @available.clear
    @connections.each do |conn|
      @available.add conn
    end
  end
end

#connected?Boolean

Returns true if a connection has already been opened.

Returns:

  • (Boolean)


226
227
228
# File 'lib/pg_helper/connection_pool.rb', line 226

def connected?
  synchronize { @connections.any? }
end

#connectionObject

Retrieve the connection associated with the current thread, or call #checkout to obtain one if necessary.

#connection can be called any number of times; the connection is held in a hash keyed by the thread id.



187
188
189
190
191
192
193
# File 'lib/pg_helper/connection_pool.rb', line 187

def connection
  # this is correctly done double-checked locking
  # (ThreadSafe::Cache's lookups have volatile semantics)
  @reserved_connections[current_connection_id] || synchronize do
    @reserved_connections[current_connection_id] ||= checkout
  end
end

#disconnect!Object

Disconnects all connections in the pool, and clears the pool.



231
232
233
234
235
236
237
238
239
240
241
242
# File 'lib/pg_helper/connection_pool.rb', line 231

def disconnect!
  synchronize do
    @reserved_connections.clear
    @connections.each do |conn|
      checkin conn
      $DEBUG && warn("Closing pg connection: #{conn.object_id}")
      conn.close
    end
    @connections = []
    @available.clear
  end
end

#release_connection(with_id = current_connection_id) ⇒ Object

Signal that the thread is finished with the current connection. #release_connection releases the connection-thread association and returns the connection to the pool.



207
208
209
210
211
212
# File 'lib/pg_helper/connection_pool.rb', line 207

def release_connection(with_id = current_connection_id)
  synchronize do
    conn = @reserved_connections.delete(with_id)
    checkin conn if conn
  end
end

#with_connectionObject

If a connection already exists yield it to the block. If no connection exists checkout a connection, yield it to the block, and checkin the connection when finished.



217
218
219
220
221
222
223
# File 'lib/pg_helper/connection_pool.rb', line 217

def with_connection
  connection_id = current_connection_id
  fresh_connection = true unless active_connection?
  yield connection
ensure
  release_connection(connection_id) if fresh_connection
end