0

问题域

Heroku Cedar 堆栈,具有多个数据库。RDS 用于主数据库,Postgres 用于第二个 Analytics 数据库。服务器使用读/写 RDSPostgres 数据库运行。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 数据库。

4

4 回答 4

2

为了扩展我对这个问题的评论,我的意思是为你的数据库添加一个“Heroku 方式”的配置,然后在你的 Procfile 中为将处理该队列上的作业的一个工作人员引用它。

使用新名称添加您需要的数据库配置的配置/环境变量:

heroku config:add ANALYTICS_DB=postgres://some_url

在您的 中Procfile,根据您想要的示例:

troveworker:    env DATABASE_URL=$(ANALYTICS_DB) QUEUE=trove_queue \
                bundle exec rake resque:work

通过这种方式,您必须为每个队列使用不同的配置,但配置至少在代码之外。

于 2013-04-17T16:55:32.367 回答
1

这里的问题是 Heroku 生成自己的 database.yml 文件:https ://devcenter.heroku.com/articles/ruby-support#build-behavior

通过使用 Amazon RDS 插件,Heroku 设置了一个DATABASE_URL环境变量。您可以通过从应用程序目录的根目录运行以下命令来查看其内容: heroku config

此外,从 Rails 3.2 开始,它将使用DATABASE_URLenv var(如果已设置)而不是 database.yml 文件:

https://github.com/mperham/sidekiq/issues/503#issuecomment-11862427

最简单的解决方法可能是:

  1. 创建一个名为DATABASE_URL_ANALYTICSw/ Postgres 连接字符串的环境变量: heroku config:add DATABASE_URL_ANALYTICS=postgres://xxxxxxxxxxxx

  2. 在 rake 文件的开头(在任何 rails 初始化可能发生之前),添加: ENV['DATABASE_URL'] = ENV['DATABASE_URL_ANALYTICS'] if Rails.env.analytics?

于 2013-04-17T00:35:16.580 回答
1

我只玩过 Heroku,但我认为数据库连接信息被 Heroku 工具基于 Heroku 工具带指定的环境变量覆盖。

于 2013-04-16T22:57:56.143 回答
0

更新:不工作。(原始答案保留为文档)

这就是我们解决它的方法:

档案:

troveworker:    env RAILS_ENV=analytics QUEUE=trove_queue rake trove:worker

lib/tasks/trove.rake:

desc 'Start the Resque workers in the proper environment'
task :worker do
  SwapConnection.with_connection_to Rails.env do
    Rake::Task['resque:work'].invoke
  end
end

这个解决方案也为我们解决了一些其他问题,并且效果很好。感谢大家。

于 2013-05-03T15:58:02.827 回答