Class: Sequel::Mysql2::Synchrony::ConnectionPool
- Inherits:
-
ConnectionPool
- Object
- ConnectionPool
- Sequel::Mysql2::Synchrony::ConnectionPool
- Defined in:
- lib/my-sequel-synchrony/connection_pool.rb
Overview
A Fiber-aware Sequel::ConnectionPool that works with EM::Synchrony! This version is not shard-aware.
Constant Summary collapse
- DEFAULT_MAX_SIZE =
4
Instance Attribute Summary collapse
-
#max_size ⇒ Object
readonly
The maximum number of connections this pool will create (per shard/server if sharding).
Instance Method Summary collapse
-
#disconnect(opts = {}, &block) ⇒ Object
Removes all connections currently available, optionally yielding each connection to the given block.
-
#hold(server = nil) ⇒ Object
Chooses the first available connection, or if none are available, creates a new connection.
-
#initialize(opts = {}, &block) ⇒ ConnectionPool
constructor
The following additional options are respected: * :connection_handling - Set how to handle available connections.
-
#size ⇒ Object
The total number of open connections, either available or in-use.
Constructor Details
#initialize(opts = {}, &block) ⇒ ConnectionPool
The following additional options are respected:
-
:connection_handling - Set how to handle available connections. By default, uses a a stack for performance. Can be set to :queue to use a queue, which reduces the chances of connections becoming stale. Can also be set to :disconnect, which will disconnect after every query or transaction.
-
:max_connections - The maximum number of connections the connection pool will open (default 4)
23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/my-sequel-synchrony/connection_pool.rb', line 23 def initialize(opts = {}, &block) super @max_size = Integer(opts[:max_connections] || DEFAULT_MAX_SIZE) raise(Sequel::Error, ':max_connections must be positive') if @max_size < 1 @connection_handling = opts[:connection_handling] @available_connections = [] @waiting_fibers = [] @in_use_connections = {} @pending_disconnects = Set.new # TODO(ilyam): remove the debug prints once this is rock-solid and has good tests etc. @debug = opts[:debug] end |
Instance Attribute Details
#max_size ⇒ Object (readonly)
The maximum number of connections this pool will create (per shard/server if sharding).
11 12 13 |
# File 'lib/my-sequel-synchrony/connection_pool.rb', line 11 def max_size @max_size end |
Instance Method Details
#disconnect(opts = {}, &block) ⇒ Object
Removes all connections currently available, 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. Schedules all in-use connections to be disconnected next time they are released into the available pool.
After a disconnect, when connections are requested using #hold, the connection pool will create new connections to the database.
49 50 51 52 53 54 55 56 57 |
# File 'lib/my-sequel-synchrony/connection_pool.rb', line 49 def disconnect(opts={}, &block) if_debug? { dputs "disconnect(opts = #{opts.inspect})! Current fiber = #{Fiber.current.inspect}" } connections_to_disconnect, @available_connections = @available_connections, [] @pending_disconnects += @in_use_connections.values.to_set block ||= @disconnection_proc connections_to_disconnect.each do |conn| disconnect_conn(conn, opts, &block) end end |
#hold(server = nil) ⇒ 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 is re-entrant, meaning it can be called recursively in the same fiber safely.
If no connection is immediately available and the pool is already using the maximum number of connections, Pool#hold will block the current fiber until a connection is available.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/my-sequel-synchrony/connection_pool.rb', line 71 def hold(server = nil) if_debug? { dputs "hold(server = #{server.inspect})! Current fiber = #{Fiber.current.inspect}" } fiber, conn = Fiber.current, nil if conn = @in_use_connections[fiber] return yield(conn) end begin conn = acquire(fiber) yield conn rescue Sequel::DatabaseDisconnectError => error disconnect_conn(conn) if conn conn = nil @in_use_connections.delete(fiber) resume_next_waiting_fiber raise error ensure release(fiber) if conn end end |
#size ⇒ Object
The total number of open connections, either available or in-use.
37 38 39 |
# File 'lib/my-sequel-synchrony/connection_pool.rb', line 37 def size @in_use_connections.size + @available_connections.size end |