問題ドメイン
複数のデータベースを持つ Heroku Cedar スタック。メイン データベースには RDS、2 つ目の Analytics データベースには Postgres を使用します。サーバーは、読み取り/書き込みの RDSおよびPostgres データベースを使用して実行されます。別の環境で実行されるナイトリー rake タスクは、RDS データベースの読み取り専用スレーブで特定の Resque キューを実行する必要があります。
Postgres DB 接続
記録として、Postgres データベースのすべてのモデルには以下が含まれます。
module Trove::PostgresConnection
def self.included(base)
base.class_eval do
…set up Postgres database
end
end
end
これは問題なく動作し、各クラスに挿入されたモジュールであるため、ActiveRecord::Base.connection への変更によって押しつぶされることはありません。
MySQL 接続
Heroku RDS プラグインを使用して定義されます。読み取り/書き込み可能な本番データベースへの接続が確立されます。残念ながら、この接続は環境に関係なく使用されます。したがって、次を使用して Heroku で rake タスクを実行すると、RAILS_ENV=analytics rake some:task
この接続は使用されませんActiveRecord::Base
。
analytics:
adapter: mysql2
encoding: utf8
database: dbase
username: uname
password: pword
host: read-only.uri.on.amazonaws.com
reconnect: true
port: 3306
代わりに、RDS 接続で提供される接続文字列を使用します。
puts Rails.env
-> 'analytics'
puts SomeModel.connection_config[:host]
-> read-write.uri.on.amazonaws.com
それを理解するのにしばらく時間がかかりました。自分へのメモ: 環境だけを見るのではなく、データベース ホストを見てください。
現在の回避策
# Perform an operation using another database connection in ActiveRecord
module SwapConnection
def with_connection_to(config, &block)
ActiveRecord::Base.connection.disconnect!
ActiveRecord::Base.establish_connection(config)
yield
end
end
require 'swap_connection'
class TroveCalculations
@queue = :trove_queue
def self.perform(class_name, id)
SwapConnection.with_connection_to(Rails.env) do
Do something in a given queue
end
end
end
求める能力
Profileにこのようなものがあります
troveworker: env RAILS_ENV=analytics QUEUE=trove_queue bundle exec rake resque:work
実際には、その worker の分析 database.yml 構成を使用します。現在、この Procfile を使用してサーバーを実行していますが、依然として RDS データベースを使用しています。