问题域
Heroku Cedar 堆栈,具有多个数据库。RDS 用于主数据库,Postgres 用于第二个 Analytics 数据库。服务器使用读/写 RDS和Postgres 数据库运行。Nightly rake 任务,在不同的环境中运行,需要在 RDS 数据库的只读从属中运行特定的 Resque 队列。
Postgres 数据库连接
作为记录,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
期望的能力
在 Procfile 中有这样的东西
troveworker: env RAILS_ENV=analytics QUEUE=trove_queue bundle exec rake resque:work
它实际上使用了该 worker 的分析 database.yml 配置。我们目前使用这个 Procfile 运行我们的服务器,但它仍然使用 RDS 数据库。