class Async::HTTP::Pool
#reusable? -> can be used again.
#multiplex -> 1 or more.
Resources must respond to
This pool doesn’t impose a maximum number of open resources, but it WILL block if there are no available resources and trying to allocate another one fails.
In general we don’t know the policy until connection is established.
- Multiplex requests per connection (HTTP2)
- Multiple sequential requests per connection (HTTP1 with keep-alive)
- Single request per connection (HTTP/1 without keep-alive)
Pool behaviours
def acquire
def acquire resource = wait_for_next_available return resource unless block_given? begin yield resource ensure release(resource) end end
def close
def close @available.each_key(&:close) @available.clear end
def create
def create # This might return nil, which means creating the resource failed. if resource = @constructor.call @available[resource] = 1 end return resource end
def empty?
def empty? @available.empty? end
def initialize(limit = nil, &block)
def initialize(limit = nil, &block) @available = {} # resource => count @waiting = [] @limit = limit @constructor = block end
def next_available
def next_available @available.each do |resource, count| if count < resource.multiplex # We want to use this resource... but is it good? if resource.good? @available[resource] += 1 return resource else retire(resource) end end end if !@limit or @available.count < @limit Async.logger.debug(self) {"No available resources, allocating new one..."} return create end end
def release(resource)
def release(resource) # A resource that is not good should also not be reusable. if resource.reusable? reuse(resource) else retire(resource) end end
def retire(resource)
def retire(resource) Async.logger.debug(self) {"Retire #{resource}"} @available.delete(resource) resource.close end
def reuse(resource)
def reuse(resource) Async.logger.debug(self) {"Reuse #{resource}"} @available[resource] -= 1 if task = @waiting.pop task.resume end end
def wait_for_next_available
def wait_for_next_available # If we fail to create a resource (below), we will end up waiting for one to become available. until resource = next_available @waiting << Fiber.current Task.yield end return resource end