ActiveRecordのestablish_connectionを読んだ

ActiveRecordのestablish_connectionを読んだのでメモ

 

やっていることは、複数のConnectionPoolを管理するConnectionHandlerのインスタンス変数(Hash)のvalueにデータベースの接続情報などConnectionPoolの情報を管理するオブジェクトをセットして、ConnectionPoolのインスタンスを取り出せる状態をつくること。
これにより、複数のDBに接続する際に、ConnectionPoolがインスタンス変数を確認して、キーをもとに正しいConnectionPoolを提供できるようになる。

 

読んだときのメモ

ActiveRecord::Base.establish_connectionは

ActiveRecord::ConecctionHandling.establish_connectionを呼ぶ

この中でActiveRecord::ConnectionAdapters::ConnectionHandlerのestablish_connectionを呼ぶ

ConnectionHandlerは複数のConnectionPoolを管理している。

複数DBを使用する際に、DBごとにConnectionPoolを持ち、それらの複数のConnectionPoolをConnectionHandlerが管理する。

ConnectionHandler#establish_connectionの中で、
databaseのconfigをもとにConnectionAdapters::PoolConfigのインスタンスが生成される。

PoolConfigはインスタンス変数として、各connectionを識別するためのconnection_specification_nameを持ち、デフォルトだと'primary'になる。PoolConfigは他にもdb_configというインスタンス変数を持つ。これは、config/database.ymlで設定したHashなどが入る。
ConnectionPoolをまとめるConnectionHandlerのインスタンスは、owner_to_pool_managerをConcurrent::Mapで持つ。keyがPoolConfigのインスタンスのconnection_specification_name、valueがPoolManagerのインスタンス

establish_connectionの際に、valueが存在しなければ、新たにPoolManagerのインスタンスが作成される。
PoolManagerは、name_to_pool_configというHashを管理するためのClass。

キーには識別するための名前が入り(デフォルトで'default')、valueにPoolConfigが入る。

establish_connectionの中で、PoolManagerのname_to_pool_configもセットされる。

最後に、PoolConfigインスタンスのpoolメソッドが呼ばれる。

この中でConnectionPoolのインスタンスが生成される。

ConnectionPoolはインスタンス変数として、PoolConfigのインスタンスや、そのインスタンスのdb_configなどを持つ。

ConnectionPoolのinitializerの中で、ConnectionAdapters::ConnectionPool::Reaperのインスタンスが作成され、runメソッドが呼ばれる。
Reaperはpoolsとthreadsをインスタンス変数として持つ。poolsにはConnectionPoolのインスタンスが入る。threadsには、スレッドが入り、設定したfrequency秒間に一度生きているConnectionPoolのインスタンスに対してreapメソッドとflushメソッドを実行する。

ConnectionPoolのインスタンスがなくなれば、そのスレッドを終了させる。

ここでinitializeされたPoolConnectionのインスタンスは、PoolConfigのpoolで参照できる。