0

問題ドメイン

複数のデータベースを持つ 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 データベースを使用しています。

4

4 に答える 4

2

質問に対する私のコメントを拡張するには、「Heroku の方法」で DB の構成を追加し、そのキューでジョブを処理する 1 つのワーカーの Procfile でそれを参照することを意味しました。

新しい名前を使用して、必要な DB 構成で config/environment 変数を追加します。

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 に答える
0

更新: 機能していません。(元の回答は文書化のために保持されています)

これが私たちがそれを解決した方法です:

プロファイル:

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

lib/タスク/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 に答える