Spec-Zone.ru › Ruby on Rails 4.2

class ActiveRecord::ConnectionAdapters::ConnectionPool

Parent:
Object
Included modules:

Базовый класс пула соединений для управления базами данных Active Record.

Введение

Пул соединений синхронизирует доступ потоков к ограниченному числу соединений с базой данных. Основная идея заключается в том, что каждый поток запрашивает соединение из пула, использует его и возвращает в пул. ConnectionPool полностью потокобезопасен и гарантирует, что соединение не может использоваться двумя потоками одновременно, если соблюдаются условия контракта ConnectionPool. Он также обрабатывает случаи, когда количество потоков превышает количество соединений: если все соединения заняты, и поток пытается получить соединение, то ConnectionPool будет ожидать, пока другое соединение не будет возвращено.

Получение (извлечение) соединения

Соединения можно получить и использовать из пула несколькими способами:

  1. Просто используйте ActiveRecord::Base.connection, как в Active Record 2.1 и ранее (до пула соединений). Когда вы закончите работу с соединением(ями) и хотите вернуть его в пул, вызывайте ActiveRecord::Base.clear_active_connections!. Это будет поведением по умолчанию для Active Record при использовании в сочетании с обработкой запросов Action Pack.

  2. Вручную извлеките соединение из пула с помощью ActiveRecord::Base.connection_pool.checkout. Вы сами отвечаете за возврат этого соединения в пул после завершения работы, вызвав ActiveRecord::Base.connection_pool.checkin(connection).

  3. Используйте ActiveRecord::Base.connection_pool.with_connection(&block), который получает соединение, передает его как единственный аргумент блоку и возвращает его в пул после завершения блока.

Соединения в пуле фактически являются объектами AbstractAdapter (или объектами, совместимыми с интерфейсом AbstractAdapter).

Параметры

Существует несколько параметров, связанных с пулом соединений, которые вы можете добавить в конфигурацию подключения к базе данных:

  • pool: число, указывающее размер пула соединений (по умолчанию 5)

  • checkout_timeout: количество секунд ожидания соединения перед отказом и выбросом ошибки таймаута (по умолчанию 5 секунд).

  • reaping_frequency: частота в секундах для периодического запуска Reaper, который пытается найти и восстановить соединения из «мертвых» потоков, что может произойти, если программист забыл закрыть соединение в конце потока или поток неожиданно завершился. Независимо от этого параметра, Reaper будет вызван перед каждым блокирующим ожиданием. (По умолчанию nil, что означает, что Reaper не будет планироваться).

Атрибуты

automatic_reconnect[RW]
checkout_timeout[RW]
connections[R]
reaper[R]
size[R]
spec[R]

Методы публичного класса

new(spec) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 233
def initialize(spec)
  super()

  @spec = spec

  @checkout_timeout = (spec.config[:checkout_timeout] && spec.config[:checkout_timeout].to_f) || 5
  @reaper = Reaper.new(self, (spec.config[:reaping_frequency] && spec.config[:reaping_frequency].to_f))
  @reaper.run

  # default max pool size to 5
  @size = (spec.config[:pool] && spec.config[:pool].to_i) || 5

  # The cache of reserved connections mapped to threads
  @reserved_connections = ThreadSafe::Cache.new(:initial_capacity => @size)

  @connections         = []
  @automatic_reconnect = true

  @available = Queue.new self
end

Создает новый объект ConnectionPool. spec — это объект ConnectionSpecification, описывающий информацию о подключении к базе данных (например, адаптер, имя хоста, имя пользователя, пароль и т. д.), а также максимальный размер для этого объекта ConnectionPool.

По умолчанию максимальный размер объекта ConnectionPool равен 5.

Вызывает метод суперкласса

Методы публичного экземпляра

active_connection?() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 268
def active_connection?
  synchronize do
    @reserved_connections.fetch(current_connection_id) {
      return false
    }.in_use?
  end
end

