Class: Quicsilver::Client::ConnectionPool
- Inherits:
-
Object
- Object
- Quicsilver::Client::ConnectionPool
- Defined in:
- lib/quicsilver/client/connection_pool.rb
Overview
Thread-safe pool of connected Client instances, keyed by (host, port). Idle connections are reused automatically. Stale ones are evicted at checkout.
Quicsilver::Client.get("example.com", 4433, "/users")
Constant Summary collapse
- DEFAULT_MAX_SIZE =
4- DEFAULT_IDLE_TIMEOUT =
seconds
60
Instance Attribute Summary collapse
-
#idle_timeout ⇒ Object
readonly
Returns the value of attribute idle_timeout.
-
#max_size ⇒ Object
readonly
Returns the value of attribute max_size.
Instance Method Summary collapse
-
#checkin(client) ⇒ Object
Return a Client to the pool.
-
#checkout(hostname, port, **options) ⇒ Object
Check out a connected Client.
-
#close ⇒ Object
Close all clients.
-
#initialize(max_size: DEFAULT_MAX_SIZE, idle_timeout: DEFAULT_IDLE_TIMEOUT) ⇒ ConnectionPool
constructor
A new instance of ConnectionPool.
-
#size(host = nil, port = nil) ⇒ Object
Total clients in the pool, optionally filtered by host:port.
Constructor Details
#initialize(max_size: DEFAULT_MAX_SIZE, idle_timeout: DEFAULT_IDLE_TIMEOUT) ⇒ ConnectionPool
Returns a new instance of ConnectionPool.
16 17 18 19 20 21 |
# File 'lib/quicsilver/client/connection_pool.rb', line 16 def initialize(max_size: DEFAULT_MAX_SIZE, idle_timeout: DEFAULT_IDLE_TIMEOUT) @max_size = max_size @idle_timeout = idle_timeout @pools = {} # "host:port" => [{ client:, checked_out: }] @mutex = Mutex.new end |
Instance Attribute Details
#idle_timeout ⇒ Object (readonly)
Returns the value of attribute idle_timeout.
11 12 13 |
# File 'lib/quicsilver/client/connection_pool.rb', line 11 def idle_timeout @idle_timeout end |
#max_size ⇒ Object (readonly)
Returns the value of attribute max_size.
11 12 13 |
# File 'lib/quicsilver/client/connection_pool.rb', line 11 def max_size @max_size end |
Instance Method Details
#checkin(client) ⇒ Object
Return a Client to the pool.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/quicsilver/client/connection_pool.rb', line 63 def checkin(client) key = "#{client.hostname}:#{client.port}" @mutex.synchronize do entries = @pools[key] return unless entries entry = entries.find { |e| e[:client].equal?(client) } return unless entry if client.connected? entry[:checked_out] = false entry[:last_used] = Time.now else entries.delete(entry) client.close_connection @pools.delete(key) if entries.empty? end end end |
#checkout(hostname, port, **options) ⇒ Object
Check out a connected Client. Reuses an idle one or creates a new one.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/quicsilver/client/connection_pool.rb', line 24 def checkout(hostname, port, **) key = "#{hostname}:#{port}" @mutex.synchronize do entries = @pools[key] ||= [] # Evict dead/stale/draining entries.reject! do |e| if !e[:checked_out] && (!e[:client].connected? || e[:client].draining? || e[:last_used] < Time.now - @idle_timeout) e[:client].close_connection true end end # Reuse an idle client (skip draining ones) idle = entries.find { |e| !e[:checked_out] && e[:client].connected? && !e[:client].draining? } if idle idle[:checked_out] = true idle[:last_used] = Time.now return idle[:client] end if entries.size >= @max_size raise ConnectionError, "Connection pool full for #{key} (max: #{@max_size})" end end # Create outside the lock (blocking I/O) client = Client.new(hostname, port, **) client.open_connection @mutex.synchronize do (@pools[key] ||= []) << { client: client, checked_out: true, last_used: Time.now } end client end |
#close ⇒ Object
Close all clients.
85 86 87 88 89 90 91 92 |
# File 'lib/quicsilver/client/connection_pool.rb', line 85 def close @mutex.synchronize do @pools.each_value do |entries| entries.each { |e| e[:client].close_connection } end @pools.clear end end |
#size(host = nil, port = nil) ⇒ Object
Total clients in the pool, optionally filtered by host:port.
95 96 97 98 99 100 101 102 103 |
# File 'lib/quicsilver/client/connection_pool.rb', line 95 def size(host = nil, port = nil) @mutex.synchronize do if host && port (@pools["#{host}:#{port}"] || []).size else @pools.values.sum(&:size) end end end |