123456789_123456789_123456789_123456789_123456789_

Class: Bundler::ConnectionPool::TimedStack

Relationships & Source Files
Extension / Inclusion / Inheritance Descendants
Subclasses:
Inherits: Object
Defined in: lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb

Overview

Examples:

ts = TimedStack.new(1) { MyConnection.new }

# fetch a connection
conn = ts.pop

# return a connection
ts.push conn

conn = ts.pop
ts.pop timeout: 5
#=> raises Bundler::ConnectionPool::TimeoutError after 5 seconds

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(size = 0, &block) ⇒ TimedStack

Creates a new pool with Bundler::ConnectionPool#size connections that are created from the given block.

[ GitHub ]

  
# File 'lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb', line 27

def initialize(size = 0, &block)
  @create_block = block
  @created = 0
  @que = []
  @max = size
  @mutex = Thread::Mutex.new
  @resource = Thread::ConditionVariable.new
  @shutdown_block = nil
end

Instance Attribute Details

#empty?Boolean (readonly)

Returns true if there are no available connections.

[ GitHub ]

  
# File 'lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb', line 125

def empty?
  (@created - @que.length) >= @max
end

#max (readonly)

[ GitHub ]

  
# File 'lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb', line 21

attr_reader :max

Instance Method Details

#<<(obj, options = {})

Alias for #push.

[ GitHub ]

  
# File 'lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb', line 53

alias_method :<<, :push

#connection_stored?(options = nil) ⇒ Boolean (private)

This is an extension point for TimedStack and is called with a mutex.

This method must returns true if a connection is available on the stack.

[ GitHub ]

  
# File 'lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb', line 153

def connection_stored?(options = nil)
  !@que.empty?
end

#current_time (private)

[ GitHub ]

  
# File 'lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb', line 144

def current_time
  Process.clock_gettime(Process::CLOCK_MONOTONIC)
end

#fetch_connection(options = nil) (private)

This is an extension point for TimedStack and is called with a mutex.

This method must return a connection from the stack.

[ GitHub ]

  
# File 'lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb', line 162

def fetch_connection(options = nil)
  @que.pop&.first
end

#idle

The number of connections created and available on the stack.

[ GitHub ]

  
# File 'lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb', line 138

def idle
  @que.length
end

#idle_connections?(idle_seconds) ⇒ Boolean (private)

This is an extension point for TimedStack and is called with a mutex.

Returns true if the first connection in the stack has been idle for more than idle_seconds

[ GitHub ]

  
# File 'lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb', line 198

def idle_connections?(idle_seconds)
  connection_stored? && (current_time - @que.first.last > idle_seconds)
end

#length

The number of connections available on the stack.

[ GitHub ]

  
# File 'lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb', line 132

def length
  @max - @created + @que.length
end

#pop(timeout = 0.5, options = {})

Retrieves a connection from the stack. If a connection is available it is immediately returned. If no connection is available within the given timeout a TimeoutError is raised.

:timeout is the only checked entry in options and is preferred over the timeout argument (which will be removed in a future release). Other options may be used by subclasses that extend TimedStack.

[ GitHub ]

  
# File 'lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb', line 64

def pop(timeout = 0.5, options = {})
  options, timeout = timeout, 0.5 if Hash === timeout
  timeout = options.fetch :timeout, timeout

  deadline = current_time + timeout
  @mutex.synchronize do
    loop do
      raise Bundler::ConnectionPool::PoolShuttingDownError if @shutdown_block
      return fetch_connection(options) if connection_stored?(options)

      connection = try_create(options)
      return connection if connection

      to_wait = deadline - current_time
      raise Bundler::ConnectionPool::TimeoutError, "Waited #{timeout} sec, #{length}/#{@max} available" if to_wait <= 0
      @resource.wait(@mutex, to_wait)
    end
  end
end

#push(obj, options = {}) Also known as: #<<

Returns obj to the stack. options is ignored in TimedStack but may be used by subclasses that extend TimedStack.

[ GitHub ]

  
# File 'lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb', line 41

def push(obj, options = {})
  @mutex.synchronize do
    if @shutdown_block
      @created -= 1 unless @created == 0
      @shutdown_block.call(obj)
    else
      store_connection obj, options
    end

    @resource.broadcast
  end
end

#reap(idle_seconds, &block)

Reaps connections that were checked in more than idle_seconds ago.

Raises:

  • (ArgumentError)
[ GitHub ]

  
# File 'lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb', line 104

def reap(idle_seconds, &block)
  raise ArgumentError, "reap must receive a block" unless block
  raise ArgumentError, "idle_seconds must be a number" unless idle_seconds.is_a?(Numeric)
  raise Bundler::ConnectionPool::PoolShuttingDownError if @shutdown_block

  idle.times do
    conn =
      @mutex.synchronize do
        raise Bundler::ConnectionPool::PoolShuttingDownError if @shutdown_block

        reserve_idle_connection(idle_seconds)
      end
    break unless conn

    block.call(conn)
  end
end

#reserve_idle_connection(idle_seconds) (private)

This is an extension point for TimedStack and is called with a mutex.

This method returns the oldest idle connection if it has been idle for more than idle_seconds. This requires that the stack is kept in order of checked in time (oldest first).

[ GitHub ]

  
# File 'lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb', line 185

def reserve_idle_connection(idle_seconds)
  return unless idle_connections?(idle_seconds)

  @created -= 1 unless @created == 0

  @que.shift.first
end

#shutdown(reload: false, &block)

Shuts down the TimedStack by passing each connection to block and then removing it from the pool. Attempting to checkout a connection after shutdown will raise PoolShuttingDownError unless :reload is true.

Raises:

  • (ArgumentError)
[ GitHub ]

  
# File 'lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb', line 90

def shutdown(reload: false, &block)
  raise ArgumentError, "shutdown must receive a block" unless block

  @mutex.synchronize do
    @shutdown_block = block
    @resource.broadcast

    shutdown_connections
    @shutdown_block = nil if reload
  end
end

#shutdown_connections(options = nil) (private)

This is an extension point for TimedStack and is called with a mutex.

This method must shut down all connections on the stack.

[ GitHub ]

  
# File 'lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb', line 171

def shutdown_connections(options = nil)
  while connection_stored?(options)
    conn = fetch_connection(options)
    @created -= 1 unless @created == 0
    @shutdown_block.call(conn)
  end
end

#store_connection(obj, options = nil) (private)

This is an extension point for TimedStack and is called with a mutex.

This method must return obj to the stack.

[ GitHub ]

  
# File 'lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb', line 207

def store_connection(obj, options = nil)
  @que.push [obj, current_time]
end

#try_create(options = nil) (private)

This is an extension point for TimedStack and is called with a mutex.

This method must create a connection if and only if the total number of connections allowed has not been met.

[ GitHub ]

  
# File 'lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb', line 217

def try_create(options = nil)
  unless @created == @max
    object = @create_block.call
    @created += 1
    object
  end
end