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

#checkin_with_last_checked_in(conn) ⇒ Object



179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 179

def checkin_with_last_checked_in(conn)
  begin
    if conn.last_checked_out
      previous_checkin, conn.last_checked_in = conn.last_checked_in, Time.now
      idle_manager.log_debug "checking in connection %s at %s (checked out for %.3f seconds)",
                             conn.object_id, conn.last_checked_in,
                             (conn.last_checked_in - conn.last_checked_out).to_f.round(6)
    else
      idle_manager.log_debug "checking in connection #{conn.object_id}"
    end
  ensure
    checkin_without_last_checked_in(conn)
  end
end

#idle_check_intervalObject



171
172
173
174
175
176
177
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 171

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

#idle_connectionsObject



203
204
205
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 203

def idle_connections
  @connections.select(&:idle?).sort
end

#initialize_with_advanced_connection(spec) ⇒ Object



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 132

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
    when :fifo, :queue   then Queues::FIFO.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(&:run)
end

#max_idle_connectionsObject



154
155
156
157
158
159
160
161
162
163
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 154

def max_idle_connections
  @max_idle_connections ||= begin
    begin
      spec.config.fetch(: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



165
166
167
168
169
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 165

def max_idle_time
  @max_idle_time ||= begin
    spec.config.fetch(:max_idle_time, AdvancedConnection.max_idle_time).to_i
  end
end

#pool_statisticsObject



194
195
196
197
198
199
200
201
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 194

def pool_statistics
  ActiveSupport::OrderedOptions.new.merge(
    total:     (total  = @connections.size),
    idle:      (idle   = @connections.count(&:idle?)),
    active:    (active = @connections.count(&:in_use?)),
    available: (total - active)
  )
end

#queue_typeObject



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

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

#remove_idle_connectionsObject



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/advanced_connection/active_record_ext/connection_pool/idle_manager.rb', line 207

def remove_idle_connections
  # don't attempt to remove idle connections if we have threads waiting
  if @available.num_waiting > 0
    idle_manager.log_warn "Skipping reap while #{@available.num_waiting} thread(s) are actively waiting on database connections..."
    return
  end

  return unless (candidates = idle_connections.size - max_idle_connections) > 0
  idle_manager.log_info "attempting to reap #{candidates} candidate connections"

  reaped = 0

  synchronize do
    idle_connections[0...candidates].each_with_index { |conn, idx|
      if remove_connection(conn)
        reaped += 1
        idle_manager.log_info "reaped candidate connection #%d id#%d age:%d idle:%d" % [
          idx, conn.object_id, conn.instance_age.to_i, conn.idle_time.to_i
        ]
      else
        idle_manager.log_info "kept candidate connection #%d id#%d age:%d idle:%d" % [
          idx, conn.object_id, conn.instance_age.to_i, conn.idle_time.to_i
        ]
      end
    }
  end

  idle_manager.log_info "reaped #{reaped} of #{candidates} candidate connections"
end