Module: AdvancedConnection::ActiveRecordExt::ConnectionPool::IdleManager

Extended by:
ActiveSupport::Concern
Defined in:
lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb

Instance Method Summary collapse

Instance Method Details

#active_connectionsObject



158
159
160
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 158

def active_connections
  @connections.select(&:in_use?)
end

#available_connectionsObject



162
163
164
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 162

def available_connections
  @connections.reject(&:in_use?)
end

#checkin_with_last_checked_in(conn) ⇒ Object



152
153
154
155
156
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 152

def checkin_with_last_checked_in(conn)
  conn.last_checked_in = Time.now
  idle_debug "checking in connection #{conn.object_id} at #{conn.last_checked_in}"
  checkin_without_last_checked_in(conn)
end

#connection_limitObject



148
149
150
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 148

def connection_limit
  @size
end

#create_idle_connectionsObject



225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 225

def create_idle_connections
  idle_count = idle_connections.size
  open_slots = connection_limit - @connections.size

  # if we already have enough idle connections, do nothing
  return unless idle_count < min_idle_connections

  # if we don't have enough available slots (i.e., current pool size
  # is greater than max pool size) then do nothing
  return unless open_slots > 0

  # otherwise, spin up connections up to our min_idle_connections setting
  create_count = min_idle_connections - idle_count
  create_count = open_slots if create_count > open_slots

  warmup_connections(create_count)
end

#idle_check_intervalObject



122
123
124
125
126
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 122

def idle_check_interval
  @idle_check_interval ||= (spec.config[:idle_check_interval] || \
                           AdvancedConnection.idle_check_interval || \
                           max_idle_time).to_i
end

#idle_connectionsObject



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 166

def idle_connections
  available_connections.select do |conn|
    (Time.now - conn.last_checked_in).to_f > max_idle_time
  end.sort { |a, b|
    case queue_type
      when :prefer_younger then
        # when prefering younger, we sort oldest->youngest
        # this ensures that older connections will be culled
        # during #remove_idle_connections()
        -(a.instance_age <=> b.instance_age)
      when :prefer_older then
        # when prefering older, we sort youngest->oldest
        # this ensures that younger connections will be culled
        # during #remove_idle_connections()
        (a.instance_age <=> b.instance_age)
      else
        # with fifo / lifo queues, we only care about the
        # last time a given connection was used (inferred
        # by when it was last checked into the pool).
        # This ensures that the longer idling connections
        # will be culled.
        -(a.last_checked_in <=> b.last_checked_in)
    end
  }
end

#initialize_with_advanced_connection(spec) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 90

def initialize_with_advanced_connection(spec)
  initialize_without_advanced_connection(spec)

  @available = case queue_type
    when :prefer_older   then Queues::OldAgeBiased.new
    when :prefer_younger then Queues::YoungAgeBiased.new
    when :lifo, :stack   then Queues::Stack.new
    else
      Rails.logger.warn "Unknown queue_type #{queue_type.inspect} - using standard FIFO instead"
      Queues::FIFO.new
  end

  @idle_manager = IdleManager.new(self, idle_check_interval).tap(&:start)
end

#max_idle_connectionsObject



128
129
130
131
132
133
134
135
136
137
138
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 128

def max_idle_connections
  @max_idle_connections ||= begin
    begin
      (spec.config[:max_idle_connections] || \
        AdvancedConnection.max_idle_connections).to_i
    rescue FloatDomainError => e
      raise unless e.message =~ /infinity/i
      ::Float::INFINITY
    end
  end
end

#max_idle_timeObject



117
118
119
120
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 117

def max_idle_time
  @max_idle_time ||= (spec.config[:max_idle_time] || \
                     AdvancedConnection.max_idle_time).to_i
end

#min_idle_connectionsObject



140
141
142
143
144
145
146
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 140

def min_idle_connections
  @min_idle_connections ||= begin
    min_idle = (spec.config[:min_idle_connections] || AdvancedConnection.min_idle_connections).to_i
    min_idle = (min_idle > 0 ? min_idle : 0)
    min_idle <= max_idle_connections ? min_idle : max_idle_connections
  end
end

#pool_statisticsObject



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 192

def pool_statistics
  idle = active = available = 0
  synchronize do
    idle      = idle_connections.size
    active    = active_connections.size
    available = available_connections.size
  end
  total = active + available

  ActiveSupport::OrderedOptions.new.merge(
    total:     total,
    idle:      idle,
    active:    active,
    available: available
  )
end

#queue_typeObject



105
106
107
108
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 105

def queue_type
  @queue_type ||= spec.config.fetch(:queue_type,
                                    AdvancedConnection.connection_pool_queue_type).to_s.downcase.to_sym
end

#remove_idle_connectionsObject



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 243

def remove_idle_connections
  # don't attempt to remove idle connections if we have threads waiting
  return if @available.num_waiting > 0

  idle_conns = idle_connections
  idle_count = idle_conns.size

  return unless idle_count > max_idle_connections

  cull_count = (idle_count - max_idle_connections)

  culled = 0
  idle_conns.each_with_index do |conn, idx|
    last_ci = (Time.now - conn.last_checked_in).to_f
    if idx < cull_count
      culled += remove_connection(conn) ? 1 : 0
      idle_info "culled connection ##{idx} id##{conn.object_id} - age:#{conn.instance_age} last_checkin:#{last_ci}"
    else
      idle_info "kept connection ##{idx} id##{conn.object_id} - age:#{conn.instance_age} last_checkin:#{last_ci}"
    end
  end

  idle_info "culled %d connections" % culled
end

#warmup_connection_countObject



110
111
112
113
114
115
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 110

def warmup_connection_count
  @warmup_connection_count ||= begin
    conns = spec.config[:warmup_connections] || AdvancedConnection.warmup_connections
    conns.to_i > connection_limit ? connection_limit : conns.to_i
  end
end

#warmup_connections(count = nil) ⇒ Object



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 209

def warmup_connections(count = nil)
  count ||= warmup_connection_count
  slots = connection_limit - @connections.size
  count = slots if slots < count

  return unless slots >= count

  idle_info "Warming up #{count} connection#{count > 1 ? 's' : ''}"
  synchronize do
    count.times {
      conn = checkout_new_connection
      @available.add conn
    }
  end
end