Class: Dorm::ConnectionPool

Inherits:
Object
  • Object
show all
Includes:
MonitorMixin
Defined in:
lib/dorm/connection_pool.rb

Defined Under Namespace

Classes: ConnectionTimeoutError, PoolExhaustedError

Constant Summary collapse

Connection =
Data.define(:raw_connection, :created_at, :last_used_at) do
  def expired?(max_age)
    Time.now - created_at > max_age
  end

  def stale?(max_idle)
    Time.now - last_used_at > max_idle
  end

  def touch!
    with(last_used_at: Time.now)
  end
end

Instance Method Summary collapse

Constructor Details

#initialize(size: 5, timeout: 5, max_age: 3600, max_idle: 300, reap_frequency: 60) ⇒ ConnectionPool

Returns a new instance of ConnectionPool.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/dorm/connection_pool.rb', line 27

def initialize(
  size: 5,
  timeout: 5,
  max_age: 3600,    # 1 hour
  max_idle: 300,    # 5 minutes
  reap_frequency: 60 # 1 minute
)
  super()

  @size = size
  @timeout = timeout
  @max_age = max_age
  @max_idle = max_idle
  @reap_frequency = reap_frequency

  @available = []
  @connections = {}
  @connection_factory = nil
  @last_reap = Time.now

  start_reaper_thread if @reap_frequency > 0
end

Instance Method Details

#available_countObject



81
82
83
# File 'lib/dorm/connection_pool.rb', line 81

def available_count
  synchronize { @available.size }
end

#checked_out_countObject



85
86
87
# File 'lib/dorm/connection_pool.rb', line 85

def checked_out_count
  synchronize { @connections.size - @available.size }
end

#configure_factory(&block) ⇒ Object



50
51
52
# File 'lib/dorm/connection_pool.rb', line 50

def configure_factory(&block)
  @connection_factory = block
end

#disconnect!Object



89
90
91
92
93
94
95
96
97
# File 'lib/dorm/connection_pool.rb', line 89

def disconnect!
  synchronize do
    @connections.each_value do |conn|
      close_connection(conn)
    end
    @connections.clear
    @available.clear
  end
end

#reap_connections!Object

Manual cleanup of expired/stale connections



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/dorm/connection_pool.rb', line 100

def reap_connections!
  synchronize do
    stale_connections = @available.select do |conn|
      conn.expired?(@max_age) || conn.stale?(@max_idle)
    end

    stale_connections.each do |conn|
      @available.delete(conn)
      @connections.delete(conn.object_id)
      close_connection(conn)
    end

    @last_reap = Time.now
  end
end

#sizeObject



77
78
79
# File 'lib/dorm/connection_pool.rb', line 77

def size
  synchronize { @connections.size }
end

#with_connection(&block) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/dorm/connection_pool.rb', line 54

def with_connection(&block)
  connection = checkout_connection
  begin
    result = block.call(connection.raw_connection)
    result
  rescue StandardError => e
    # If connection is bad, don't return it to pool
    remove_connection(connection)
    raise
  ensure
    # Always try to check the connection back in (if it wasn't removed)
    if connection && @connections.key?(connection.object_id)
      updated_connection = connection.touch!
      synchronize do
        # Replace the connection in the hash with the updated version
        @connections[updated_connection.object_id] = updated_connection
        @connections.delete(connection.object_id) unless connection.equal?(updated_connection)
      end
      checkin_connection(updated_connection)
    end
  end
end