class SSHKit::Backend::ConnectionPool::Cache

A Cache holds connections for a given key. Each connection is stored along with an expiration time so that its idle duration can be measured.

Attributes

closer[R]
connections[R]
idle_timeout[R]
key[RW]

Public Class Methods

new(key, idle_timeout, closer) click to toggle source
# File lib/sshkit/backends/connection_pool/cache.rb, line 6
def initialize(key, idle_timeout, closer)
  @key = key
  @connections = []
  @connections.extend(MonitorMixin)
  @idle_timeout = idle_timeout
  @closer = closer
end

Public Instance Methods

clear() click to toggle source

Close all connections and completely clear the cache.

# File lib/sshkit/backends/connection_pool/cache.rb, line 52
def clear
  connections.synchronize do
    connections.map(&:last).each(&closer)
    connections.clear
  end
end
evict() click to toggle source

Close and remove any connections in this Cache that have been idle for too long.

# File lib/sshkit/backends/connection_pool/cache.rb, line 36
def evict
  # Peek at the first connection to see if it is still fresh. If so, we can
  # return right away without needing to use `synchronize`.
  first_expires_at, first_conn = connections.first
  return if (first_expires_at.nil? || fresh?(first_expires_at)) && !closed?(first_conn)

  connections.synchronize do
    fresh, stale = connections.partition do |expires_at, conn|
      fresh?(expires_at) && !closed?(conn)
    end
    connections.replace(fresh)
    stale.each { |_, conn| closer.call(conn) }
  end
end
pop() click to toggle source

Remove and return a fresh connection from this Cache. Returns `nil` if the Cache is empty or if all existing connections have gone stale.

# File lib/sshkit/backends/connection_pool/cache.rb, line 16
def pop
  connections.synchronize do
    evict
    _, connection = connections.pop
    connection
  end
end
push(conn) click to toggle source

Return a connection to this Cache.

# File lib/sshkit/backends/connection_pool/cache.rb, line 25
def push(conn)
  # No need to cache if the connection has already been closed.
  return if closed?(conn)

  connections.synchronize do
    connections.push([Time.now + idle_timeout, conn])
  end
end
same_key?(other_key) click to toggle source
# File lib/sshkit/backends/connection_pool/cache.rb, line 59
def same_key?(other_key)
  key == other_key
end

Private Instance Methods

closed?(conn) click to toggle source
# File lib/sshkit/backends/connection_pool/cache.rb, line 73
def closed?(conn)
  return true if conn.respond_to?(:closed?) && conn.closed?
  # test if connection is alive
  conn.process(0) if conn.respond_to?(:process)
  return false
rescue IOError => e
  # connection is closed by server
  return true if e.message == 'closed stream'
  raise
end
fresh?(expires_at) click to toggle source
# File lib/sshkit/backends/connection_pool/cache.rb, line 69
def fresh?(expires_at)
  expires_at > Time.now
end