Существует ли открытое подключение, используемое текущей нитью?

checkin(conn) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 360
def checkin(conn)
  synchronize do
    owner = conn.owner

    conn._run_checkin_callbacks do
      conn.expire
    end

    release conn, owner

    @available.add conn
  end
end

Возврат подключения к базе данных в пул, что означает, что вам больше не нужно это подключение.

conn: объект AbstractAdapter, полученный ранее с помощью вызова checkout для этого пула.

checkout() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 347
def checkout
  synchronize do
    conn = acquire_connection
    conn.lease
    checkout_and_verify(conn)
  end
end

Выдача подключения к базе данных из пула, что означает, что вы хотите его использовать. Вы должны вызвать checkin, когда вам больше не нужно это подключение.

Это выполняется либо путем возврата и предоставления существующего подключения, либо путем создания нового подключения и предоставления его.

Если все подключения выданы, и пул заполнен (т. е. число выданных подключений больше или равно предельному размеру), будет вызвано исключение ActiveRecord::ConnectionTimeoutError.

Возвращает: объект AbstractAdapter.

Возбуждает:

  • ConnectionTimeoutError: подключение не может быть получено из пула.

clear_reloadable_connections!() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 316
def clear_reloadable_connections!
  synchronize do
    @reserved_connections.clear
    @connections.each do |conn|
      checkin conn
      conn.disconnect! if conn.requires_reloading?
    end
    @connections.delete_if do |conn|
      conn.requires_reloading?
    end
    @available.clear
    @connections.each do |conn|
      @available.add conn
    end
  end
end

Очищает кэш, который сопоставляет классы.

connected?() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 298
def connected?
  synchronize { @connections.any? }
end

Возвращает true, если подключение уже открыто.

connection() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 259
def connection
  # this is correctly done double-checked locking
  # (ThreadSafe::Cache's lookups have volatile semantics)
  @reserved_connections[current_connection_id] || synchronize do
    @reserved_connections[current_connection_id] ||= checkout
  end
end

Получение подключения, связанного с текущей нитью, или вызов checkout для получения его, если необходимо.

connection может вызываться любое количество раз; подключение хранится в хэше, ключом которого является идентификатор нити.

disconnect!() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 303
def disconnect!
  synchronize do
    @reserved_connections.clear
    @connections.each do |conn|
      checkin conn
      conn.disconnect!
    end
    @connections = []
    @available.clear
  end
end

Отключает все подключения в пуле и очищает пул.

reap() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 390
def reap
  stale_connections = synchronize do
    @connections.select do |conn|
      conn.in_use? && !conn.owner.alive?
    end
  end

  stale_connections.each do |conn|
    synchronize do
      if conn.active?
        conn.reset!
        checkin conn
      else
        remove conn
      end
    end
  end
end

Восстановление потерянных подключений для пула. Потеря подключения может произойти, если программист забывает проверить подключение в конце нити или нить завершается неожиданно.

release_connection(with_id = current_connection_id) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 279
def release_connection(with_id = current_connection_id)
  synchronize do
    conn = @reserved_connections.delete(with_id)
    checkin conn if conn
  end
end

Сигнализирует, что нить завершила работу с текущим подключением. release_connection освобождает связь подключение-нить и возвращает подключение в пул.

remove(conn) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 376
def remove(conn)
  synchronize do
    @connections.delete conn
    @available.delete conn

    release conn, conn.owner

    @available.add checkout_new_connection if @available.any_waiting?
  end
end

Удаление подключения из пула подключений. Подключение останется открытым и активным, но больше не будет управляться этим пулом.

with_connection() { |connection| ... } Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 289
def with_connection
  connection_id = current_connection_id
  fresh_connection = true unless active_connection?
  yield connection
ensure
  release_connection(connection_id) if fresh_connection
end

Если подключение уже существует, передайте его в блок. Если подключение не существует, выдайте подключение, передайте его в блок и верните подключение в пул по завершении.

© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API